@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
|
||||
build/bin |
||||
node_modules |
||||
frontend/dist |
||||
@ -1,3 +1,19 @@
@@ -1,3 +1,19 @@
|
||||
# oemProject |
||||
# README |
||||
|
||||
一键打包生成oem项目exe |
||||
## About |
||||
|
||||
This is the official Wails Vue template. |
||||
|
||||
You can configure the project by editing `wails.json`. More information about the project settings can be found |
||||
here: https://wails.io/docs/reference/project-config |
||||
|
||||
## Live Development |
||||
|
||||
To run in live development mode, run `wails dev` in the project directory. This will run a Vite development |
||||
server that will provide very fast hot reload of your frontend changes. If you want to develop in a browser |
||||
and have access to your Go methods, there is also a dev server that runs on http://localhost:34115. Connect |
||||
to this in your browser, and you can call your Go code from devtools. |
||||
|
||||
## Building |
||||
|
||||
To build a redistributable, production mode package, use `wails build`. |
||||
|
||||
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
package main |
||||
|
||||
// App struct
|
||||
// type App struct {
|
||||
// ctx context.Context
|
||||
// }
|
||||
|
||||
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
# Build Directory |
||||
|
||||
The build directory is used to house all the build files and assets for your application. |
||||
|
||||
The structure is: |
||||
|
||||
* bin - Output directory |
||||
* darwin - macOS specific files |
||||
* windows - Windows specific files |
||||
|
||||
## Mac |
||||
|
||||
The `darwin` directory holds files specific to Mac builds. |
||||
These may be customised and used as part of the build. To return these files to the default state, simply delete them |
||||
and |
||||
build with `wails build`. |
||||
|
||||
The directory contains the following files: |
||||
|
||||
- `Info.plist` - the main plist file used for Mac builds. It is used when building using `wails build`. |
||||
- `Info.dev.plist` - same as the main plist file but used when building using `wails dev`. |
||||
|
||||
## Windows |
||||
|
||||
The `windows` directory contains the manifest and rc files used when building with `wails build`. |
||||
These may be customised for your application. To return these files to the default state, simply delete them and |
||||
build with `wails build`. |
||||
|
||||
- `icon.ico` - The icon used for the application. This is used when building using `wails build`. If you wish to |
||||
use a different icon, simply replace this file with your own. If it is missing, a new `icon.ico` file |
||||
will be created using the `appicon.png` file in the build directory. |
||||
- `installer/*` - The files used to create the Windows installer. These are used when building using `wails build`. |
||||
- `info.json` - Application details used for Windows builds. The data here will be used by the Windows installer, |
||||
as well as the application itself (right click the exe -> properties -> details) |
||||
- `wails.exe.manifest` - The main application manifest file. |
||||
|
After Width: | Height: | Size: 130 KiB |
@ -0,0 +1,68 @@
@@ -0,0 +1,68 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
||||
<plist version="1.0"> |
||||
<dict> |
||||
<key>CFBundlePackageType</key> |
||||
<string>APPL</string> |
||||
<key>CFBundleName</key> |
||||
<string>{{.Info.ProductName}}</string> |
||||
<key>CFBundleExecutable</key> |
||||
<string>{{.Name}}</string> |
||||
<key>CFBundleIdentifier</key> |
||||
<string>com.wails.{{.Name}}</string> |
||||
<key>CFBundleVersion</key> |
||||
<string>{{.Info.ProductVersion}}</string> |
||||
<key>CFBundleGetInfoString</key> |
||||
<string>{{.Info.Comments}}</string> |
||||
<key>CFBundleShortVersionString</key> |
||||
<string>{{.Info.ProductVersion}}</string> |
||||
<key>CFBundleIconFile</key> |
||||
<string>iconfile</string> |
||||
<key>LSMinimumSystemVersion</key> |
||||
<string>10.13.0</string> |
||||
<key>NSHighResolutionCapable</key> |
||||
<string>true</string> |
||||
<key>NSHumanReadableCopyright</key> |
||||
<string>{{.Info.Copyright}}</string> |
||||
{{if .Info.FileAssociations}} |
||||
<key>CFBundleDocumentTypes</key> |
||||
<array> |
||||
{{range .Info.FileAssociations}} |
||||
<dict> |
||||
<key>CFBundleTypeExtensions</key> |
||||
<array> |
||||
<string>{{.Ext}}</string> |
||||
</array> |
||||
<key>CFBundleTypeName</key> |
||||
<string>{{.Name}}</string> |
||||
<key>CFBundleTypeRole</key> |
||||
<string>{{.Role}}</string> |
||||
<key>CFBundleTypeIconFile</key> |
||||
<string>{{.IconName}}</string> |
||||
</dict> |
||||
{{end}} |
||||
</array> |
||||
{{end}} |
||||
{{if .Info.Protocols}} |
||||
<key>CFBundleURLTypes</key> |
||||
<array> |
||||
{{range .Info.Protocols}} |
||||
<dict> |
||||
<key>CFBundleURLName</key> |
||||
<string>com.wails.{{.Scheme}}</string> |
||||
<key>CFBundleURLSchemes</key> |
||||
<array> |
||||
<string>{{.Scheme}}</string> |
||||
</array> |
||||
<key>CFBundleTypeRole</key> |
||||
<string>{{.Role}}</string> |
||||
</dict> |
||||
{{end}} |
||||
</array> |
||||
{{end}} |
||||
<key>NSAppTransportSecurity</key> |
||||
<dict> |
||||
<key>NSAllowsLocalNetworking</key> |
||||
<true/> |
||||
</dict> |
||||
</dict> |
||||
</plist> |
||||
@ -0,0 +1,63 @@
@@ -0,0 +1,63 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
||||
<plist version="1.0"> |
||||
<dict> |
||||
<key>CFBundlePackageType</key> |
||||
<string>APPL</string> |
||||
<key>CFBundleName</key> |
||||
<string>{{.Info.ProductName}}</string> |
||||
<key>CFBundleExecutable</key> |
||||
<string>{{.Name}}</string> |
||||
<key>CFBundleIdentifier</key> |
||||
<string>com.wails.{{.Name}}</string> |
||||
<key>CFBundleVersion</key> |
||||
<string>{{.Info.ProductVersion}}</string> |
||||
<key>CFBundleGetInfoString</key> |
||||
<string>{{.Info.Comments}}</string> |
||||
<key>CFBundleShortVersionString</key> |
||||
<string>{{.Info.ProductVersion}}</string> |
||||
<key>CFBundleIconFile</key> |
||||
<string>iconfile</string> |
||||
<key>LSMinimumSystemVersion</key> |
||||
<string>10.13.0</string> |
||||
<key>NSHighResolutionCapable</key> |
||||
<string>true</string> |
||||
<key>NSHumanReadableCopyright</key> |
||||
<string>{{.Info.Copyright}}</string> |
||||
{{if .Info.FileAssociations}} |
||||
<key>CFBundleDocumentTypes</key> |
||||
<array> |
||||
{{range .Info.FileAssociations}} |
||||
<dict> |
||||
<key>CFBundleTypeExtensions</key> |
||||
<array> |
||||
<string>{{.Ext}}</string> |
||||
</array> |
||||
<key>CFBundleTypeName</key> |
||||
<string>{{.Name}}</string> |
||||
<key>CFBundleTypeRole</key> |
||||
<string>{{.Role}}</string> |
||||
<key>CFBundleTypeIconFile</key> |
||||
<string>{{.IconName}}</string> |
||||
</dict> |
||||
{{end}} |
||||
</array> |
||||
{{end}} |
||||
{{if .Info.Protocols}} |
||||
<key>CFBundleURLTypes</key> |
||||
<array> |
||||
{{range .Info.Protocols}} |
||||
<dict> |
||||
<key>CFBundleURLName</key> |
||||
<string>com.wails.{{.Scheme}}</string> |
||||
<key>CFBundleURLSchemes</key> |
||||
<array> |
||||
<string>{{.Scheme}}</string> |
||||
</array> |
||||
<key>CFBundleTypeRole</key> |
||||
<string>{{.Role}}</string> |
||||
</dict> |
||||
{{end}} |
||||
</array> |
||||
{{end}} |
||||
</dict> |
||||
</plist> |
||||
|
After Width: | Height: | Size: 20 KiB |
@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
|
||||
{ |
||||
"fixed": { |
||||
"file_version": "{{.Info.ProductVersion}}" |
||||
}, |
||||
"info": { |
||||
"0000": { |
||||
"ProductVersion": "{{.Info.ProductVersion}}", |
||||
"CompanyName": "{{.Info.CompanyName}}", |
||||
"FileDescription": "{{.Info.ProductName}}", |
||||
"LegalCopyright": "{{.Info.Copyright}}", |
||||
"ProductName": "{{.Info.ProductName}}", |
||||
"Comments": "{{.Info.Comments}}" |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,114 @@
@@ -0,0 +1,114 @@
|
||||
Unicode true |
||||
|
||||
#### |
||||
## Please note: Template replacements don't work in this file. They are provided with default defines like |
||||
## mentioned underneath. |
||||
## If the keyword is not defined, "wails_tools.nsh" will populate them with the values from ProjectInfo. |
||||
## If they are defined here, "wails_tools.nsh" will not touch them. This allows to use this project.nsi manually |
||||
## from outside of Wails for debugging and development of the installer. |
||||
## |
||||
## For development first make a wails nsis build to populate the "wails_tools.nsh": |
||||
## > wails build --target windows/amd64 --nsis |
||||
## Then you can call makensis on this file with specifying the path to your binary: |
||||
## For a AMD64 only installer: |
||||
## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app.exe |
||||
## For a ARM64 only installer: |
||||
## > makensis -DARG_WAILS_ARM64_BINARY=..\..\bin\app.exe |
||||
## For a installer with both architectures: |
||||
## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app-amd64.exe -DARG_WAILS_ARM64_BINARY=..\..\bin\app-arm64.exe |
||||
#### |
||||
## The following information is taken from the ProjectInfo file, but they can be overwritten here. |
||||
#### |
||||
## !define INFO_PROJECTNAME "MyProject" # Default "{{.Name}}" |
||||
## !define INFO_COMPANYNAME "MyCompany" # Default "{{.Info.CompanyName}}" |
||||
## !define INFO_PRODUCTNAME "MyProduct" # Default "{{.Info.ProductName}}" |
||||
## !define INFO_PRODUCTVERSION "1.0.0" # Default "{{.Info.ProductVersion}}" |
||||
## !define INFO_COPYRIGHT "Copyright" # Default "{{.Info.Copyright}}" |
||||
### |
||||
## !define PRODUCT_EXECUTABLE "Application.exe" # Default "${INFO_PROJECTNAME}.exe" |
||||
## !define UNINST_KEY_NAME "UninstKeyInRegistry" # Default "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" |
||||
#### |
||||
## !define REQUEST_EXECUTION_LEVEL "admin" # Default "admin" see also https://nsis.sourceforge.io/Docs/Chapter4.html |
||||
#### |
||||
## Include the wails tools |
||||
#### |
||||
!include "wails_tools.nsh" |
||||
|
||||
# The version information for this two must consist of 4 parts |
||||
VIProductVersion "${INFO_PRODUCTVERSION}.0" |
||||
VIFileVersion "${INFO_PRODUCTVERSION}.0" |
||||
|
||||
VIAddVersionKey "CompanyName" "${INFO_COMPANYNAME}" |
||||
VIAddVersionKey "FileDescription" "${INFO_PRODUCTNAME} Installer" |
||||
VIAddVersionKey "ProductVersion" "${INFO_PRODUCTVERSION}" |
||||
VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}" |
||||
VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}" |
||||
VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}" |
||||
|
||||
# Enable HiDPI support. https://nsis.sourceforge.io/Reference/ManifestDPIAware |
||||
ManifestDPIAware true |
||||
|
||||
!include "MUI.nsh" |
||||
|
||||
!define MUI_ICON "..\icon.ico" |
||||
!define MUI_UNICON "..\icon.ico" |
||||
# !define MUI_WELCOMEFINISHPAGE_BITMAP "resources\leftimage.bmp" #Include this to add a bitmap on the left side of the Welcome Page. Must be a size of 164x314 |
||||
!define MUI_FINISHPAGE_NOAUTOCLOSE # Wait on the INSTFILES page so the user can take a look into the details of the installation steps |
||||
!define MUI_ABORTWARNING # This will warn the user if they exit from the installer. |
||||
|
||||
!insertmacro MUI_PAGE_WELCOME # Welcome to the installer page. |
||||
# !insertmacro MUI_PAGE_LICENSE "resources\eula.txt" # Adds a EULA page to the installer |
||||
!insertmacro MUI_PAGE_DIRECTORY # In which folder install page. |
||||
!insertmacro MUI_PAGE_INSTFILES # Installing page. |
||||
!insertmacro MUI_PAGE_FINISH # Finished installation page. |
||||
|
||||
!insertmacro MUI_UNPAGE_INSTFILES # Uinstalling page |
||||
|
||||
!insertmacro MUI_LANGUAGE "English" # Set the Language of the installer |
||||
|
||||
## The following two statements can be used to sign the installer and the uninstaller. The path to the binaries are provided in %1 |
||||
#!uninstfinalize 'signtool --file "%1"' |
||||
#!finalize 'signtool --file "%1"' |
||||
|
||||
Name "${INFO_PRODUCTNAME}" |
||||
OutFile "..\..\bin\${INFO_PROJECTNAME}-${ARCH}-installer.exe" # Name of the installer's file. |
||||
InstallDir "$PROGRAMFILES64\${INFO_COMPANYNAME}\${INFO_PRODUCTNAME}" # Default installing folder ($PROGRAMFILES is Program Files folder). |
||||
ShowInstDetails show # This will always show the installation details. |
||||
|
||||
Function .onInit |
||||
!insertmacro wails.checkArchitecture |
||||
FunctionEnd |
||||
|
||||
Section |
||||
!insertmacro wails.setShellContext |
||||
|
||||
!insertmacro wails.webview2runtime |
||||
|
||||
SetOutPath $INSTDIR |
||||
|
||||
!insertmacro wails.files |
||||
|
||||
CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" |
||||
CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" |
||||
|
||||
!insertmacro wails.associateFiles |
||||
!insertmacro wails.associateCustomProtocols |
||||
|
||||
!insertmacro wails.writeUninstaller |
||||
SectionEnd |
||||
|
||||
Section "uninstall" |
||||
!insertmacro wails.setShellContext |
||||
|
||||
RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath |
||||
|
||||
RMDir /r $INSTDIR |
||||
|
||||
Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" |
||||
Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk" |
||||
|
||||
!insertmacro wails.unassociateFiles |
||||
!insertmacro wails.unassociateCustomProtocols |
||||
|
||||
!insertmacro wails.deleteUninstaller |
||||
SectionEnd |
||||
@ -0,0 +1,249 @@
@@ -0,0 +1,249 @@
|
||||
# DO NOT EDIT - Generated automatically by `wails build` |
||||
|
||||
!include "x64.nsh" |
||||
!include "WinVer.nsh" |
||||
!include "FileFunc.nsh" |
||||
|
||||
!ifndef INFO_PROJECTNAME |
||||
!define INFO_PROJECTNAME "{{.Name}}" |
||||
!endif |
||||
!ifndef INFO_COMPANYNAME |
||||
!define INFO_COMPANYNAME "{{.Info.CompanyName}}" |
||||
!endif |
||||
!ifndef INFO_PRODUCTNAME |
||||
!define INFO_PRODUCTNAME "{{.Info.ProductName}}" |
||||
!endif |
||||
!ifndef INFO_PRODUCTVERSION |
||||
!define INFO_PRODUCTVERSION "{{.Info.ProductVersion}}" |
||||
!endif |
||||
!ifndef INFO_COPYRIGHT |
||||
!define INFO_COPYRIGHT "{{.Info.Copyright}}" |
||||
!endif |
||||
!ifndef PRODUCT_EXECUTABLE |
||||
!define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe" |
||||
!endif |
||||
!ifndef UNINST_KEY_NAME |
||||
!define UNINST_KEY_NAME "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" |
||||
!endif |
||||
!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINST_KEY_NAME}" |
||||
|
||||
!ifndef REQUEST_EXECUTION_LEVEL |
||||
!define REQUEST_EXECUTION_LEVEL "admin" |
||||
!endif |
||||
|
||||
RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}" |
||||
|
||||
!ifdef ARG_WAILS_AMD64_BINARY |
||||
!define SUPPORTS_AMD64 |
||||
!endif |
||||
|
||||
!ifdef ARG_WAILS_ARM64_BINARY |
||||
!define SUPPORTS_ARM64 |
||||
!endif |
||||
|
||||
!ifdef SUPPORTS_AMD64 |
||||
!ifdef SUPPORTS_ARM64 |
||||
!define ARCH "amd64_arm64" |
||||
!else |
||||
!define ARCH "amd64" |
||||
!endif |
||||
!else |
||||
!ifdef SUPPORTS_ARM64 |
||||
!define ARCH "arm64" |
||||
!else |
||||
!error "Wails: Undefined ARCH, please provide at least one of ARG_WAILS_AMD64_BINARY or ARG_WAILS_ARM64_BINARY" |
||||
!endif |
||||
!endif |
||||
|
||||
!macro wails.checkArchitecture |
||||
!ifndef WAILS_WIN10_REQUIRED |
||||
!define WAILS_WIN10_REQUIRED "This product is only supported on Windows 10 (Server 2016) and later." |
||||
!endif |
||||
|
||||
!ifndef WAILS_ARCHITECTURE_NOT_SUPPORTED |
||||
!define WAILS_ARCHITECTURE_NOT_SUPPORTED "This product can't be installed on the current Windows architecture. Supports: ${ARCH}" |
||||
!endif |
||||
|
||||
${If} ${AtLeastWin10} |
||||
!ifdef SUPPORTS_AMD64 |
||||
${if} ${IsNativeAMD64} |
||||
Goto ok |
||||
${EndIf} |
||||
!endif |
||||
|
||||
!ifdef SUPPORTS_ARM64 |
||||
${if} ${IsNativeARM64} |
||||
Goto ok |
||||
${EndIf} |
||||
!endif |
||||
|
||||
IfSilent silentArch notSilentArch |
||||
silentArch: |
||||
SetErrorLevel 65 |
||||
Abort |
||||
notSilentArch: |
||||
MessageBox MB_OK "${WAILS_ARCHITECTURE_NOT_SUPPORTED}" |
||||
Quit |
||||
${else} |
||||
IfSilent silentWin notSilentWin |
||||
silentWin: |
||||
SetErrorLevel 64 |
||||
Abort |
||||
notSilentWin: |
||||
MessageBox MB_OK "${WAILS_WIN10_REQUIRED}" |
||||
Quit |
||||
${EndIf} |
||||
|
||||
ok: |
||||
!macroend |
||||
|
||||
!macro wails.files |
||||
!ifdef SUPPORTS_AMD64 |
||||
${if} ${IsNativeAMD64} |
||||
File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_AMD64_BINARY}" |
||||
${EndIf} |
||||
!endif |
||||
|
||||
!ifdef SUPPORTS_ARM64 |
||||
${if} ${IsNativeARM64} |
||||
File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_ARM64_BINARY}" |
||||
${EndIf} |
||||
!endif |
||||
!macroend |
||||
|
||||
!macro wails.writeUninstaller |
||||
WriteUninstaller "$INSTDIR\uninstall.exe" |
||||
|
||||
SetRegView 64 |
||||
WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${INFO_COMPANYNAME}" |
||||
WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${INFO_PRODUCTNAME}" |
||||
WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${INFO_PRODUCTVERSION}" |
||||
WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_EXECUTABLE}" |
||||
WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" |
||||
WriteRegStr HKLM "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" |
||||
|
||||
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 |
||||
IntFmt $0 "0x%08X" $0 |
||||
WriteRegDWORD HKLM "${UNINST_KEY}" "EstimatedSize" "$0" |
||||
!macroend |
||||
|
||||
!macro wails.deleteUninstaller |
||||
Delete "$INSTDIR\uninstall.exe" |
||||
|
||||
SetRegView 64 |
||||
DeleteRegKey HKLM "${UNINST_KEY}" |
||||
!macroend |
||||
|
||||
!macro wails.setShellContext |
||||
${If} ${REQUEST_EXECUTION_LEVEL} == "admin" |
||||
SetShellVarContext all |
||||
${else} |
||||
SetShellVarContext current |
||||
${EndIf} |
||||
!macroend |
||||
|
||||
# Install webview2 by launching the bootstrapper |
||||
# See https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#online-only-deployment |
||||
!macro wails.webview2runtime |
||||
!ifndef WAILS_INSTALL_WEBVIEW_DETAILPRINT |
||||
!define WAILS_INSTALL_WEBVIEW_DETAILPRINT "Installing: WebView2 Runtime" |
||||
!endif |
||||
|
||||
SetRegView 64 |
||||
# If the admin key exists and is not empty then webview2 is already installed |
||||
ReadRegStr $0 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" |
||||
${If} $0 != "" |
||||
Goto ok |
||||
${EndIf} |
||||
|
||||
${If} ${REQUEST_EXECUTION_LEVEL} == "user" |
||||
# If the installer is run in user level, check the user specific key exists and is not empty then webview2 is already installed |
||||
ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" |
||||
${If} $0 != "" |
||||
Goto ok |
||||
${EndIf} |
||||
${EndIf} |
||||
|
||||
SetDetailsPrint both |
||||
DetailPrint "${WAILS_INSTALL_WEBVIEW_DETAILPRINT}" |
||||
SetDetailsPrint listonly |
||||
|
||||
InitPluginsDir |
||||
CreateDirectory "$pluginsdir\webview2bootstrapper" |
||||
SetOutPath "$pluginsdir\webview2bootstrapper" |
||||
File "tmp\MicrosoftEdgeWebview2Setup.exe" |
||||
ExecWait '"$pluginsdir\webview2bootstrapper\MicrosoftEdgeWebview2Setup.exe" /silent /install' |
||||
|
||||
SetDetailsPrint both |
||||
ok: |
||||
!macroend |
||||
|
||||
# Copy of APP_ASSOCIATE and APP_UNASSOCIATE macros from here https://gist.github.com/nikku/281d0ef126dbc215dd58bfd5b3a5cd5b |
||||
!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND |
||||
; Backup the previously associated file class |
||||
ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" "" |
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0" |
||||
|
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}" |
||||
|
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}` |
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}` |
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" "open" |
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open" "" `${COMMANDTEXT}` |
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open\command" "" `${COMMAND}` |
||||
!macroend |
||||
|
||||
!macro APP_UNASSOCIATE EXT FILECLASS |
||||
; Backup the previously associated file class |
||||
ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" `${FILECLASS}_backup` |
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "$R0" |
||||
|
||||
DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}` |
||||
!macroend |
||||
|
||||
!macro wails.associateFiles |
||||
; Create file associations |
||||
{{range .Info.FileAssociations}} |
||||
!insertmacro APP_ASSOCIATE "{{.Ext}}" "{{.Name}}" "{{.Description}}" "$INSTDIR\{{.IconName}}.ico" "Open with ${INFO_PRODUCTNAME}" "$INSTDIR\${PRODUCT_EXECUTABLE} $\"%1$\"" |
||||
|
||||
File "..\{{.IconName}}.ico" |
||||
{{end}} |
||||
!macroend |
||||
|
||||
!macro wails.unassociateFiles |
||||
; Delete app associations |
||||
{{range .Info.FileAssociations}} |
||||
!insertmacro APP_UNASSOCIATE "{{.Ext}}" "{{.Name}}" |
||||
|
||||
Delete "$INSTDIR\{{.IconName}}.ico" |
||||
{{end}} |
||||
!macroend |
||||
|
||||
!macro CUSTOM_PROTOCOL_ASSOCIATE PROTOCOL DESCRIPTION ICON COMMAND |
||||
DeleteRegKey SHELL_CONTEXT "Software\Classes\${PROTOCOL}" |
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}" "" "${DESCRIPTION}" |
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}" "URL Protocol" "" |
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\DefaultIcon" "" "${ICON}" |
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell" "" "" |
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell\open" "" "" |
||||
WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell\open\command" "" "${COMMAND}" |
||||
!macroend |
||||
|
||||
!macro CUSTOM_PROTOCOL_UNASSOCIATE PROTOCOL |
||||
DeleteRegKey SHELL_CONTEXT "Software\Classes\${PROTOCOL}" |
||||
!macroend |
||||
|
||||
!macro wails.associateCustomProtocols |
||||
; Create custom protocols associations |
||||
{{range .Info.Protocols}} |
||||
!insertmacro CUSTOM_PROTOCOL_ASSOCIATE "{{.Scheme}}" "{{.Description}}" "$INSTDIR\${PRODUCT_EXECUTABLE},0" "$INSTDIR\${PRODUCT_EXECUTABLE} $\"%1$\"" |
||||
|
||||
{{end}} |
||||
!macroend |
||||
|
||||
!macro wails.unassociateCustomProtocols |
||||
; Delete app custom protocol associations |
||||
{{range .Info.Protocols}} |
||||
!insertmacro CUSTOM_PROTOCOL_UNASSOCIATE "{{.Scheme}}" |
||||
{{end}} |
||||
!macroend |
||||
@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> |
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3"> |
||||
<assemblyIdentity type="win32" name="com.wails.{{.Name}}" version="{{.Info.ProductVersion}}.0" processorArchitecture="*"/> |
||||
<dependency> |
||||
<dependentAssembly> |
||||
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/> |
||||
</dependentAssembly> |
||||
</dependency> |
||||
<asmv3:application> |
||||
<asmv3:windowsSettings> |
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware> <!-- fallback for Windows 7 and 8 --> |
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">permonitorv2,permonitor</dpiAwareness> <!-- falls back to per-monitor if per-monitor v2 is not supported --> |
||||
</asmv3:windowsSettings> |
||||
</asmv3:application> |
||||
</assembly> |
||||
@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
|
||||
# Vue 3 + Vite |
||||
|
||||
This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, |
||||
check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more. |
||||
|
||||
## Recommended IDE Setup |
||||
|
||||
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) |
||||
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<meta charset="UTF-8"/> |
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/> |
||||
<title>testWails</title> |
||||
</head> |
||||
<body> |
||||
<div id="app"></div> |
||||
<script src="./src/main.js" type="module"></script> |
||||
</body> |
||||
</html> |
||||
|
||||
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
{ |
||||
"name": "frontend", |
||||
"private": true, |
||||
"version": "0.0.0", |
||||
"type": "module", |
||||
"scripts": { |
||||
"dev": "vite", |
||||
"build": "vite build", |
||||
"preview": "vite preview" |
||||
}, |
||||
"dependencies": { |
||||
"vue": "^3.2.37" |
||||
}, |
||||
"devDependencies": { |
||||
"@vitejs/plugin-vue": "^3.0.3", |
||||
"vite": "^3.0.7" |
||||
} |
||||
} |
||||
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
21d2a2199c4fb87865d8160b492f51c3 |
||||
@ -0,0 +1,50 @@
@@ -0,0 +1,50 @@
|
||||
{ |
||||
"server": { |
||||
"debug": true, |
||||
"http_debug": false, |
||||
"http_demo": true, |
||||
"http_dir": "web", |
||||
"http_login": "demo", |
||||
"http_password": "demo", |
||||
"http_port": ":8083", |
||||
"https": false, |
||||
"https_auto_tls": false, |
||||
"https_auto_tls_name": "", |
||||
"https_cert": "server.crt", |
||||
"https_key": "server.key", |
||||
"https_port": ":443", |
||||
"ice_servers": ["stun:stun.l.google.com:193022"], |
||||
"log_level": "debug", |
||||
"rtsp_port": ":5541", |
||||
"token": { |
||||
"backend": "http://127.0.0.1/test.php" |
||||
}, |
||||
"defaults": { |
||||
"audio": true |
||||
} |
||||
}, |
||||
"streams": { |
||||
"dahua108": { |
||||
"channels": { |
||||
"0": { |
||||
"url": "rtsp://admin:@Sua123sua@192.168.88.7:554/h264/ch1/sub/av_stream", |
||||
"debug": false, |
||||
"on_demand": false, |
||||
"audio": true |
||||
} |
||||
}, |
||||
"name": "dahua" |
||||
}, |
||||
"dahua107": { |
||||
"channels": { |
||||
"0": { |
||||
"url": "rtsp://admin:@Sua123sua@192.168.88.7:554/stream2&channel=2", |
||||
"debug": false, |
||||
"on_demand": false, |
||||
"audio": true |
||||
} |
||||
}, |
||||
"name": "dahua" |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,163 @@
@@ -0,0 +1,163 @@
|
||||
.grid-wrapper{ |
||||
height: calc(100vh - 30px); |
||||
margin: 0px; |
||||
background: transparent; |
||||
display: flex; |
||||
flex-wrap: wrap; |
||||
} |
||||
.layout-top-nav .wrapper .main-header { |
||||
margin-left: 0; |
||||
height: 30px; |
||||
} |
||||
video.background{ |
||||
pointer-events: none; |
||||
position: absolute; |
||||
top:0; |
||||
left: 0; |
||||
width: 100%; |
||||
height: 100%; |
||||
object-fit: cover; |
||||
} |
||||
.control-sidebar.custom{ |
||||
background: black; |
||||
height: 100%; |
||||
margin-top: -57px; |
||||
padding: 30px 8px 8px; |
||||
background: linear-gradient(45deg, black, transparent); |
||||
overflow: hidden; |
||||
} |
||||
.control-sidebar.custom .row{ |
||||
height:100%; |
||||
overflow: auto; |
||||
} |
||||
.control-sidebar.custom>h5{ |
||||
color: white; |
||||
text-align: center; |
||||
} |
||||
|
||||
.grid-wrapper .player video.video-class { |
||||
background: #000; |
||||
object-fit: fill; |
||||
} |
||||
.grid-wrapper .player video.video-class.empty { |
||||
background: transparent; |
||||
} |
||||
|
||||
.img-background{ |
||||
/* background: url(/../static/img/back.jpg); */ |
||||
background-color: #343a40; |
||||
background-position: center; |
||||
background-repeat: no-repeat; |
||||
background-size: cover; |
||||
backdrop-filter: sepia(0.5) grayscale(0.4); |
||||
} |
||||
.img-background .content-wrapper{ |
||||
background: transparent; |
||||
} |
||||
.img-background .main-header{ |
||||
background: |
||||
} |
||||
.grid-wrapper .player { |
||||
|
||||
padding: 0px; |
||||
border: 2px solid #000; |
||||
} |
||||
|
||||
.grid-wrapper .player .remove-btn{ |
||||
color:white; |
||||
display: none; |
||||
position: absolute; |
||||
right: 0px; |
||||
top: 0px; |
||||
cursor: pointer; |
||||
padding: 5px 10px; |
||||
border-radius: 50px; |
||||
filter: drop-shadow(1px 1px 1px black); |
||||
} |
||||
.grid-wrapper .player.empty .remove-btn{ |
||||
display: none; |
||||
} |
||||
.grid-wrapper .player:not(.empty):hover .remove-btn{ |
||||
display: block; |
||||
} |
||||
|
||||
.grid-wrapper .player .add-stream-btn{ |
||||
position: absolute; |
||||
left: 0; |
||||
top: calc(50% - 2vw); |
||||
text-align: center; |
||||
width: 100%; |
||||
font-variant-caps: all-petite-caps; |
||||
font-size: 1.5vw; |
||||
line-height: 1; |
||||
color: white; |
||||
cursor: pointer; |
||||
display: none; |
||||
filter: drop-shadow(2px 4px 6px black); |
||||
} |
||||
.grid-wrapper .player.empty .add-stream-btn{ |
||||
display: block; |
||||
|
||||
} |
||||
|
||||
.carousel-caption { |
||||
pointer-events: none; |
||||
filter: drop-shadow(1px 1px 1px black); |
||||
} |
||||
.stream-img{ |
||||
height: 150px; |
||||
} |
||||
.player .loader, .main-player .loader{ |
||||
position: absolute; |
||||
width: 100px; |
||||
height: 70px; |
||||
top: calc(50% - 35px); |
||||
left: calc(50% - 50px); |
||||
} |
||||
.control-sidebar-close-btn{ |
||||
position: absolute; |
||||
top: 37px; |
||||
right: 12px; |
||||
color: #fff; |
||||
} |
||||
.control-sidebar-close-btn:hover{ |
||||
color: #999; |
||||
} |
||||
.dropdown-menu.custom-dropdown.show{ |
||||
color: #ffF; |
||||
border: 1px solid #343a40; |
||||
background: linear-gradient(45deg, #000000d1 30%,#343a40); |
||||
padding: 0; |
||||
text-align: center; |
||||
} |
||||
|
||||
.dropdown-menu.custom-dropdown .custom-dropdown-item{ |
||||
float: left; |
||||
width: 33%; |
||||
padding: 10px; |
||||
font-size: 12px; |
||||
cursor: pointer; |
||||
} |
||||
.dropdown-menu.custom-dropdown .custom-dropdown-item.active,.dropdown-menu.custom-dropdown .custom-dropdown-item:hover{ |
||||
border-radius: 5px; |
||||
box-shadow: inset 0px 0px 15px -5px; |
||||
} |
||||
.dropdown-menu.custom-dropdown .dropdown-item{ |
||||
color: #fff; |
||||
|
||||
} |
||||
.dropdown-menu.custom-dropdown .dropdown-item:hover{ |
||||
box-shadow: inset 0px 0px 15px -5px; |
||||
background: transparent; |
||||
} |
||||
|
||||
.custom-dropdown-item.with-img{ |
||||
width: 50%!important; |
||||
height: auto; |
||||
padding: 2px!important; |
||||
|
||||
} |
||||
.custom-dropdown-item.with-img img{ |
||||
width: 100%; |
||||
height: auto; |
||||
} |
||||
@ -0,0 +1,224 @@
@@ -0,0 +1,224 @@
|
||||
/* cyrillic-ext */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: italic; |
||||
font-weight: 400; |
||||
src: url(fonts/6xK1dSBYKcSV-LCoeQqfX1RYOo3qPZ7qsDJB9cme_xc.woff2) format('woff2'); |
||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; |
||||
} |
||||
/* cyrillic */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: italic; |
||||
font-weight: 400; |
||||
src: url(fonts/6xK1dSBYKcSV-LCoeQqfX1RYOo3qPZ7jsDJB9cme_xc.woff2) format('woff2'); |
||||
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; |
||||
} |
||||
/* greek-ext */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: italic; |
||||
font-weight: 400; |
||||
src: url(fonts/6xK1dSBYKcSV-LCoeQqfX1RYOo3qPZ7rsDJB9cme_xc.woff2) format('woff2'); |
||||
unicode-range: U+1F00-1FFF; |
||||
} |
||||
/* greek */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: italic; |
||||
font-weight: 400; |
||||
src: url(fonts/6xK1dSBYKcSV-LCoeQqfX1RYOo3qPZ7ksDJB9cme_xc.woff2) format('woff2'); |
||||
unicode-range: U+0370-03FF; |
||||
} |
||||
/* vietnamese */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: italic; |
||||
font-weight: 400; |
||||
src: url(fonts/6xK1dSBYKcSV-LCoeQqfX1RYOo3qPZ7osDJB9cme_xc.woff2) format('woff2'); |
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; |
||||
} |
||||
/* latin-ext */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: italic; |
||||
font-weight: 400; |
||||
src: url(fonts/6xK1dSBYKcSV-LCoeQqfX1RYOo3qPZ7psDJB9cme_xc.woff2) format('woff2'); |
||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; |
||||
} |
||||
/* latin */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: italic; |
||||
font-weight: 400; |
||||
src: url(fonts/6xK1dSBYKcSV-LCoeQqfX1RYOo3qPZ7nsDJB9cme.woff2) format('woff2'); |
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; |
||||
} |
||||
/* cyrillic-ext */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: normal; |
||||
font-weight: 300; |
||||
src: url(fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zwmhdu3cOWxy40.woff2) format('woff2'); |
||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; |
||||
} |
||||
/* cyrillic */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: normal; |
||||
font-weight: 300; |
||||
src: url(fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zwkxdu3cOWxy40.woff2) format('woff2'); |
||||
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; |
||||
} |
||||
/* greek-ext */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: normal; |
||||
font-weight: 300; |
||||
src: url(fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zwmxdu3cOWxy40.woff2) format('woff2'); |
||||
unicode-range: U+1F00-1FFF; |
||||
} |
||||
/* greek */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: normal; |
||||
font-weight: 300; |
||||
src: url(fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zwlBdu3cOWxy40.woff2) format('woff2'); |
||||
unicode-range: U+0370-03FF; |
||||
} |
||||
/* vietnamese */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: normal; |
||||
font-weight: 300; |
||||
src: url(fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zwmBdu3cOWxy40.woff2) format('woff2'); |
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; |
||||
} |
||||
/* latin-ext */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: normal; |
||||
font-weight: 300; |
||||
src: url(fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zwmRdu3cOWxy40.woff2) format('woff2'); |
||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; |
||||
} |
||||
/* latin */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: normal; |
||||
font-weight: 300; |
||||
src: url(fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ik4zwlxdu3cOWxw.woff2) format('woff2'); |
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; |
||||
} |
||||
/* cyrillic-ext */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: normal; |
||||
font-weight: 400; |
||||
src: url(fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3qNa7lujVj9_mf.woff2) format('woff2'); |
||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; |
||||
} |
||||
/* cyrillic */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: normal; |
||||
font-weight: 400; |
||||
src: url(fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3qPK7lujVj9_mf.woff2) format('woff2'); |
||||
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; |
||||
} |
||||
/* greek-ext */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: normal; |
||||
font-weight: 400; |
||||
src: url(fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3qNK7lujVj9_mf.woff2) format('woff2'); |
||||
unicode-range: U+1F00-1FFF; |
||||
} |
||||
/* greek */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: normal; |
||||
font-weight: 400; |
||||
src: url(fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3qO67lujVj9_mf.woff2) format('woff2'); |
||||
unicode-range: U+0370-03FF; |
||||
} |
||||
/* vietnamese */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: normal; |
||||
font-weight: 400; |
||||
src: url(fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3qN67lujVj9_mf.woff2) format('woff2'); |
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; |
||||
} |
||||
/* latin-ext */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: normal; |
||||
font-weight: 400; |
||||
src: url(fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3qNq7lujVj9_mf.woff2) format('woff2'); |
||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; |
||||
} |
||||
/* latin */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: normal; |
||||
font-weight: 400; |
||||
src: url(fonts/6xK3dSBYKcSV-LCoeQqfX1RYOo3qOK7lujVj9w.woff2) format('woff2'); |
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; |
||||
} |
||||
/* cyrillic-ext */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: normal; |
||||
font-weight: 700; |
||||
src: url(fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwmhdu3cOWxy40.woff2) format('woff2'); |
||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; |
||||
} |
||||
/* cyrillic */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: normal; |
||||
font-weight: 700; |
||||
src: url(fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwkxdu3cOWxy40.woff2) format('woff2'); |
||||
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; |
||||
} |
||||
/* greek-ext */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: normal; |
||||
font-weight: 700; |
||||
src: url(fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwmxdu3cOWxy40.woff2) format('woff2'); |
||||
unicode-range: U+1F00-1FFF; |
||||
} |
||||
/* greek */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: normal; |
||||
font-weight: 700; |
||||
src: url(fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlBdu3cOWxy40.woff2) format('woff2'); |
||||
unicode-range: U+0370-03FF; |
||||
} |
||||
/* vietnamese */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: normal; |
||||
font-weight: 700; |
||||
src: url(fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwmBdu3cOWxy40.woff2) format('woff2'); |
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; |
||||
} |
||||
/* latin-ext */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: normal; |
||||
font-weight: 700; |
||||
src: url(fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwmRdu3cOWxy40.woff2) format('woff2'); |
||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; |
||||
} |
||||
/* latin */ |
||||
@font-face { |
||||
font-family: 'Source Sans Pro'; |
||||
font-style: normal; |
||||
font-weight: 700; |
||||
src: url(fonts/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlxdu3cOWxw.woff2) format('woff2'); |
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; |
||||
} |
||||
@ -0,0 +1,223 @@
@@ -0,0 +1,223 @@
|
||||
#videoPlayer{ |
||||
width: 100%; |
||||
background: black; |
||||
position: -webkit-sticky; /* Safari */ |
||||
position: sticky; |
||||
top: 15px; |
||||
margin-bottom: -6px; |
||||
|
||||
} |
||||
.videoPlayer{ |
||||
width: 100%; |
||||
background: black; |
||||
position: -webkit-sticky; /* Safari */ |
||||
position: sticky; |
||||
top: 15px; |
||||
margin-bottom: -6px; |
||||
|
||||
} |
||||
.btn-group.stream{ |
||||
display: flex; |
||||
justify-content: space-between; |
||||
flex-wrap: wrap; |
||||
} |
||||
.btn-group.stream .btn{ |
||||
flex: 1 0 30%; |
||||
} |
||||
.btn-group.stream .input-group-prepend{ |
||||
flex: 1 0 30%; |
||||
} |
||||
.img-wrapper{ |
||||
width: 100%; |
||||
height: 180px; |
||||
background: black; |
||||
cursor: pointer; |
||||
} |
||||
.img-wrapper img{ |
||||
width: 100%; |
||||
height: 100%; |
||||
} |
||||
.text-wrapper{ |
||||
padding: 10px; |
||||
} |
||||
|
||||
@media (min-width: 576px){ |
||||
.card-columns { |
||||
-webkit-column-count: 4; |
||||
-moz-column-count: 4; |
||||
column-count: 4; |
||||
-webkit-column-gap: 1.25rem; |
||||
-moz-column-gap: 1.25rem; |
||||
column-gap: 1.25rem; |
||||
orphans: 1; |
||||
widows: 1; |
||||
} |
||||
} |
||||
@media (min-width: 576px){ |
||||
.card-column { |
||||
column-count: 2; |
||||
} |
||||
} |
||||
@media (min-width: 768px){ |
||||
.card-column { |
||||
column-count: 4; |
||||
} |
||||
} |
||||
@media (min-width: 1920px){ |
||||
.card-column { |
||||
column-count: 6; |
||||
} |
||||
} |
||||
|
||||
|
||||
.grid-wrapper{ |
||||
height: 80vh; |
||||
margin: -1px; |
||||
background: #000; |
||||
display: flex; |
||||
flex-wrap: wrap; |
||||
} |
||||
:-webkit-full-screen .grid-wrapper{/*WebKit, Opera 15+*/ |
||||
height: 100vh; |
||||
width: 100vw; |
||||
} |
||||
:-moz-full-screen .grid-wrapper{/*FireFox*/ |
||||
height: 100vh; |
||||
width: 100vw; |
||||
} |
||||
:full-screen .grid-wrapper{/*Opera 12.15-, Blink, w3c standard*/ |
||||
height: 100vh; |
||||
width: 100vw; |
||||
} |
||||
.grid-wrapper .player{ |
||||
height: 50%; |
||||
width: 50%; |
||||
position: relative; |
||||
padding: 2px; |
||||
} |
||||
.grid-wrapper .player.grid-1{ |
||||
width: 100%; |
||||
height: 100%; |
||||
} |
||||
.grid-wrapper .player.grid-6{ |
||||
width: 33.33%; |
||||
} |
||||
.grid-wrapper .player.grid-9{ |
||||
width: 33.33%; |
||||
height: 33.33%; |
||||
} |
||||
.grid-wrapper .player.grid-12{ |
||||
width: 25%; |
||||
height: 33.33%; |
||||
} |
||||
.grid-wrapper .player.grid-16{ |
||||
width: 25%; |
||||
height: 25%; |
||||
} |
||||
.grid-wrapper .player.grid-25{ |
||||
width: 20%; |
||||
height: 20%; |
||||
} |
||||
.grid-wrapper .player.grid-36{ |
||||
width: 16.66%; |
||||
height: 16.66%; |
||||
} |
||||
.grid-wrapper .player.grid-49{ |
||||
width: 14.285%; |
||||
height: 14.29%; |
||||
} |
||||
.grid-wrapper .player video{ |
||||
height: 100%; |
||||
width: 100%; |
||||
background: #343a40; |
||||
margin-bottom: -6px; |
||||
} |
||||
.grid-wrapper .player .play-info{ |
||||
position: absolute; |
||||
padding: 10px; |
||||
text-align: center; |
||||
color: #fff; |
||||
top:0; |
||||
left: 0; |
||||
width: 100%; |
||||
} |
||||
.grid-wrapper .player .control{ |
||||
width: 100%; |
||||
position: absolute; |
||||
bottom: 0; |
||||
padding: 10px; |
||||
text-align: center; |
||||
} |
||||
.grid-wrapper .player .control .btn{ |
||||
margin: 0 0 10px 10px; |
||||
} |
||||
|
||||
.card .stream-name{ |
||||
position: absolute; |
||||
width: 100%; |
||||
height: 100%; |
||||
display: flex; |
||||
align-items: center; |
||||
} |
||||
.card .stream-name .card-title{ |
||||
color: #FFF; |
||||
width: 100%; |
||||
filter: drop-shadow(1px 0px 1px black); |
||||
font-size: 30px; |
||||
} |
||||
.one-line-header{ |
||||
white-space: nowrap; |
||||
overflow: hidden; |
||||
text-overflow: ellipsis; |
||||
max-width: 95%; |
||||
} |
||||
.main-player-wrapper{ |
||||
position: fixed; |
||||
top: 0; |
||||
left: 0; |
||||
width: 100vw; |
||||
height: 100vh; |
||||
background: rgb(0 0 0 / 0.8); |
||||
z-index: 1100; |
||||
padding: 15px; |
||||
} |
||||
.main-player-wrapper a{ |
||||
color: #fff; |
||||
position: absolute; |
||||
right: 5px; |
||||
top: 5px; |
||||
font-size: 30px; |
||||
padding: 0 12px; |
||||
border-radius: 50px; |
||||
box-shadow: 0px 0px 10px -1px #fff; |
||||
cursor: pointer; |
||||
} |
||||
.main-player-wrapper a:hover{ |
||||
color: #dc3545; |
||||
box-shadow: 0px 0px 10px -1px #dc3545; |
||||
} |
||||
.main-player-wrapper .main-player{ |
||||
width: 100%; |
||||
height: 100%; |
||||
position: relative; |
||||
} |
||||
.main-player-wrapper .main-player video{ |
||||
width: 100%; |
||||
height: 100%; |
||||
background: #000; |
||||
} |
||||
.main-player-wrapper .main-player .play-info{ |
||||
position: absolute; |
||||
padding: 10px; |
||||
text-align: center; |
||||
color: #fff; |
||||
top: 0; |
||||
width: 100%; |
||||
} |
||||
.carousel-caption{ |
||||
pointer-events: none; |
||||
} |
||||
.fix-height{ |
||||
object-fit: fill; |
||||
aspect-ratio: 16/9; |
||||
} |
||||
|
After Width: | Height: | Size: 298 KiB |
|
After Width: | Height: | Size: 493 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 411 KiB |
|
After Width: | Height: | Size: 221 KiB |
@ -0,0 +1,218 @@
@@ -0,0 +1,218 @@
|
||||
var rtspPlayer={ |
||||
active:false, |
||||
type:'live', |
||||
hls:null, |
||||
ws:null, |
||||
mseSourceBuffer:null, |
||||
mse:null, |
||||
mseQueue:[], |
||||
mseStreamingStarted:false, |
||||
webrtc:null, |
||||
webrtcSendChannel:null, |
||||
webrtcSendChannelInterval:null, |
||||
uuid:null, |
||||
|
||||
clearPlayer:function(){ |
||||
if(this.active){ |
||||
|
||||
if(this.hls!=null){ |
||||
this.hls.destroy(); |
||||
this.hls=null; |
||||
} |
||||
if(this.ws!=null){ |
||||
//close WebSocket connection if opened
|
||||
this.ws.close(1000); |
||||
this.ws=null; |
||||
} |
||||
if(this.webrtc!=null){ |
||||
clearInterval(this.webrtcSendChannelInterval); |
||||
|
||||
this.webrtc=null; |
||||
} |
||||
$('#videoPlayer')[0].src = ''; |
||||
$('#videoPlayer')[0].load(); |
||||
|
||||
|
||||
this.active=false; |
||||
} |
||||
}, |
||||
livePlayer:function(type,uuid){ |
||||
this.clearPlayer(); |
||||
this.uuid=uuid; |
||||
this.active=true; |
||||
|
||||
$('.streams-vs-player').addClass('active-player'); |
||||
if(type==0){ |
||||
type=$('input[name=defaultPlayer]:checked').val() |
||||
} |
||||
switch (type) { |
||||
case 'hls': |
||||
this.playHls(); |
||||
break; |
||||
case 'mse': |
||||
this.playMse(); |
||||
break; |
||||
case 'webrtc': |
||||
this.playWebrtc(); |
||||
break; |
||||
default: |
||||
Swal.fire( |
||||
'Sorry', |
||||
'This option is still under development', |
||||
'question' |
||||
) |
||||
return; |
||||
} |
||||
|
||||
}, |
||||
playHls:function(){ |
||||
if(this.hls==null && Hls.isSupported()){ |
||||
this.hls = new Hls(); |
||||
} |
||||
if ($("#videoPlayer")[0].canPlayType('application/vnd.apple.mpegurl')) { |
||||
$("#videoPlayer")[0].src = this.streamPlayUrl('hls'); |
||||
$("#videoPlayer")[0].load(); |
||||
} else { |
||||
if (this.hls != null) { |
||||
this.hls.loadSource(this.streamPlayUrl('hls')); |
||||
this.hls.attachMedia($("#videoPlayer")[0]); |
||||
} else { |
||||
Swal.fire({ |
||||
icon: 'error', |
||||
title: 'Oops...', |
||||
text: 'Your browser don`t support hls ' |
||||
}) |
||||
} |
||||
} |
||||
}, |
||||
playWebrtc:function(){ |
||||
var _this=this; |
||||
this.webrtc=new RTCPeerConnection({ |
||||
iceServers: [{ |
||||
urls: ["stun:stun.l.google.com:19302"] |
||||
}] |
||||
}); |
||||
this.webrtc.onnegotiationneeded = this.handleNegotiationNeeded; |
||||
this.webrtc.ontrack = function(event) { |
||||
console.log(event.streams.length + ' track is delivered'); |
||||
$("#videoPlayer")[0].srcObject = event.streams[0]; |
||||
$("#videoPlayer")[0].play(); |
||||
} |
||||
this.webrtc.addTransceiver('video', { |
||||
'direction': 'sendrecv' |
||||
}); |
||||
this.webrtcSendChannel = this.webrtc.createDataChannel('foo'); |
||||
this.webrtcSendChannel.onclose = () => console.log('sendChannel has closed'); |
||||
this.webrtcSendChannel.onopen = () => { |
||||
console.log('sendChannel has opened'); |
||||
this.webrtcSendChannel.send('ping'); |
||||
this.webrtcSendChannelInterval = setInterval(() => { |
||||
this.webrtcSendChannel.send('ping'); |
||||
}, 1000) |
||||
} |
||||
|
||||
this.webrtcSendChannel.onmessage = e => console.log(e.data); |
||||
}, |
||||
handleNegotiationNeeded: async function(){ |
||||
var _this=rtspPlayer; |
||||
|
||||
offer = await _this.webrtc.createOffer(); |
||||
await _this.webrtc.setLocalDescription(offer); |
||||
$.post(_this.streamPlayUrl('webrtc'), { |
||||
data: btoa(_this.webrtc.localDescription.sdp) |
||||
}, function(data) { |
||||
//console.log(data)
|
||||
try { |
||||
|
||||
_this.webrtc.setRemoteDescription(new RTCSessionDescription({ |
||||
type: 'answer', |
||||
sdp: atob(data) |
||||
})) |
||||
|
||||
|
||||
|
||||
} catch (e) { |
||||
console.warn(e); |
||||
} |
||||
|
||||
}); |
||||
}, |
||||
playMse:function(){ |
||||
//console.log(this.streamPlayUrl('mse'));
|
||||
var _this=this; |
||||
this.mse = new MediaSource(); |
||||
$("#videoPlayer")[0].src=window.URL.createObjectURL(this.mse); |
||||
this.mse.addEventListener('sourceopen', function(){ |
||||
_this.ws=new WebSocket(_this.streamPlayUrl('mse')); |
||||
_this.ws.binaryType = "arraybuffer"; |
||||
_this.ws.onopen = function(event) { |
||||
console.log('Connect to ws'); |
||||
} |
||||
|
||||
_this.ws.onmessage = function(event) { |
||||
var data = new Uint8Array(event.data); |
||||
if (data[0] == 9) { |
||||
decoded_arr=data.slice(1); |
||||
if (window.TextDecoder) { |
||||
mimeCodec = new TextDecoder("utf-8").decode(decoded_arr); |
||||
} else { |
||||
mimeCodec = Utf8ArrayToStr(decoded_arr); |
||||
} |
||||
console.log(mimeCodec); |
||||
_this.mseSourceBuffer = _this.mse.addSourceBuffer('video/mp4; codecs="' + mimeCodec + '"'); |
||||
_this.mseSourceBuffer.mode = "segments" |
||||
_this.mseSourceBuffer.addEventListener("updateend", _this.pushPacket); |
||||
|
||||
} else { |
||||
_this.readPacket(event.data); |
||||
} |
||||
}; |
||||
}, false); |
||||
|
||||
}, |
||||
readPacket:function(packet){ |
||||
if (!this.mseStreamingStarted) { |
||||
this.mseSourceBuffer.appendBuffer(packet); |
||||
this.mseStreamingStarted = true; |
||||
return; |
||||
} |
||||
this.mseQueue.push(packet); |
||||
|
||||
if (!this.mseSourceBuffer.updating) { |
||||
this.pushPacket(); |
||||
} |
||||
}, |
||||
pushPacket:function(){ |
||||
var _this=rtspPlayer; |
||||
if (!_this.mseSourceBuffer.updating) { |
||||
if (_this.mseQueue.length > 0) { |
||||
packet = _this.mseQueue.shift(); |
||||
var view = new Uint8Array(packet); |
||||
_this.mseSourceBuffer.appendBuffer(packet); |
||||
} else { |
||||
_this.mseStreamingStarted = false; |
||||
} |
||||
} |
||||
}, |
||||
streamPlayUrl:function(type){ |
||||
switch (type) { |
||||
case 'hls': |
||||
return '/stream/' + this.uuid + '/hls/live/index.m3u8'; |
||||
break; |
||||
case 'mse': |
||||
var potocol = 'ws'; |
||||
if (location.protocol == 'https:') { |
||||
potocol = 'wss'; |
||||
} |
||||
return potocol+'://'+location.host+'/stream/' + this.uuid +'/mse?uuid='+this.uuid; |
||||
//return 'ws://sr4.ipeye.ru/ws/mp4/live?name=d4ee855e40874ef7b7149357a42f18f0';
|
||||
break; |
||||
case 'webrtc': |
||||
return "/stream/"+this.uuid+"/webrtc?uuid=" + this.uuid; |
||||
break; |
||||
default: |
||||
return ''; |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,531 @@
@@ -0,0 +1,531 @@
|
||||
$(document).ready(() => { |
||||
localImages(); |
||||
if (localStorage.getItem('defaultPlayer') != null) { |
||||
$('input[name=defaultPlayer]').val([localStorage.getItem('defaultPlayer')]); |
||||
} |
||||
}) |
||||
$('input[name=defaultPlayer]').on('change', function() { |
||||
localStorage.setItem('defaultPlayer', $(this).val()); |
||||
}) |
||||
|
||||
var activeStream = null; |
||||
|
||||
function showAddStream(streamName, streamUrl) { |
||||
streamName = streamName || ''; |
||||
streamUrl = streamUrl || ''; |
||||
Swal.fire({ |
||||
title: 'Add stream', |
||||
html: '<form class="text-left"> ' + |
||||
'<div class="form-group">' + |
||||
'<label>Name</label>' + |
||||
'<input type="text" class="form-control" id="stream-name">' + |
||||
'<small class="form-text text-muted"></small>' + |
||||
'</div>' + |
||||
'<div class="form-group">' + |
||||
' <label>URL</label>' + |
||||
' <input type="text" class="form-control" id="stream-url">' + |
||||
' </div>' + |
||||
'<div class="form-group form-check">' + |
||||
'<input type="checkbox" class="form-check-input" id="stream-ondemand">' + |
||||
'<label class="form-check-label">ondemand</label>' + |
||||
'</div>' + |
||||
'</form>', |
||||
focusConfirm: true, |
||||
showCancelButton: true, |
||||
preConfirm: () => { |
||||
var uuid = randomUuid(), |
||||
name = $('#stream-name').val(), |
||||
url = $('#stream-url').val(), |
||||
ondemand = $('#stream-ondemand').val(); |
||||
if (!validURL(url)) { |
||||
Swal.fire({ |
||||
icon: 'error', |
||||
title: 'Oops...', |
||||
text: 'wrong url', |
||||
confirmButtonText: 'return back', |
||||
preConfirm: () => { |
||||
showAddStream(name, url) |
||||
} |
||||
}) |
||||
} else { |
||||
goRequest('add', uuid, { |
||||
name: name, |
||||
url: url, |
||||
ondemand: ondemand |
||||
}); |
||||
|
||||
|
||||
} |
||||
} |
||||
}) |
||||
|
||||
} |
||||
|
||||
function showEditStream(uuid) { |
||||
console.log(streams[uuid]); |
||||
} |
||||
|
||||
function deleteStream(uuid) { |
||||
activeStream = uuid; |
||||
Swal.fire({ |
||||
title: 'Are you sure?', |
||||
text: "Do you want delete stream " + streams[uuid].name + " ?", |
||||
icon: 'warning', |
||||
showCancelButton: true, |
||||
confirmButtonColor: '#3085d6', |
||||
cancelButtonColor: '#d33', |
||||
confirmButtonText: 'Yes, delete it!' |
||||
}).then((result) => { |
||||
if (result.value) { |
||||
goRequest('delete', uuid) |
||||
|
||||
} |
||||
}) |
||||
} |
||||
|
||||
function renewStreamlist() { |
||||
goRequest('streams'); |
||||
} |
||||
|
||||
function goRequest(method, uuid, data) { |
||||
data = data || null; |
||||
uuid = uuid || null; |
||||
var path = ''; |
||||
var type = 'GET'; |
||||
switch (method) { |
||||
case 'add': |
||||
path = '/stream/' + uuid + '/add'; |
||||
type = 'POST'; |
||||
break; |
||||
case 'edit': |
||||
path = '/stream/' + uuid + '/edit'; |
||||
type = 'POST'; |
||||
break; |
||||
case 'delete': |
||||
path = '/stream/' + uuid + '/delete'; |
||||
break; |
||||
case 'reload': |
||||
path = '/stream/' + uuid + '/reload'; |
||||
break; |
||||
case 'info': |
||||
path = '/stream/' + uuid + '/info'; |
||||
break; |
||||
case 'streams': |
||||
path = '/streams'; |
||||
break; |
||||
default: |
||||
path = ''; |
||||
type = 'GET'; |
||||
} |
||||
if (path == '') { |
||||
Swal.fire({ |
||||
icon: 'error', |
||||
title: 'Oops...', |
||||
text: 'It`s goRequest function mistake', |
||||
confirmButtonText: 'Close', |
||||
|
||||
}) |
||||
return; |
||||
} |
||||
var ajaxParam = { |
||||
url: path, |
||||
type: type, |
||||
dataType: 'json', |
||||
beforeSend: function(xhr) { |
||||
xhr.setRequestHeader("Authorization", "Basic " + btoa("demo:demo")); |
||||
}, |
||||
success: function(response) { |
||||
goRequestHandle(method, response, uuid); |
||||
}, |
||||
error: function(e) { |
||||
console.log(e); |
||||
} |
||||
}; |
||||
if (data != null) { |
||||
ajaxParam.data = JSON.stringify(data); |
||||
} |
||||
$.ajax(ajaxParam); |
||||
} |
||||
|
||||
function goRequestHandle(method, response, uuid) { |
||||
switch (method) { |
||||
case 'add': |
||||
|
||||
if (response.status == 1) { |
||||
renewStreamlist(); |
||||
Swal.fire( |
||||
'Added!', |
||||
'Your stream has been Added.', |
||||
'success' |
||||
); |
||||
|
||||
} else { |
||||
Swal.fire({ |
||||
icon: 'error', |
||||
title: 'Oops...', |
||||
text: 'Same mistake issset', |
||||
}) |
||||
} |
||||
|
||||
break; |
||||
case 'edit': |
||||
if (response.status == 1) { |
||||
renewStreamlist(); |
||||
Swal.fire( |
||||
'Success!', |
||||
'Your stream has been modified.', |
||||
'success' |
||||
); |
||||
} else { |
||||
Swal.fire({ |
||||
icon: 'error', |
||||
title: 'Oops...', |
||||
text: 'Same mistake issset', |
||||
}) |
||||
} |
||||
break; |
||||
case 'delete': |
||||
|
||||
if (response.status == 1) { |
||||
$('#' + uuid).remove(); |
||||
delete(streams[uuid]); |
||||
$('#stream-counter').html(Object.keys(streams).length); |
||||
Swal.fire( |
||||
'Deleted!', |
||||
'Your stream has been deleted.', |
||||
'success' |
||||
) |
||||
} |
||||
|
||||
break; |
||||
case 'reload': |
||||
|
||||
break; |
||||
case 'info': |
||||
|
||||
break; |
||||
case 'streams': |
||||
if (response.status == 1) { |
||||
streams = response.payload; |
||||
$('#stream-counter').html(Object.keys(streams).length); |
||||
if (Object.keys(streams).length > 0) { |
||||
|
||||
$.each(streams, function(uuid, param) { |
||||
if ($('#' + uuid).length == 0) { |
||||
$('.streams').append(streamHtmlTemplate(uuid, param.name)); |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
|
||||
break; |
||||
default: |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
function getImageBase64(videoEl){ |
||||
const canvas = document.createElement("canvas"); |
||||
canvas.width = videoEl.videoWidth; |
||||
canvas.height = videoEl.videoHeight; |
||||
canvas.getContext('2d').drawImage(videoEl, 0, 0, canvas.width, canvas.height); |
||||
const dataURL = canvas.toDataURL(); |
||||
canvas.remove(); |
||||
return dataURL; |
||||
} |
||||
|
||||
function downloadBase64Image(base64Data){ |
||||
const a = document.createElement("a"); |
||||
a.href = base64Data; |
||||
a.download = "screenshot.png"; |
||||
a.click(); |
||||
a.remove(); |
||||
} |
||||
|
||||
|
||||
function makePic(video_element, uuid, chan) { |
||||
if (typeof(video_element) === "undefined") { |
||||
video_element = $("#videoPlayer")[0]; |
||||
} |
||||
ratio = video_element.videoWidth / video_element.videoHeight; |
||||
w = 400; |
||||
h = parseInt(w / ratio, 10); |
||||
$('#canvas')[0].width = w; |
||||
$('#canvas')[0].height = h; |
||||
$('#canvas')[0].getContext('2d').fillRect(0, 0, w, h); |
||||
$('#canvas')[0].getContext('2d').drawImage(video_element, 0, 0, w, h); |
||||
var imageData = $('#canvas')[0].toDataURL(); |
||||
var images = localStorage.getItem('imagesNew'); |
||||
if (images != null) { |
||||
images = JSON.parse(images); |
||||
} else { |
||||
images = {}; |
||||
} |
||||
var uid = $('#uuid').val(); |
||||
if (!!uuid) { |
||||
uid = uuid; |
||||
} |
||||
|
||||
var channel = $('#channel').val() || chan || 0; |
||||
if (typeof(images[uid]) === "undefined") { |
||||
images[uid] = {}; |
||||
} |
||||
images[uid][channel] = imageData; |
||||
localStorage.setItem('imagesNew', JSON.stringify(images)); |
||||
$('#' + uid).find('.stream-img[channel="' + channel + '"]').attr('src', imageData); |
||||
} |
||||
|
||||
function localImages() { |
||||
var images = localStorage.getItem('imagesNew'); |
||||
if (images != null) { |
||||
images = JSON.parse(images); |
||||
$.each(images, function(k, v) { |
||||
$.each(v, function(channel, img) { |
||||
$('#' + k).find('.stream-img[channel="' + channel + '"]').attr('src', img); |
||||
}) |
||||
|
||||
}); |
||||
} |
||||
} |
||||
|
||||
function clearLocalImg() { |
||||
localStorage.setItem('imagesNew', '{}'); |
||||
} |
||||
|
||||
function streamHtmlTemplate(uuid, name) { |
||||
return '<div class="item" id="' + uuid + '">' + |
||||
'<div class="stream">' + |
||||
'<div class="thumbs" onclick="rtspPlayer.livePlayer(0, \'' + uuid + '\')">' + |
||||
'<img src="../static/img/noimage.svg" alt="" class="stream-img">' + |
||||
'</div>' + |
||||
'<div class="text">' + |
||||
'<h5>' + name + '</h5>' + |
||||
'<p>property</p>' + |
||||
'<div class="input-group-prepend dropleft text-muted">' + |
||||
'<a class="btn" data-toggle="dropdown" >' + |
||||
'<i class="fas fa-ellipsis-v"></i>' + |
||||
'</a>' + |
||||
'<div class="dropdown-menu">' + |
||||
'<a class="dropdown-item" onclick="rtspPlayer.livePlayer(\'hls\', \'' + uuid + '\')" href="#">Play HLS</a>' + |
||||
'<a class="dropdown-item" onclick="rtspPlayer.livePlayer(\'mse\', \'' + uuid + '\')" href="#">Play MSE</a>' + |
||||
'<a class="dropdown-item" onclick="rtspPlayer.livePlayer(\'webrtc\', \'' + uuid + '\')" href="#">Play WebRTC</a>' + |
||||
'<div class="dropdown-divider"></div>' + |
||||
'<a class="dropdown-item" onclick="showEditStream(\'' + uuid + '\')" href="#">Edit</a>' + |
||||
'<a class="dropdown-item" onclick="deleteStream(\'' + uuid + '\')" href="#">Delete</a>' + |
||||
'</div>' + |
||||
'</div>' + |
||||
'</div>' + |
||||
'</div>' + |
||||
'</div>'; |
||||
} |
||||
|
||||
function randomUuid() { |
||||
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => |
||||
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16) |
||||
); |
||||
} |
||||
|
||||
function validURL(url) { |
||||
//TODO: fix it
|
||||
return true; |
||||
} |
||||
|
||||
function Utf8ArrayToStr(array) { |
||||
var out, i, len, c; |
||||
var char2, char3; |
||||
out = ""; |
||||
len = array.length; |
||||
i = 0; |
||||
while (i < len) { |
||||
c = array[i++]; |
||||
switch (c >> 4) { |
||||
case 7: |
||||
out += String.fromCharCode(c); |
||||
break; |
||||
case 13: |
||||
char2 = array[i++]; |
||||
out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F)); |
||||
break; |
||||
case 14: |
||||
char2 = array[i++]; |
||||
char3 = array[i++]; |
||||
out += String.fromCharCode(((c & 0x0F) << 12) | |
||||
((char2 & 0x3F) << 6) | |
||||
((char3 & 0x3F) << 0)); |
||||
break; |
||||
} |
||||
} |
||||
return out; |
||||
} |
||||
|
||||
function browserDetector() { |
||||
var Browser; |
||||
var ua = self.navigator.userAgent.toLowerCase(); |
||||
var match = |
||||
/(edge)\/([\w.]+)/.exec(ua) || |
||||
/(opr)[\/]([\w.]+)/.exec(ua) || |
||||
/(chrome)[ \/]([\w.]+)/.exec(ua) || |
||||
/(iemobile)[\/]([\w.]+)/.exec(ua) || |
||||
/(version)(applewebkit)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(ua) || |
||||
/(webkit)[ \/]([\w.]+).*(version)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec( |
||||
ua |
||||
) || |
||||
/(webkit)[ \/]([\w.]+)/.exec(ua) || |
||||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || |
||||
/(msie) ([\w.]+)/.exec(ua) || |
||||
(ua.indexOf("trident") >= 0 && /(rv)(?::| )([\w.]+)/.exec(ua)) || |
||||
(ua.indexOf("compatible") < 0 && /(firefox)[ \/]([\w.]+)/.exec(ua)) || []; |
||||
var platform_match = |
||||
/(ipad)/.exec(ua) || |
||||
/(ipod)/.exec(ua) || |
||||
/(windows phone)/.exec(ua) || |
||||
/(iphone)/.exec(ua) || |
||||
/(kindle)/.exec(ua) || |
||||
/(android)/.exec(ua) || |
||||
/(windows)/.exec(ua) || |
||||
/(mac)/.exec(ua) || |
||||
/(linux)/.exec(ua) || |
||||
/(cros)/.exec(ua) || []; |
||||
var matched = { |
||||
browser: match[5] || match[3] || match[1] || "", |
||||
version: match[2] || match[4] || "0", |
||||
majorVersion: match[4] || match[2] || "0", |
||||
platform: platform_match[0] || "" |
||||
}; |
||||
var browser = {}; |
||||
|
||||
if (matched.browser) { |
||||
browser[matched.browser] = true; |
||||
var versionArray = matched.majorVersion.split("."); |
||||
browser.version = { |
||||
major: parseInt(matched.majorVersion, 10), |
||||
string: matched.version |
||||
}; |
||||
|
||||
if (versionArray.length > 1) { |
||||
browser.version.minor = parseInt(versionArray[1], 10); |
||||
} |
||||
|
||||
if (versionArray.length > 2) { |
||||
browser.version.build = parseInt(versionArray[2], 10); |
||||
} |
||||
} |
||||
|
||||
if (matched.platform) { |
||||
browser[matched.platform] = true; |
||||
} |
||||
|
||||
if (browser.chrome || browser.opr || browser.safari) { |
||||
browser.webkit = true; |
||||
} // MSIE. IE11 has 'rv' identifer
|
||||
|
||||
if (browser.rv || browser.iemobile) { |
||||
if (browser.rv) { |
||||
delete browser.rv; |
||||
} |
||||
|
||||
var msie = "msie"; |
||||
matched.browser = msie; |
||||
browser[msie] = true; |
||||
} // Microsoft Edge
|
||||
|
||||
if (browser.edge) { |
||||
delete browser.edge; |
||||
var msedge = "msedge"; |
||||
matched.browser = msedge; |
||||
browser[msedge] = true; |
||||
} // Opera 15+
|
||||
|
||||
if (browser.opr) { |
||||
var opera = "opera"; |
||||
matched.browser = opera; |
||||
browser[opera] = true; |
||||
} // Stock android browsers are marked as Safari
|
||||
|
||||
if (browser.safari && browser.android) { |
||||
var android = "android"; |
||||
matched.browser = android; |
||||
browser[android] = true; |
||||
} |
||||
|
||||
browser.name = matched.browser; |
||||
browser.platform = matched.platform; |
||||
|
||||
|
||||
return browser; |
||||
} |
||||
|
||||
function addChannel() { |
||||
$('#streams-form-wrapper').append(chanellTemplate()); |
||||
} |
||||
|
||||
function chanellTemplate() { |
||||
let random = Math.ceil(Math.random() * 1000); |
||||
let html = ` |
||||
<div class="col-12"> |
||||
<div class="card card-secondary"> |
||||
<div class="card-header"> |
||||
<h3 class="card-title">Sub channel<small> parameters</small></h3> |
||||
<div class="card-tools"> |
||||
<button type="button" class="btn btn-tool" onclick="removeChannelDiv(this)"><i class="fas fa-times"></i></button> |
||||
</div> |
||||
</div> |
||||
<div class="card-body"> |
||||
<form class="stream-form"> |
||||
<div class="form-group"> |
||||
<label for="exampleInputPassword1">Substream url</label> |
||||
<input type="text" name="stream-url" class="form-control" placeholder="Enter stream url" > |
||||
<small class="form-text text-muted">Enter rtsp address as instructed by your camera. Look like <code>rtsp://<ip>:<port>/path </code> </small>
|
||||
</div> |
||||
<div class="form-group"> |
||||
<label for="inputStatus">Substream type</label> |
||||
<select class="form-control custom-select" name="stream-ondemand" > |
||||
<option selected disabled><small>Select One</small></option> |
||||
<option value="1">On demand only</option> |
||||
<option value="0">Persistent connection</option> |
||||
</select> |
||||
<small class="form-text text-muted">On persistent connection, the server get data from the camera continuously. On demand, the server get data from the camera only when you click play button </small> |
||||
</div> |
||||
<div class="form-group"> |
||||
<div class="custom-control custom-switch"> |
||||
<input type="checkbox" class="custom-control-input" name="debug" id="substream-debug-switch-` + random + `" > |
||||
<label class="custom-control-label" for="substream-debug-switch-` + random + `">Enable debug</label> |
||||
</div> |
||||
<small class="form-text text-muted">Select this options if you want get more data about the stream </small> |
||||
</div> |
||||
</form> |
||||
</div> |
||||
</div> |
||||
</div>`; |
||||
return html; |
||||
} |
||||
|
||||
function removeChannelDiv(element) { |
||||
$(element).closest('.col-12').remove(); |
||||
} |
||||
|
||||
function logger() { |
||||
if (!colordebug) { |
||||
return; |
||||
} |
||||
let colors = { |
||||
"0": "color:green", |
||||
"1": "color:#66CDAA", |
||||
"2": "color:blue", |
||||
"3": "color:#FF1493", |
||||
"4": "color:#40E0D0", |
||||
"5": "color:red", |
||||
"6": "color:red", |
||||
"7": "color:red", |
||||
"8": "color:red", |
||||
"9": "color:red", |
||||
"10": "color:red", |
||||
"11": "color:red", |
||||
"12": "color:red", |
||||
"13": "color:red", |
||||
"14": "color:red", |
||||
"15": "color:red", |
||||
} |
||||
console.log('%c%s', colors[arguments[0]], new Date().toLocaleString() + " " + [].slice.call(arguments).join('|')) |
||||
} |
||||
@ -0,0 +1,325 @@
@@ -0,0 +1,325 @@
|
||||
/*! |
||||
* Bootstrap Reboot v4.5.1 (https://getbootstrap.com/) |
||||
* Copyright 2011-2020 The Bootstrap Authors |
||||
* Copyright 2011-2020 Twitter, Inc. |
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) |
||||
*/ |
||||
*, |
||||
*::before, |
||||
*::after { |
||||
box-sizing: border-box; |
||||
} |
||||
|
||||
html { |
||||
font-family: sans-serif; |
||||
line-height: 1.15; |
||||
-webkit-text-size-adjust: 100%; |
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0); |
||||
} |
||||
|
||||
article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { |
||||
display: block; |
||||
} |
||||
|
||||
body { |
||||
margin: 0; |
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; |
||||
font-size: 1rem; |
||||
font-weight: 400; |
||||
line-height: 1.5; |
||||
color: #212529; |
||||
text-align: left; |
||||
background-color: #fff; |
||||
} |
||||
|
||||
[tabindex="-1"]:focus:not(:focus-visible) { |
||||
outline: 0 !important; |
||||
} |
||||
|
||||
hr { |
||||
box-sizing: content-box; |
||||
height: 0; |
||||
overflow: visible; |
||||
} |
||||
|
||||
h1, h2, h3, h4, h5, h6 { |
||||
margin-top: 0; |
||||
margin-bottom: 0.5rem; |
||||
} |
||||
|
||||
p { |
||||
margin-top: 0; |
||||
margin-bottom: 1rem; |
||||
} |
||||
|
||||
abbr[title], |
||||
abbr[data-original-title] { |
||||
text-decoration: underline; |
||||
-webkit-text-decoration: underline dotted; |
||||
text-decoration: underline dotted; |
||||
cursor: help; |
||||
border-bottom: 0; |
||||
-webkit-text-decoration-skip-ink: none; |
||||
text-decoration-skip-ink: none; |
||||
} |
||||
|
||||
address { |
||||
margin-bottom: 1rem; |
||||
font-style: normal; |
||||
line-height: inherit; |
||||
} |
||||
|
||||
ol, |
||||
ul, |
||||
dl { |
||||
margin-top: 0; |
||||
margin-bottom: 1rem; |
||||
} |
||||
|
||||
ol ol, |
||||
ul ul, |
||||
ol ul, |
||||
ul ol { |
||||
margin-bottom: 0; |
||||
} |
||||
|
||||
dt { |
||||
font-weight: 700; |
||||
} |
||||
|
||||
dd { |
||||
margin-bottom: .5rem; |
||||
margin-left: 0; |
||||
} |
||||
|
||||
blockquote { |
||||
margin: 0 0 1rem; |
||||
} |
||||
|
||||
b, |
||||
strong { |
||||
font-weight: bolder; |
||||
} |
||||
|
||||
small { |
||||
font-size: 80%; |
||||
} |
||||
|
||||
sub, |
||||
sup { |
||||
position: relative; |
||||
font-size: 75%; |
||||
line-height: 0; |
||||
vertical-align: baseline; |
||||
} |
||||
|
||||
sub { |
||||
bottom: -.25em; |
||||
} |
||||
|
||||
sup { |
||||
top: -.5em; |
||||
} |
||||
|
||||
a { |
||||
color: #007bff; |
||||
text-decoration: none; |
||||
background-color: transparent; |
||||
} |
||||
|
||||
a:hover { |
||||
color: #0056b3; |
||||
text-decoration: underline; |
||||
} |
||||
|
||||
a:not([href]):not([class]) { |
||||
color: inherit; |
||||
text-decoration: none; |
||||
} |
||||
|
||||
a:not([href]):not([class]):hover { |
||||
color: inherit; |
||||
text-decoration: none; |
||||
} |
||||
|
||||
pre, |
||||
code, |
||||
kbd, |
||||
samp { |
||||
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; |
||||
font-size: 1em; |
||||
} |
||||
|
||||
pre { |
||||
margin-top: 0; |
||||
margin-bottom: 1rem; |
||||
overflow: auto; |
||||
-ms-overflow-style: scrollbar; |
||||
} |
||||
|
||||
figure { |
||||
margin: 0 0 1rem; |
||||
} |
||||
|
||||
img { |
||||
vertical-align: middle; |
||||
border-style: none; |
||||
} |
||||
|
||||
svg { |
||||
overflow: hidden; |
||||
vertical-align: middle; |
||||
} |
||||
|
||||
table { |
||||
border-collapse: collapse; |
||||
} |
||||
|
||||
caption { |
||||
padding-top: 0.75rem; |
||||
padding-bottom: 0.75rem; |
||||
color: #6c757d; |
||||
text-align: left; |
||||
caption-side: bottom; |
||||
} |
||||
|
||||
th { |
||||
text-align: inherit; |
||||
} |
||||
|
||||
label { |
||||
display: inline-block; |
||||
margin-bottom: 0.5rem; |
||||
} |
||||
|
||||
button { |
||||
border-radius: 0; |
||||
} |
||||
|
||||
button:focus { |
||||
outline: 1px dotted; |
||||
outline: 5px auto -webkit-focus-ring-color; |
||||
} |
||||
|
||||
input, |
||||
button, |
||||
select, |
||||
optgroup, |
||||
textarea { |
||||
margin: 0; |
||||
font-family: inherit; |
||||
font-size: inherit; |
||||
line-height: inherit; |
||||
} |
||||
|
||||
button, |
||||
input { |
||||
overflow: visible; |
||||
} |
||||
|
||||
button, |
||||
select { |
||||
text-transform: none; |
||||
} |
||||
|
||||
[role="button"] { |
||||
cursor: pointer; |
||||
} |
||||
|
||||
select { |
||||
word-wrap: normal; |
||||
} |
||||
|
||||
button, |
||||
[type="button"], |
||||
[type="reset"], |
||||
[type="submit"] { |
||||
-webkit-appearance: button; |
||||
} |
||||
|
||||
button:not(:disabled), |
||||
[type="button"]:not(:disabled), |
||||
[type="reset"]:not(:disabled), |
||||
[type="submit"]:not(:disabled) { |
||||
cursor: pointer; |
||||
} |
||||
|
||||
button::-moz-focus-inner, |
||||
[type="button"]::-moz-focus-inner, |
||||
[type="reset"]::-moz-focus-inner, |
||||
[type="submit"]::-moz-focus-inner { |
||||
padding: 0; |
||||
border-style: none; |
||||
} |
||||
|
||||
input[type="radio"], |
||||
input[type="checkbox"] { |
||||
box-sizing: border-box; |
||||
padding: 0; |
||||
} |
||||
|
||||
textarea { |
||||
overflow: auto; |
||||
resize: vertical; |
||||
} |
||||
|
||||
fieldset { |
||||
min-width: 0; |
||||
padding: 0; |
||||
margin: 0; |
||||
border: 0; |
||||
} |
||||
|
||||
legend { |
||||
display: block; |
||||
width: 100%; |
||||
max-width: 100%; |
||||
padding: 0; |
||||
margin-bottom: .5rem; |
||||
font-size: 1.5rem; |
||||
line-height: inherit; |
||||
color: inherit; |
||||
white-space: normal; |
||||
} |
||||
|
||||
progress { |
||||
vertical-align: baseline; |
||||
} |
||||
|
||||
[type="number"]::-webkit-inner-spin-button, |
||||
[type="number"]::-webkit-outer-spin-button { |
||||
height: auto; |
||||
} |
||||
|
||||
[type="search"] { |
||||
outline-offset: -2px; |
||||
-webkit-appearance: none; |
||||
} |
||||
|
||||
[type="search"]::-webkit-search-decoration { |
||||
-webkit-appearance: none; |
||||
} |
||||
|
||||
::-webkit-file-upload-button { |
||||
font: inherit; |
||||
-webkit-appearance: button; |
||||
} |
||||
|
||||
output { |
||||
display: inline-block; |
||||
} |
||||
|
||||
summary { |
||||
display: list-item; |
||||
cursor: pointer; |
||||
} |
||||
|
||||
template { |
||||
display: none; |
||||
} |
||||
|
||||
[hidden] { |
||||
display: none !important; |
||||
} |
||||
/*# sourceMappingURL=bootstrap-reboot.css.map */ |
||||
@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
|
||||
/*! |
||||
* Bootstrap Reboot v4.5.1 (https://getbootstrap.com/) |
||||
* Copyright 2011-2020 The Bootstrap Authors |
||||
* Copyright 2011-2020 Twitter, Inc. |
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) |
||||
*/*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([class]){color:inherit;text-decoration:none}a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important} |
||||
/*# sourceMappingURL=bootstrap-reboot.min.css.map */ |
||||
@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
|
||||
/*! |
||||
* Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com |
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) |
||||
*/ |
||||
@font-face { |
||||
font-family: 'Font Awesome 5 Brands'; |
||||
font-style: normal; |
||||
font-weight: 400; |
||||
font-display: block; |
||||
src: url("../webfonts/fa-brands-400.eot"); |
||||
src: url("../webfonts/fa-brands-400.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.woff") format("woff"), url("../webfonts/fa-brands-400.ttf") format("truetype"), url("../webfonts/fa-brands-400.svg#fontawesome") format("svg"); } |
||||
|
||||
.fab { |
||||
font-family: 'Font Awesome 5 Brands'; |
||||
font-weight: 400; } |
||||
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
/*! |
||||
* Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com |
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) |
||||
*/ |
||||
@font-face{font-family:"Font Awesome 5 Brands";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:"Font Awesome 5 Brands";font-weight:400} |
||||
@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
|
||||
/*! |
||||
* Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com |
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) |
||||
*/ |
||||
@font-face { |
||||
font-family: 'Font Awesome 5 Free'; |
||||
font-style: normal; |
||||
font-weight: 400; |
||||
font-display: block; |
||||
src: url("../webfonts/fa-regular-400.eot"); |
||||
src: url("../webfonts/fa-regular-400.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.woff") format("woff"), url("../webfonts/fa-regular-400.ttf") format("truetype"), url("../webfonts/fa-regular-400.svg#fontawesome") format("svg"); } |
||||
|
||||
.far { |
||||
font-family: 'Font Awesome 5 Free'; |
||||
font-weight: 400; } |
||||
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
/*! |
||||
* Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com |
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) |
||||
*/ |
||||
@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-regular-400.eot);src:url(../webfonts/fa-regular-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.woff) format("woff"),url(../webfonts/fa-regular-400.ttf) format("truetype"),url(../webfonts/fa-regular-400.svg#fontawesome) format("svg")}.far{font-family:"Font Awesome 5 Free";font-weight:400} |
||||
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
/*! |
||||
* Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com |
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) |
||||
*/ |
||||
@font-face { |
||||
font-family: 'Font Awesome 5 Free'; |
||||
font-style: normal; |
||||
font-weight: 900; |
||||
font-display: block; |
||||
src: url("../webfonts/fa-solid-900.eot"); |
||||
src: url("../webfonts/fa-solid-900.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.woff") format("woff"), url("../webfonts/fa-solid-900.ttf") format("truetype"), url("../webfonts/fa-solid-900.svg#fontawesome") format("svg"); } |
||||
|
||||
.fa, |
||||
.fas { |
||||
font-family: 'Font Awesome 5 Free'; |
||||
font-weight: 900; } |
||||
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
/*! |
||||
* Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com |
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) |
||||
*/ |
||||
@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.fas{font-family:"Font Awesome 5 Free";font-weight:900} |
||||
@ -0,0 +1,371 @@
@@ -0,0 +1,371 @@
|
||||
/*! |
||||
* Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com |
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) |
||||
*/ |
||||
svg:not(:root).svg-inline--fa { |
||||
overflow: visible; } |
||||
|
||||
.svg-inline--fa { |
||||
display: inline-block; |
||||
font-size: inherit; |
||||
height: 1em; |
||||
overflow: visible; |
||||
vertical-align: -.125em; } |
||||
.svg-inline--fa.fa-lg { |
||||
vertical-align: -.225em; } |
||||
.svg-inline--fa.fa-w-1 { |
||||
width: 0.0625em; } |
||||
.svg-inline--fa.fa-w-2 { |
||||
width: 0.125em; } |
||||
.svg-inline--fa.fa-w-3 { |
||||
width: 0.1875em; } |
||||
.svg-inline--fa.fa-w-4 { |
||||
width: 0.25em; } |
||||
.svg-inline--fa.fa-w-5 { |
||||
width: 0.3125em; } |
||||
.svg-inline--fa.fa-w-6 { |
||||
width: 0.375em; } |
||||
.svg-inline--fa.fa-w-7 { |
||||
width: 0.4375em; } |
||||
.svg-inline--fa.fa-w-8 { |
||||
width: 0.5em; } |
||||
.svg-inline--fa.fa-w-9 { |
||||
width: 0.5625em; } |
||||
.svg-inline--fa.fa-w-10 { |
||||
width: 0.625em; } |
||||
.svg-inline--fa.fa-w-11 { |
||||
width: 0.6875em; } |
||||
.svg-inline--fa.fa-w-12 { |
||||
width: 0.75em; } |
||||
.svg-inline--fa.fa-w-13 { |
||||
width: 0.8125em; } |
||||
.svg-inline--fa.fa-w-14 { |
||||
width: 0.875em; } |
||||
.svg-inline--fa.fa-w-15 { |
||||
width: 0.9375em; } |
||||
.svg-inline--fa.fa-w-16 { |
||||
width: 1em; } |
||||
.svg-inline--fa.fa-w-17 { |
||||
width: 1.0625em; } |
||||
.svg-inline--fa.fa-w-18 { |
||||
width: 1.125em; } |
||||
.svg-inline--fa.fa-w-19 { |
||||
width: 1.1875em; } |
||||
.svg-inline--fa.fa-w-20 { |
||||
width: 1.25em; } |
||||
.svg-inline--fa.fa-pull-left { |
||||
margin-right: .3em; |
||||
width: auto; } |
||||
.svg-inline--fa.fa-pull-right { |
||||
margin-left: .3em; |
||||
width: auto; } |
||||
.svg-inline--fa.fa-border { |
||||
height: 1.5em; } |
||||
.svg-inline--fa.fa-li { |
||||
width: 2em; } |
||||
.svg-inline--fa.fa-fw { |
||||
width: 1.25em; } |
||||
|
||||
.fa-layers svg.svg-inline--fa { |
||||
bottom: 0; |
||||
left: 0; |
||||
margin: auto; |
||||
position: absolute; |
||||
right: 0; |
||||
top: 0; } |
||||
|
||||
.fa-layers { |
||||
display: inline-block; |
||||
height: 1em; |
||||
position: relative; |
||||
text-align: center; |
||||
vertical-align: -.125em; |
||||
width: 1em; } |
||||
.fa-layers svg.svg-inline--fa { |
||||
-webkit-transform-origin: center center; |
||||
transform-origin: center center; } |
||||
|
||||
.fa-layers-text, .fa-layers-counter { |
||||
display: inline-block; |
||||
position: absolute; |
||||
text-align: center; } |
||||
|
||||
.fa-layers-text { |
||||
left: 50%; |
||||
top: 50%; |
||||
-webkit-transform: translate(-50%, -50%); |
||||
transform: translate(-50%, -50%); |
||||
-webkit-transform-origin: center center; |
||||
transform-origin: center center; } |
||||
|
||||
.fa-layers-counter { |
||||
background-color: #ff253a; |
||||
border-radius: 1em; |
||||
-webkit-box-sizing: border-box; |
||||
box-sizing: border-box; |
||||
color: #fff; |
||||
height: 1.5em; |
||||
line-height: 1; |
||||
max-width: 5em; |
||||
min-width: 1.5em; |
||||
overflow: hidden; |
||||
padding: .25em; |
||||
right: 0; |
||||
text-overflow: ellipsis; |
||||
top: 0; |
||||
-webkit-transform: scale(0.25); |
||||
transform: scale(0.25); |
||||
-webkit-transform-origin: top right; |
||||
transform-origin: top right; } |
||||
|
||||
.fa-layers-bottom-right { |
||||
bottom: 0; |
||||
right: 0; |
||||
top: auto; |
||||
-webkit-transform: scale(0.25); |
||||
transform: scale(0.25); |
||||
-webkit-transform-origin: bottom right; |
||||
transform-origin: bottom right; } |
||||
|
||||
.fa-layers-bottom-left { |
||||
bottom: 0; |
||||
left: 0; |
||||
right: auto; |
||||
top: auto; |
||||
-webkit-transform: scale(0.25); |
||||
transform: scale(0.25); |
||||
-webkit-transform-origin: bottom left; |
||||
transform-origin: bottom left; } |
||||
|
||||
.fa-layers-top-right { |
||||
right: 0; |
||||
top: 0; |
||||
-webkit-transform: scale(0.25); |
||||
transform: scale(0.25); |
||||
-webkit-transform-origin: top right; |
||||
transform-origin: top right; } |
||||
|
||||
.fa-layers-top-left { |
||||
left: 0; |
||||
right: auto; |
||||
top: 0; |
||||
-webkit-transform: scale(0.25); |
||||
transform: scale(0.25); |
||||
-webkit-transform-origin: top left; |
||||
transform-origin: top left; } |
||||
|
||||
.fa-lg { |
||||
font-size: 1.33333em; |
||||
line-height: 0.75em; |
||||
vertical-align: -.0667em; } |
||||
|
||||
.fa-xs { |
||||
font-size: .75em; } |
||||
|
||||
.fa-sm { |
||||
font-size: .875em; } |
||||
|
||||
.fa-1x { |
||||
font-size: 1em; } |
||||
|
||||
.fa-2x { |
||||
font-size: 2em; } |
||||
|
||||
.fa-3x { |
||||
font-size: 3em; } |
||||
|
||||
.fa-4x { |
||||
font-size: 4em; } |
||||
|
||||
.fa-5x { |
||||
font-size: 5em; } |
||||
|
||||
.fa-6x { |
||||
font-size: 6em; } |
||||
|
||||
.fa-7x { |
||||
font-size: 7em; } |
||||
|
||||
.fa-8x { |
||||
font-size: 8em; } |
||||
|
||||
.fa-9x { |
||||
font-size: 9em; } |
||||
|
||||
.fa-10x { |
||||
font-size: 10em; } |
||||
|
||||
.fa-fw { |
||||
text-align: center; |
||||
width: 1.25em; } |
||||
|
||||
.fa-ul { |
||||
list-style-type: none; |
||||
margin-left: 2.5em; |
||||
padding-left: 0; } |
||||
.fa-ul > li { |
||||
position: relative; } |
||||
|
||||
.fa-li { |
||||
left: -2em; |
||||
position: absolute; |
||||
text-align: center; |
||||
width: 2em; |
||||
line-height: inherit; } |
||||
|
||||
.fa-border { |
||||
border: solid 0.08em #eee; |
||||
border-radius: .1em; |
||||
padding: .2em .25em .15em; } |
||||
|
||||
.fa-pull-left { |
||||
float: left; } |
||||
|
||||
.fa-pull-right { |
||||
float: right; } |
||||
|
||||
.fa.fa-pull-left, |
||||
.fas.fa-pull-left, |
||||
.far.fa-pull-left, |
||||
.fal.fa-pull-left, |
||||
.fab.fa-pull-left { |
||||
margin-right: .3em; } |
||||
|
||||
.fa.fa-pull-right, |
||||
.fas.fa-pull-right, |
||||
.far.fa-pull-right, |
||||
.fal.fa-pull-right, |
||||
.fab.fa-pull-right { |
||||
margin-left: .3em; } |
||||
|
||||
.fa-spin { |
||||
-webkit-animation: fa-spin 2s infinite linear; |
||||
animation: fa-spin 2s infinite linear; } |
||||
|
||||
.fa-pulse { |
||||
-webkit-animation: fa-spin 1s infinite steps(8); |
||||
animation: fa-spin 1s infinite steps(8); } |
||||
|
||||
@-webkit-keyframes fa-spin { |
||||
0% { |
||||
-webkit-transform: rotate(0deg); |
||||
transform: rotate(0deg); } |
||||
100% { |
||||
-webkit-transform: rotate(360deg); |
||||
transform: rotate(360deg); } } |
||||
|
||||
@keyframes fa-spin { |
||||
0% { |
||||
-webkit-transform: rotate(0deg); |
||||
transform: rotate(0deg); } |
||||
100% { |
||||
-webkit-transform: rotate(360deg); |
||||
transform: rotate(360deg); } } |
||||
|
||||
.fa-rotate-90 { |
||||
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; |
||||
-webkit-transform: rotate(90deg); |
||||
transform: rotate(90deg); } |
||||
|
||||
.fa-rotate-180 { |
||||
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)"; |
||||
-webkit-transform: rotate(180deg); |
||||
transform: rotate(180deg); } |
||||
|
||||
.fa-rotate-270 { |
||||
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)"; |
||||
-webkit-transform: rotate(270deg); |
||||
transform: rotate(270deg); } |
||||
|
||||
.fa-flip-horizontal { |
||||
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)"; |
||||
-webkit-transform: scale(-1, 1); |
||||
transform: scale(-1, 1); } |
||||
|
||||
.fa-flip-vertical { |
||||
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; |
||||
-webkit-transform: scale(1, -1); |
||||
transform: scale(1, -1); } |
||||
|
||||
.fa-flip-both, .fa-flip-horizontal.fa-flip-vertical { |
||||
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; |
||||
-webkit-transform: scale(-1, -1); |
||||
transform: scale(-1, -1); } |
||||
|
||||
:root .fa-rotate-90, |
||||
:root .fa-rotate-180, |
||||
:root .fa-rotate-270, |
||||
:root .fa-flip-horizontal, |
||||
:root .fa-flip-vertical, |
||||
:root .fa-flip-both { |
||||
-webkit-filter: none; |
||||
filter: none; } |
||||
|
||||
.fa-stack { |
||||
display: inline-block; |
||||
height: 2em; |
||||
position: relative; |
||||
width: 2.5em; } |
||||
|
||||
.fa-stack-1x, |
||||
.fa-stack-2x { |
||||
bottom: 0; |
||||
left: 0; |
||||
margin: auto; |
||||
position: absolute; |
||||
right: 0; |
||||
top: 0; } |
||||
|
||||
.svg-inline--fa.fa-stack-1x { |
||||
height: 1em; |
||||
width: 1.25em; } |
||||
|
||||
.svg-inline--fa.fa-stack-2x { |
||||
height: 2em; |
||||
width: 2.5em; } |
||||
|
||||
.fa-inverse { |
||||
color: #fff; } |
||||
|
||||
.sr-only { |
||||
border: 0; |
||||
clip: rect(0, 0, 0, 0); |
||||
height: 1px; |
||||
margin: -1px; |
||||
overflow: hidden; |
||||
padding: 0; |
||||
position: absolute; |
||||
width: 1px; } |
||||
|
||||
.sr-only-focusable:active, .sr-only-focusable:focus { |
||||
clip: auto; |
||||
height: auto; |
||||
margin: 0; |
||||
overflow: visible; |
||||
position: static; |
||||
width: auto; } |
||||
|
||||
.svg-inline--fa .fa-primary { |
||||
fill: var(--fa-primary-color, currentColor); |
||||
opacity: 1; |
||||
opacity: var(--fa-primary-opacity, 1); } |
||||
|
||||
.svg-inline--fa .fa-secondary { |
||||
fill: var(--fa-secondary-color, currentColor); |
||||
opacity: 0.4; |
||||
opacity: var(--fa-secondary-opacity, 0.4); } |
||||
|
||||
.svg-inline--fa.fa-swap-opacity .fa-primary { |
||||
opacity: 0.4; |
||||
opacity: var(--fa-secondary-opacity, 0.4); } |
||||
|
||||
.svg-inline--fa.fa-swap-opacity .fa-secondary { |
||||
opacity: 1; |
||||
opacity: var(--fa-primary-opacity, 1); } |
||||
|
||||
.svg-inline--fa mask .fa-primary, |
||||
.svg-inline--fa mask .fa-secondary { |
||||
fill: black; } |
||||
|
||||
.fad.fa-inverse { |
||||
color: #fff; } |
||||
|
After Width: | Height: | Size: 699 KiB |