Compare commits
40 Commits
bugfix/non
...
v2.0.0-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c13257b9e9 | ||
|
|
3f773f80ac | ||
|
|
5b23122b35 | ||
|
|
d5cbfa6749 | ||
|
|
3ad92192a9 | ||
|
|
466676d99f | ||
|
|
a1d5412465 | ||
|
|
9fdd5148ca | ||
|
|
ac957b27cb | ||
|
|
20bc332720 | ||
|
|
d2507660c2 | ||
|
|
64264c6378 | ||
|
|
ddadcdc18f | ||
|
|
4738a0e0a8 | ||
|
|
d2e4a0b0d2 | ||
|
|
9f365ed85e | ||
|
|
5e733657c2 | ||
|
|
93d9b61366 | ||
|
|
b5d289bda9 | ||
|
|
319b7a3755 | ||
|
|
410d23b4d9 | ||
|
|
003e505c4a | ||
|
|
22f09772d3 | ||
|
|
a300172adc | ||
|
|
1eba408f64 | ||
|
|
be39b293b5 | ||
|
|
31cf04a944 | ||
|
|
f5912d29b6 | ||
|
|
caad3a6b00 | ||
|
|
08f4476087 | ||
|
|
46ea3e6074 | ||
|
|
8be2a39daf | ||
|
|
7591b45ffa | ||
|
|
f5056e7232 | ||
|
|
101d344303 | ||
|
|
6ab1a4adb0 | ||
|
|
5a30425091 | ||
|
|
e9deb248f9 | ||
|
|
7d0ff8b1a2 | ||
|
|
8399cc1e57 |
2
.gitignore
vendored
@@ -28,4 +28,6 @@ v2/test/kitchensink/frontend/public
|
||||
v2/test/kitchensink/build/darwin/desktop/kitchensink
|
||||
v2/test/kitchensink/frontend/package.json.md5
|
||||
/v2/internal/ffenestri/windows/test/cmake-build-debug/
|
||||
!v2/internal/ffenestri/windows/x64/webview2.dll
|
||||
!v2/internal/ffenestri/windows/x64/WebView2Loader.dll
|
||||
.idea/
|
||||
|
||||
13
v2/.vscode/settings.json
vendored
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"ios": "c",
|
||||
"typeinfo": "c",
|
||||
"sstream": "c",
|
||||
"__functional_03": "c",
|
||||
"functional": "c",
|
||||
"__locale": "c",
|
||||
"locale": "c",
|
||||
"chrono": "c",
|
||||
"system_error": "c"
|
||||
}
|
||||
}
|
||||
54
v2/cmd/wails/internal/commands/build/README.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Build
|
||||
|
||||
The build command processes the Wails project and generates an application binary.
|
||||
|
||||
## Usage
|
||||
|
||||
`wails build <flags>`
|
||||
|
||||
### Flags
|
||||
|
||||
| Flag | Details | Default |
|
||||
| :------------- | :----------- | :------ |
|
||||
| -clean | Clean the bin directory before building | |
|
||||
| -compiler path/to/compiler | Use a different go compiler, eg go1.15beta1 | go |
|
||||
| -ldflags "custom ld flags" | Use given ldflags | |
|
||||
| -o path/to/binary | Compile to given path/filename | |
|
||||
| -k | Keep generated assets | |
|
||||
| -package | Create a platform specific package | |
|
||||
| -production | Compile in production mode: -ldflags="-w -s" + "-h windows" on Windows | |
|
||||
| -tags | Build tags to pass to Go compiler (quoted and space separated) | |
|
||||
| -upx | Compress final binary with UPX (if installed) | |
|
||||
| -upxflags "custom flags" | Flags to pass to upx | |
|
||||
| -v int | Verbosity level (0 - silent, 1 - default, 2 - verbose) | 1 |
|
||||
|
||||
## The Build Process
|
||||
|
||||
The build process is as follows:
|
||||
|
||||
- The flags are processed, and an Options struct built containing the build context.
|
||||
- The type of target is determined, and a custom build process is followed for target.
|
||||
|
||||
### Desktop Target
|
||||
|
||||
- The frontend dependencies are installed. The command is read from the project file `wails.json` under the key `frontend:install` and executed in the `frontend` directory. If this is not defined, it is ignored.
|
||||
- The frontend is then built. This command is read from the project file `wails.json` under the key `frontend:install` and executed in the `frontend` directory. If this is not defined, it is ignored.
|
||||
- The project directory is checked to see if the `build` directory exists. If not, it is created and default project assets are copied to it.
|
||||
- An asset bundle is then created by reading the `html` key from `wails.json` and loading the referenced file. This is then parsed, looking for local Javascript and CSS references. Those files are in turn loaded into memory, converted to C data and saved into the asset bundle located at `build/assets.h`, which also includes the original HTML.
|
||||
- The application icon is then processed: if there is no `build/appicon.png`, a default icon is copied. On Windows, an `app.ico` file is generated from this png. On Mac, `icons.icns` is generated.
|
||||
- If there are icons in the `build/tray` directory, these are processed, converted to C data and saved as `build/trayicons.h`, ready for the compilation step.
|
||||
- If there are icons in the `build/dialog` directory, these are processed, converted to C data and saved as `build/userdialogicons.h`, ready for the compilation step.
|
||||
- If the `-package` flag is given for a Windows target, the Windows assets in the `build/windows` directory are processed: manifest + icons compiled to a `.syso` file (deleted after compilation).
|
||||
- If we are building a universal binary for Mac, the application is compiled for both `arm64` and `amd64`. The `lipo` tool is then executed to create the universal binary.
|
||||
- If we are not building a universal binary for Mac, the application is built using `go build`, using build tags to indicate type of application and build mode (debug/production).
|
||||
- If the `-upx` flag was provided, `upx` is invoked to compress the binary. Custom flags may be provided using the `-upxflags` flag.
|
||||
- If the `package` flag is given for a non Windows target, the application is bundled for the platform. On Mac, this creates a `.app` with the processed icons, the `Info.plist` in `build/darwin` and the compiled binary.
|
||||
|
||||
### Server Target
|
||||
|
||||
TBD
|
||||
|
||||
### Hybrid Target
|
||||
|
||||
TBD
|
||||
|
||||
@@ -36,7 +36,10 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
||||
command.StringFlag("compiler", "Use a different go compiler to build, eg go1.15beta1", &compilerCommand)
|
||||
|
||||
compress := false
|
||||
command.BoolFlag("compress", "Compress final binary", &compress)
|
||||
command.BoolFlag("upx", "Compress final binary with UPX (if installed)", &compress)
|
||||
|
||||
compressFlags := ""
|
||||
command.StringFlag("upxflags", "Flags to pass to upx", &compressFlags)
|
||||
|
||||
// Setup Platform flag
|
||||
platform := runtime.GOOS
|
||||
@@ -95,6 +98,7 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
||||
"darwin/amd64",
|
||||
"darwin/arm64",
|
||||
"darwin/universal",
|
||||
"linux",
|
||||
//"linux/amd64",
|
||||
//"linux/arm-7",
|
||||
"windows",
|
||||
@@ -131,6 +135,7 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
||||
KeepAssets: keepAssets,
|
||||
Verbosity: verbosity,
|
||||
Compress: compress,
|
||||
CompressFlags: compressFlags,
|
||||
UserTags: userTags,
|
||||
}
|
||||
|
||||
|
||||
22
v2/cmd/wails/internal/commands/dev/README.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Dev
|
||||
|
||||
The dev command allows you to develop your application through a standard browser.
|
||||
|
||||
## Usage
|
||||
|
||||
`wails dev <flags>`
|
||||
|
||||
### Flags
|
||||
|
||||
| Flag | Details | Default |
|
||||
| :------------- | :----------- | :------ |
|
||||
| -compiler path/to/compiler | Use a different go compiler, eg go1.15beta1 | go |
|
||||
| -ldflags "custom ld flags" | Use given ldflags | |
|
||||
| -e list,of,extensions | File extensions to trigger rebuilds | go |
|
||||
| -w | Show warnings | false |
|
||||
| -v int | Verbosity level (0 - silent, 1 - default, 2 - verbose) | 1 |
|
||||
| -loglevel | Loglevel to pass to the application - Trace, Debug, Info, Warning, Error | Debug |
|
||||
|
||||
## How it works
|
||||
|
||||
The project is built using a special mode that starts a webserver and starts listening to port 34115. When the frontend project is run independently, so long as the JS is wrapped with the runtime method `ready`, then the frontend will connect to the backend code via websockets. The interface should be present in your browser, and you should be able to interact with the backend as you would in a desktop app.
|
||||
@@ -3,6 +3,7 @@ package dev
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
@@ -57,6 +58,10 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
||||
showWarnings := false
|
||||
command.BoolFlag("w", "Show warnings", &showWarnings)
|
||||
|
||||
// Verbosity
|
||||
verbosity := 1
|
||||
command.IntFlag("v", "Verbosity level (0 - silent, 1 - default, 2 - verbose)", &verbosity)
|
||||
|
||||
loglevel := ""
|
||||
command.StringFlag("loglevel", "Loglevel to use - Trace, Debug, Info, Warning, Error", &loglevel)
|
||||
|
||||
@@ -72,7 +77,12 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer watcher.Close()
|
||||
defer func(watcher *fsnotify.Watcher) {
|
||||
err := watcher.Close()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}(watcher)
|
||||
|
||||
var debugBinaryProcess *process.Process = nil
|
||||
var extensionsThatTriggerARebuild = strings.Split(extensions, ",")
|
||||
@@ -83,15 +93,22 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
||||
|
||||
debounceQuit := make(chan bool, 1)
|
||||
|
||||
var passthruArgs []string
|
||||
//if len(os.Args) > 2 {
|
||||
// passthruArgs = os.Args[2:]
|
||||
//}
|
||||
|
||||
// Do initial build
|
||||
logger.Println("Building application for development...")
|
||||
newProcess, err := restartApp(logger, "dev", ldflags, compilerCommand, debugBinaryProcess, loglevel)
|
||||
newProcess, appBinary, err := restartApp(logger, ldflags, compilerCommand, debugBinaryProcess, loglevel, passthruArgs, verbosity)
|
||||
if newProcess != nil {
|
||||
debugBinaryProcess = newProcess
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var newBinaryProcess *process.Process
|
||||
go debounce(100*time.Millisecond, watcher.Events, debounceQuit, func(event fsnotify.Event) {
|
||||
// logger.Println("event: %+v", event)
|
||||
|
||||
@@ -135,7 +152,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
||||
// Do a rebuild
|
||||
|
||||
// Try and build the app
|
||||
newBinaryProcess, err := restartApp(logger, "dev", ldflags, compilerCommand, debugBinaryProcess, loglevel)
|
||||
newBinaryProcess, _, err = restartApp(logger, ldflags, compilerCommand, debugBinaryProcess, loglevel, passthruArgs, verbosity)
|
||||
if err != nil {
|
||||
fmt.Printf("Error during build: %s", err.Error())
|
||||
return
|
||||
@@ -197,6 +214,12 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Remove dev binary
|
||||
err = os.Remove(appBinary)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
LogGreen("Development mode exited")
|
||||
|
||||
return nil
|
||||
@@ -224,14 +247,14 @@ exit:
|
||||
}
|
||||
}
|
||||
|
||||
func restartApp(logger *clilogger.CLILogger, outputType string, ldflags string, compilerCommand string, debugBinaryProcess *process.Process, loglevel string) (*process.Process, error) {
|
||||
func restartApp(logger *clilogger.CLILogger, ldflags string, compilerCommand string, debugBinaryProcess *process.Process, loglevel string, passthruArgs []string, verbosity int) (*process.Process, string, error) {
|
||||
|
||||
appBinary, err := buildApp(logger, outputType, ldflags, compilerCommand)
|
||||
appBinary, err := buildApp(logger, ldflags, compilerCommand, verbosity)
|
||||
println()
|
||||
if err != nil {
|
||||
LogRed("Build error - continuing to run current version")
|
||||
LogDarkYellow(err.Error())
|
||||
return nil, nil
|
||||
return nil, "", nil
|
||||
}
|
||||
|
||||
// Kill existing binary if need be
|
||||
@@ -247,8 +270,12 @@ func restartApp(logger *clilogger.CLILogger, outputType string, ldflags string,
|
||||
|
||||
// TODO: Generate `backend.js`
|
||||
|
||||
// Start up new binary
|
||||
newProcess := process.NewProcess(logger, appBinary, "-loglevel", loglevel)
|
||||
// Start up new binary with correct args
|
||||
var args = []string{"-loglevel", loglevel}
|
||||
if len(passthruArgs) > 0 {
|
||||
args = append(args, passthruArgs...)
|
||||
}
|
||||
newProcess := process.NewProcess(logger, appBinary, args...)
|
||||
err = newProcess.Start()
|
||||
if err != nil {
|
||||
// Remove binary
|
||||
@@ -259,18 +286,21 @@ func restartApp(logger *clilogger.CLILogger, outputType string, ldflags string,
|
||||
logger.Fatal("Unable to start application: %s", err.Error())
|
||||
}
|
||||
|
||||
return newProcess, nil
|
||||
return newProcess, appBinary, nil
|
||||
}
|
||||
|
||||
func buildApp(logger *clilogger.CLILogger, outputType string, ldflags string, compilerCommand string) (string, error) {
|
||||
func buildApp(logger *clilogger.CLILogger, ldflags string, compilerCommand string, verbosity int) (string, error) {
|
||||
|
||||
// Create random output file
|
||||
outputFile := fmt.Sprintf("dev-%d", time.Now().Unix())
|
||||
outputFile := "wailsdev"
|
||||
if runtime.GOOS == "windows" {
|
||||
outputFile += ".exe"
|
||||
}
|
||||
|
||||
// Create BuildOptions
|
||||
buildOptions := &build.Options{
|
||||
Logger: logger,
|
||||
OutputType: outputType,
|
||||
OutputType: "dev",
|
||||
Mode: build.Debug,
|
||||
Pack: false,
|
||||
Platform: runtime.GOOS,
|
||||
@@ -278,6 +308,7 @@ func buildApp(logger *clilogger.CLILogger, outputType string, ldflags string, co
|
||||
Compiler: compilerCommand,
|
||||
OutputFile: outputFile,
|
||||
IgnoreFrontend: true,
|
||||
Verbosity: verbosity,
|
||||
}
|
||||
|
||||
return build.Build(buildOptions)
|
||||
|
||||
@@ -3,7 +3,6 @@ package doctor
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
@@ -25,11 +24,13 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
||||
logger := clilogger.New(w)
|
||||
|
||||
app.PrintBanner()
|
||||
logger.Print("Scanning system - please wait...")
|
||||
|
||||
logger.Print("Scanning system - Please wait (this may take a long time)...")
|
||||
|
||||
// Get system info
|
||||
info, err := system.GetInfo()
|
||||
if err != nil {
|
||||
logger.Println("Failed.")
|
||||
return err
|
||||
}
|
||||
logger.Println("Done.")
|
||||
@@ -39,25 +40,22 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
||||
w.Init(os.Stdout, 8, 8, 0, '\t', 0)
|
||||
|
||||
// Write out the system information
|
||||
fmt.Fprintf(w, "\n")
|
||||
fmt.Fprintf(w, "System\n")
|
||||
fmt.Fprintf(w, "------\n")
|
||||
fmt.Fprintf(w, "%s\t%s\n", "OS:", info.OS.Name)
|
||||
fmt.Fprintf(w, "%s\t%s\n", "Version: ", info.OS.Version)
|
||||
fmt.Fprintf(w, "%s\t%s\n", "ID:", info.OS.ID)
|
||||
|
||||
// Exit early if PM not found
|
||||
if info.PM == nil {
|
||||
w.Flush()
|
||||
return nil
|
||||
}
|
||||
fmt.Fprintf(w, "%s\t%s\n", "Package Manager: ", info.PM.Name())
|
||||
|
||||
// Output Go Information
|
||||
fmt.Fprintf(w, "%s\t%s\n", "Go Version:", runtime.Version())
|
||||
fmt.Fprintf(w, "%s\t%s\n", "Platform:", runtime.GOOS)
|
||||
fmt.Fprintf(w, "%s\t%s\n", "Architecture:", runtime.GOARCH)
|
||||
|
||||
// Exit early if PM not found
|
||||
if info.PM != nil {
|
||||
fmt.Fprintf(w, "%s\t%s\n", "Package Manager: ", info.PM.Name())
|
||||
}
|
||||
|
||||
// Output Dependencies Status
|
||||
var dependenciesMissing = []string{}
|
||||
var externalPackages = []*packagemanager.Dependancy{}
|
||||
@@ -67,12 +65,14 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
||||
fmt.Fprintf(w, "Dependency\tPackage Name\tStatus\tVersion\n")
|
||||
fmt.Fprintf(w, "----------\t------------\t------\t-------\n")
|
||||
|
||||
hasOptionalDependencies := false
|
||||
// Loop over dependencies
|
||||
for _, dependency := range info.Dependencies {
|
||||
|
||||
name := dependency.Name
|
||||
if dependency.Optional {
|
||||
name += "*"
|
||||
name = "*" + name
|
||||
hasOptionalDependencies = true
|
||||
}
|
||||
packageName := "Unknown"
|
||||
status := "Not Found"
|
||||
@@ -107,44 +107,48 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
||||
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", name, packageName, status, dependency.Version)
|
||||
}
|
||||
fmt.Fprintf(w, "\n")
|
||||
fmt.Fprintf(w, "* - Optional Dependency\n")
|
||||
if hasOptionalDependencies {
|
||||
fmt.Fprintf(w, "\n")
|
||||
fmt.Fprintf(w, "* - Optional Dependency\n")
|
||||
}
|
||||
w.Flush()
|
||||
logger.Println("")
|
||||
logger.Println("Diagnosis")
|
||||
logger.Println("---------\n")
|
||||
logger.Println("---------")
|
||||
|
||||
// Generate an appropriate diagnosis
|
||||
|
||||
if len(dependenciesMissing) == 0 && dependenciesAvailableRequired == 0 {
|
||||
logger.Println("Your system is ready for Wails development!")
|
||||
} else {
|
||||
logger.Println("Your system has missing dependencies!\n")
|
||||
}
|
||||
|
||||
if dependenciesAvailableRequired != 0 {
|
||||
log.Println("Install required packages using: " + info.Dependencies.InstallAllRequiredCommand())
|
||||
logger.Println("Required package(s) installation details: \n" + info.Dependencies.InstallAllRequiredCommand())
|
||||
}
|
||||
|
||||
if dependenciesAvailableOptional != 0 {
|
||||
log.Println("Install optional packages using: " + info.Dependencies.InstallAllOptionalCommand())
|
||||
}
|
||||
|
||||
if len(externalPackages) > 0 {
|
||||
for _, p := range externalPackages {
|
||||
if p.Optional {
|
||||
print("[Optional] ")
|
||||
}
|
||||
log.Println("Install " + p.Name + ": " + p.InstallCommand)
|
||||
}
|
||||
logger.Println("Optional package(s) installation details: \n" + info.Dependencies.InstallAllOptionalCommand())
|
||||
}
|
||||
//
|
||||
//if len(externalPackages) > 0 {
|
||||
// for _, p := range externalPackages {
|
||||
// if p.Optional {
|
||||
// print("[Optional] ")
|
||||
// }
|
||||
// logger.Println("Install " + p.Name + ": " + p.InstallCommand)
|
||||
// }
|
||||
//}
|
||||
|
||||
if len(dependenciesMissing) != 0 {
|
||||
// TODO: Check if apps are available locally and if so, adjust the diagnosis
|
||||
log.Println("Fatal:")
|
||||
log.Println("Required dependencies missing: " + strings.Join(dependenciesMissing, " "))
|
||||
log.Println("Please read this article on how to resolve this: https://wails.app/guides/resolving-missing-packages")
|
||||
logger.Println("Fatal:")
|
||||
logger.Println("Required dependencies missing: " + strings.Join(dependenciesMissing, " "))
|
||||
logger.Println("Please read this article on how to resolve this: https://wails.app/guides/resolving-missing-packages")
|
||||
}
|
||||
|
||||
log.Println("")
|
||||
logger.Println("")
|
||||
return nil
|
||||
})
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package initialise
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/wailsapp/wails/v2/pkg/buildassets"
|
||||
"io"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -40,7 +41,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
||||
|
||||
// Quiet Init
|
||||
quiet := false
|
||||
command.BoolFlag("q", "Supress output to console", &quiet)
|
||||
command.BoolFlag("q", "Suppress output to console", &quiet)
|
||||
|
||||
initGit := false
|
||||
gitInstalled := git.IsInstalled()
|
||||
@@ -106,10 +107,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
||||
}
|
||||
|
||||
// Try to discover author details from git config
|
||||
err := findAuthorDetails(options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
findAuthorDetails(options)
|
||||
|
||||
return initProject(options)
|
||||
})
|
||||
@@ -129,6 +127,12 @@ func initProject(options *templates.Options) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Install the default assets
|
||||
err = buildassets.Install(options.TargetDir, options.ProjectName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if options.InitGit {
|
||||
err = initGit(options)
|
||||
if err != nil {
|
||||
@@ -164,20 +168,18 @@ func initGit(options *templates.Options) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func findAuthorDetails(options *templates.Options) error {
|
||||
// findAuthorDetails tries to find the user's name and email
|
||||
// from gitconfig. If it finds them, it stores them in the project options
|
||||
func findAuthorDetails(options *templates.Options) {
|
||||
if git.IsInstalled() {
|
||||
name, err := git.Name()
|
||||
if err != nil {
|
||||
return err
|
||||
if err == nil {
|
||||
options.AuthorName = strings.TrimSpace(name)
|
||||
}
|
||||
options.AuthorName = strings.TrimSpace(name)
|
||||
|
||||
email, err := git.Email()
|
||||
if err != nil {
|
||||
return err
|
||||
if err == nil {
|
||||
options.AuthorEmail = strings.TrimSpace(email)
|
||||
}
|
||||
options.AuthorEmail = strings.TrimSpace(email)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
# README
|
||||
|
||||
## About
|
||||
|
||||
This template uses vanilla JS / HTML and CSS. [Rollup](https://rollupjs.org/guide/en/) is used for processing and bundling the files.
|
||||
|
||||
## Building
|
||||
|
||||
To build this project in debug mode, use `wails build`. For production, use `wails build -production`.
|
||||
To generate a platform native package, add the `-package` flag.
|
||||
|
||||
## Live Development
|
||||
|
||||
To run in live development mode, run `wails dev` in the project directory. In another terminal, go into the `frontend`
|
||||
directory and run `npm run dev`. The frontend dev server will run on http://localhost:5000. Connect to this
|
||||
in your browser and connect to your application.
|
||||
2605
v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/package-lock.json
generated
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "vanilla",
|
||||
"version": "1.0.0",
|
||||
"description": "Vanilla Wails v2 template",
|
||||
"main": "src/main.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"build": "rollup -c",
|
||||
"dev": "rollup -c -w",
|
||||
"start": "sirv dist"
|
||||
},
|
||||
"author": "{{.AuthorName}}",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@rollup/plugin-commonjs": "^19.0.0",
|
||||
"@rollup/plugin-image": "^2.0.6",
|
||||
"@rollup/plugin-node-resolve": "^13.0.0",
|
||||
"@rollup/plugin-url": "^6.0.0",
|
||||
"@wails/runtime": "^1.3.19",
|
||||
"rollup": "^2.50.4",
|
||||
"rollup-plugin-copy": "^3.4.0",
|
||||
"rollup-plugin-livereload": "^2.0.0",
|
||||
"rollup-plugin-postcss": "^4.0.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"sirv-cli": "^1.0.12"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
import resolve from '@rollup/plugin-node-resolve';
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import livereload from 'rollup-plugin-livereload';
|
||||
import { terser } from 'rollup-plugin-terser';
|
||||
import postcss from 'rollup-plugin-postcss';
|
||||
import image from '@rollup/plugin-image';
|
||||
import url from '@rollup/plugin-url';
|
||||
import copy from 'rollup-plugin-copy';
|
||||
|
||||
const production = !process.env.ROLLUP_WATCH;
|
||||
|
||||
export default {
|
||||
input: 'src/main.js',
|
||||
output: {
|
||||
sourcemap: true,
|
||||
format: 'iife',
|
||||
name: 'app',
|
||||
file: 'dist/main.js'
|
||||
},
|
||||
onwarn: handleRollupWarning,
|
||||
plugins: [
|
||||
|
||||
image(),
|
||||
|
||||
copy({
|
||||
targets: [
|
||||
{ src: 'src/index.html', dest: 'dist' },
|
||||
{ src: 'src/main.css', dest: 'dist' },
|
||||
]
|
||||
}),
|
||||
|
||||
// Embed binary files
|
||||
url({
|
||||
include: ['**/*.woff', '**/*.woff2'],
|
||||
limit: Infinity,
|
||||
}),
|
||||
|
||||
// If you have external dependencies installed from
|
||||
// npm, you'll most likely need these plugins. In
|
||||
// some cases you'll need additional configuration -
|
||||
// consult the documentation for details:
|
||||
// https://github.com/rollup/plugins/tree/master/packages/commonjs
|
||||
resolve({
|
||||
browser: true,
|
||||
}),
|
||||
commonjs(),
|
||||
|
||||
// PostCSS preprocessing
|
||||
postcss({
|
||||
extensions: ['.css', '.scss'],
|
||||
extract: true,
|
||||
minimize: false,
|
||||
use: [
|
||||
['sass', {
|
||||
includePaths: [
|
||||
'./src',
|
||||
'./node_modules'
|
||||
]
|
||||
}]
|
||||
],
|
||||
}),
|
||||
|
||||
// In dev mode, call `npm run start` once
|
||||
// the bundle has been generated
|
||||
!production && serve(),
|
||||
|
||||
// Watch the `public` directory and refresh the
|
||||
// browser on changes when not in production
|
||||
!production && livereload('dist'),
|
||||
|
||||
// If we're building for production (npm run build
|
||||
// instead of npm run dev), minify
|
||||
production && terser()
|
||||
],
|
||||
watch: {
|
||||
clearScreen: false
|
||||
}
|
||||
};
|
||||
|
||||
function handleRollupWarning(warning) {
|
||||
console.error('ERROR: ' + warning.toString());
|
||||
}
|
||||
|
||||
function serve() {
|
||||
let server;
|
||||
|
||||
function toExit() {
|
||||
if (server) server.kill(0);
|
||||
}
|
||||
|
||||
return {
|
||||
writeBundle() {
|
||||
if (server) return;
|
||||
server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
|
||||
stdio: ['ignore', 'inherit', 'inherit'],
|
||||
shell: true
|
||||
});
|
||||
|
||||
process.on('SIGTERM', toExit);
|
||||
process.on('exit', toExit);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,16 +1,21 @@
|
||||
// Get input + focus
|
||||
let nameElement = document.getElementById("name");
|
||||
nameElement.focus();
|
||||
|
||||
// Setup the greet function
|
||||
window.greet = function () {
|
||||
import {ready} from '@wails/runtime';
|
||||
|
||||
// Get name
|
||||
let name = nameElement.value;
|
||||
ready( () => {
|
||||
// Get input + focus
|
||||
let nameElement = document.getElementById("name");
|
||||
nameElement.focus();
|
||||
|
||||
// Call Basic.Greet(name)
|
||||
window.backend.main.Basic.Greet(name).then((result) => {
|
||||
// Update result with data back from Basic.Greet()
|
||||
document.getElementById("result").innerText = result;
|
||||
});
|
||||
}
|
||||
// Setup the greet function
|
||||
window.greet = function () {
|
||||
|
||||
// Get name
|
||||
let name = nameElement.value;
|
||||
|
||||
// Call Basic.Greet(name)
|
||||
window.backend.main.Basic.Greet(name).then((result) => {
|
||||
// Update result with data back from Basic.Greet()
|
||||
document.getElementById("result").innerText = result;
|
||||
});
|
||||
};
|
||||
});
|
||||
@@ -1,7 +1,9 @@
|
||||
{
|
||||
"name": "{{.ProjectName}}",
|
||||
"outputfilename": "{{.BinaryName}}",
|
||||
"html": "frontend/src/index.html",
|
||||
"html": "frontend/dist/index.html",
|
||||
"frontend:build": "npm run build",
|
||||
"frontend:install": "npm ci",
|
||||
"author": {
|
||||
"name": "{{.AuthorName}}",
|
||||
"email": "{{.AuthorEmail}}"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
package main
|
||||
|
||||
var version = "v2.0.0-alpha.65"
|
||||
var version = "v2.0.0-alpha.66"
|
||||
|
||||
@@ -10,10 +10,11 @@ require (
|
||||
github.com/imdario/mergo v0.3.11
|
||||
github.com/jackmordaunt/icns v1.0.0
|
||||
github.com/leaanthony/clir v1.0.4
|
||||
github.com/leaanthony/debme v1.1.2
|
||||
github.com/leaanthony/debme v1.2.0
|
||||
github.com/leaanthony/go-ansi-parser v1.0.1
|
||||
github.com/leaanthony/gosod v1.0.1
|
||||
github.com/leaanthony/slicer v1.5.0
|
||||
github.com/leaanthony/winicon v0.0.0-20200606125418-4419cea822a0
|
||||
github.com/matryer/is v1.4.0
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.4
|
||||
|
||||
@@ -42,14 +42,16 @@ github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs
|
||||
github.com/leaanthony/clir v1.0.4 h1:Dov2y9zWJmZr7CjaCe86lKa4b5CSxskGAt2yBkoDyiU=
|
||||
github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0=
|
||||
github.com/leaanthony/debme v1.1.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA=
|
||||
github.com/leaanthony/debme v1.1.2 h1:dGeQuj0+xPIlDQzGIjmAU52+yRg85u5pWaaqrdLBjD0=
|
||||
github.com/leaanthony/debme v1.1.2/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA=
|
||||
github.com/leaanthony/debme v1.2.0 h1:i7JUQhuv7PtJ/7qV+SIa5QARTGBcojUZ+2eCiV9begU=
|
||||
github.com/leaanthony/debme v1.2.0/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA=
|
||||
github.com/leaanthony/go-ansi-parser v1.0.1 h1:97v6c5kYppVsbScf4r/VZdXyQ21KQIfeQOk2DgKxGG4=
|
||||
github.com/leaanthony/go-ansi-parser v1.0.1/go.mod h1:7arTzgVI47srICYhvgUV4CGd063sGEeoSlych5yeSPM=
|
||||
github.com/leaanthony/gosod v1.0.1 h1:F+4c3DmEBfigi7oAswCV2RpQ+k4DcNbhuCZUGdBHacQ=
|
||||
github.com/leaanthony/gosod v1.0.1/go.mod h1:W8RyeSFBXu7RpIxPGEJfW4moSyGGEjlJMLV25wEbAdU=
|
||||
github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0HtY=
|
||||
github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
|
||||
github.com/leaanthony/winicon v0.0.0-20200606125418-4419cea822a0 h1:FPGYnfxuuxqCZhrGq8nKjthEcYHgHmFbyY953Xv9cNI=
|
||||
github.com/leaanthony/winicon v0.0.0-20200606125418-4419cea822a0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU=
|
||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
|
||||
@@ -92,6 +94,8 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw=
|
||||
golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
|
||||
@@ -79,7 +79,7 @@ func (a *App) Run() error {
|
||||
// Default app options
|
||||
var port = 8080
|
||||
var ip = "localhost"
|
||||
var supressLogging = false
|
||||
var SuppressLogging = false
|
||||
var debugMode = false
|
||||
|
||||
// Create CLI
|
||||
@@ -89,7 +89,7 @@ func (a *App) Run() error {
|
||||
cli.IntFlag("p", "Port to serve on", &port)
|
||||
cli.StringFlag("i", "IP to serve on", &ip)
|
||||
cli.BoolFlag("d", "Debug mode", &debugMode)
|
||||
cli.BoolFlag("q", "Supress logging", &supressLogging)
|
||||
cli.BoolFlag("q", "Suppress logging", &SuppressLogging)
|
||||
|
||||
// Setup main action
|
||||
cli.Action(func() error {
|
||||
@@ -98,8 +98,8 @@ func (a *App) Run() error {
|
||||
a.webserver.SetPort(port)
|
||||
a.webserver.SetIP(ip)
|
||||
a.webserver.SetBindings(a.bindings)
|
||||
// Log information (if we aren't supressing it)
|
||||
if !supressLogging {
|
||||
// Log information (if we aren't Suppressing it)
|
||||
if !SuppressLogging {
|
||||
cli.PrintBanner()
|
||||
a.logger.Info("Running server at %s", a.webserver.URL())
|
||||
}
|
||||
|
||||
1
v2/internal/bridge/linux.js
Normal file
@@ -18,6 +18,12 @@ import (
|
||||
//go:embed darwin.js
|
||||
var darwinRuntime string
|
||||
|
||||
//go:embed windows.js
|
||||
var windowsRuntime string
|
||||
|
||||
//go:embed linux.js
|
||||
var linuxRuntime string
|
||||
|
||||
// session represents a single websocket session
|
||||
type session struct {
|
||||
bindings string
|
||||
@@ -84,6 +90,10 @@ func (s *session) start(firstSession bool) {
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
wailsRuntime = darwinRuntime
|
||||
case "windows":
|
||||
wailsRuntime = windowsRuntime
|
||||
case "linux":
|
||||
wailsRuntime = linuxRuntime
|
||||
default:
|
||||
log.Fatal("platform not supported")
|
||||
}
|
||||
@@ -92,7 +102,10 @@ func (s *session) start(firstSession bool) {
|
||||
s.log.Info(bindingsMessage)
|
||||
bootstrapMessage := bindingsMessage + wailsRuntime
|
||||
|
||||
s.sendMessage("b" + bootstrapMessage)
|
||||
err := s.sendMessage("b" + bootstrapMessage)
|
||||
if err != nil {
|
||||
s.log.Error(err.Error())
|
||||
}
|
||||
|
||||
// Send menus
|
||||
traymenus, err := s.menumanager.GetTrayMenus()
|
||||
@@ -101,7 +114,10 @@ func (s *session) start(firstSession bool) {
|
||||
}
|
||||
|
||||
for _, trayMenu := range traymenus {
|
||||
s.sendMessage("TS" + trayMenu)
|
||||
err := s.sendMessage("TS" + trayMenu)
|
||||
if err != nil {
|
||||
s.log.Error(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
@@ -130,7 +146,10 @@ func (s *session) start(firstSession bool) {
|
||||
|
||||
// Shutdown
|
||||
func (s *session) Shutdown() {
|
||||
s.conn.Close()
|
||||
err := s.conn.Close()
|
||||
if err != nil {
|
||||
s.log.Error(err.Error())
|
||||
}
|
||||
s.done = true
|
||||
s.log.Info("session %v exit", s.Identifier())
|
||||
}
|
||||
@@ -146,10 +165,16 @@ func (s *session) writePump() {
|
||||
s.Shutdown()
|
||||
return
|
||||
case msg, ok := <-s.writeChan:
|
||||
s.conn.SetWriteDeadline(time.Now().Add(1 * time.Second))
|
||||
err := s.conn.SetWriteDeadline(time.Now().Add(1 * time.Second))
|
||||
if err != nil {
|
||||
s.log.Error(err.Error())
|
||||
}
|
||||
if !ok {
|
||||
s.log.Debug("writeChan was closed!")
|
||||
s.conn.WriteMessage(websocket.CloseMessage, []byte{})
|
||||
err := s.conn.WriteMessage(websocket.CloseMessage, []byte{})
|
||||
if err != nil {
|
||||
s.log.Error(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -983,7 +983,7 @@ void SaveDialog(struct Application *app, char *callbackID, char *title, char *fi
|
||||
);
|
||||
}
|
||||
|
||||
const char *invoke = "window.external={invoke:function(x){window.webkit.messageHandlers.external.postMessage(x);}};";
|
||||
const char *invoke = "window.wailsInvoke=function(message){window.webkit.messageHandlers.external.postMessage(message);};window.wailsDrag=function(message){window.webkit.messageHandlers.windowDrag.postMessage(message);};window.wailsContextMenuMessage=function(message){window.webkit.messageHandlers.contextMenu.postMessage(message);};";
|
||||
|
||||
// DisableFrame disables the window frame
|
||||
void DisableFrame(struct Application *app)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#ifndef __FFENESTRI_LINUX_H__
|
||||
#define __FFENESTRI_LINUX_H__
|
||||
|
||||
#include "common.h"
|
||||
#include "gtk/gtk.h"
|
||||
#include "webkit2/webkit2.h"
|
||||
#include <time.h>
|
||||
@@ -11,9 +12,10 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
// References to assets
|
||||
extern const unsigned char *assets[];
|
||||
extern const unsigned char runtime;
|
||||
extern const char *icon[];
|
||||
|
||||
#include "icon.h"
|
||||
#include "assets.h"
|
||||
|
||||
// Constants
|
||||
#define PRIMARY_MOUSE_BUTTON 1
|
||||
@@ -23,17 +25,6 @@ extern const char *icon[];
|
||||
// MAIN DEBUG FLAG
|
||||
int debug;
|
||||
|
||||
// Credit: https://stackoverflow.com/a/8465083
|
||||
char *concat(const char *s1, const char *s2)
|
||||
{
|
||||
const size_t len1 = strlen(s1);
|
||||
const size_t len2 = strlen(s2);
|
||||
char *result = malloc(len1 + len2 + 1);
|
||||
memcpy(result, s1, len1);
|
||||
memcpy(result + len1, s2, len2 + 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Debug works like sprintf but mutes if the global debug flag is true
|
||||
// Credit: https://stackoverflow.com/a/20639708
|
||||
void Debug(char *message, ...)
|
||||
@@ -312,17 +303,17 @@ void SetMaxWindowSize(struct Application *app, int maxWidth, int maxHeight)
|
||||
}
|
||||
|
||||
// SetColour sets the colour of the webview to the given colour string
|
||||
int SetColour(struct Application *app, const char *colourString)
|
||||
void SetColour(struct Application *app, int red, int green, int blue, int alpha)
|
||||
{
|
||||
GdkRGBA rgba;
|
||||
gboolean result = gdk_rgba_parse(&rgba, colourString);
|
||||
if (result == FALSE)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// Debug("Setting webview colour to: %s", colourString);
|
||||
webkit_web_view_get_background_color((WebKitWebView *)(app->webView), &rgba);
|
||||
return 1;
|
||||
// GdkRGBA rgba;
|
||||
// rgba.
|
||||
// gboolean result = gdk_rgba_parse(&rgba, colourString);
|
||||
// if (result == FALSE)
|
||||
// {
|
||||
// return 0;
|
||||
// }
|
||||
// // Debug("Setting webview colour to: %s", colourString);
|
||||
// webkit_web_view_get_background_color((WebKitWebView *)(app->webView), &rgba);
|
||||
}
|
||||
|
||||
// DisableFrame disables the window frame
|
||||
@@ -523,6 +514,11 @@ static void load_finished_cb(WebKitWebView *webView,
|
||||
Debug("Binding Methods");
|
||||
syncEval(app, app->bindings);
|
||||
|
||||
// Setup IPC commands
|
||||
Debug("Setting up IPC methods");
|
||||
const char *invoke = "window.wailsInvoke=function(message){window.webkit.messageHandlers.external.postMessage(message);};window.wailsDrag=function(message){window.webkit.messageHandlers.windowDrag.postMessage(message);};window.wailsContextMenuMessage=function(message){window.webkit.messageHandlers.contextMenu.postMessage(message);};";
|
||||
syncEval(app, invoke);
|
||||
|
||||
// Runtime
|
||||
Debug("Setting up Wails runtime");
|
||||
syncEval(app, &runtime);
|
||||
@@ -824,7 +820,7 @@ void Show(struct Application *app) {
|
||||
|
||||
// maximiseInternal maximises the main window
|
||||
void maximiseInternal(struct Application *app) {
|
||||
gtk_window_maximize(GTK_WIDGET(app->mainWindow));
|
||||
gtk_window_maximize(GTK_WINDOW(app->mainWindow));
|
||||
}
|
||||
|
||||
// Maximise places the maximiseInternal method onto the main thread for execution
|
||||
@@ -841,7 +837,7 @@ void Maximise(struct Application *app) {
|
||||
|
||||
// unmaximiseInternal unmaximises the main window
|
||||
void unmaximiseInternal(struct Application *app) {
|
||||
gtk_window_unmaximize(GTK_WIDGET(app->mainWindow));
|
||||
gtk_window_unmaximize(GTK_WINDOW(app->mainWindow));
|
||||
}
|
||||
|
||||
// Unmaximise places the unmaximiseInternal method onto the main thread for execution
|
||||
@@ -857,6 +853,21 @@ void Unmaximise(struct Application *app) {
|
||||
}
|
||||
|
||||
|
||||
void DarkModeEnabled(struct Application* app, char *callbackID) {}
|
||||
void SetApplicationMenu(struct Application* app, const char *menuJSON) {}
|
||||
void AddTrayMenu(struct Application* app, const char *menuTrayJSON) {}
|
||||
void SetTrayMenu(struct Application* app, const char *menuTrayJSON) {}
|
||||
void DeleteTrayMenuByID(struct Application* app, const char *id) {}
|
||||
void UpdateTrayMenuLabel(struct Application* app, const char* JSON) {}
|
||||
void AddContextMenu(struct Application* app, char *contextMenuJSON) {}
|
||||
void UpdateContextMenu(struct Application* app, char *contextMenuJSON) {}
|
||||
void WebviewIsTransparent(struct Application* app) {}
|
||||
void WindowBackgroundIsTranslucent(struct Application* app) {}
|
||||
void OpenDialog(struct Application* app, char *callbackID, char *title, char *filters, char *defaultFilename, char *defaultDir, int allowFiles, int allowDirs, int allowMultiple, int showHiddenFiles, int canCreateDirectories, int resolvesAliases, int treatPackagesAsDirectories) {}
|
||||
void SaveDialog(struct Application* app, char *callbackID, char *title, char *filters, char *defaultFilename, char *defaultDir, int showHiddenFiles, int canCreateDirectories, int treatPackagesAsDirectories) {}
|
||||
void MessageDialog(struct Application* app, char *callbackID, char *type, char *title, char *message, char *icon, char *button1, char *button2, char *button3, char *button4, char *defaultButton, char *cancelButton) {}
|
||||
|
||||
|
||||
// minimiseInternal minimises the main window
|
||||
void minimiseInternal(struct Application *app) {
|
||||
gtk_window_iconify(app->mainWindow);
|
||||
|
||||
17
v2/internal/ffenestri/ffenestri_linux.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package ffenestri
|
||||
|
||||
/*
|
||||
#cgo linux CFLAGS: -DFFENESTRI_LINUX=1
|
||||
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0
|
||||
|
||||
|
||||
#include "ffenestri.h"
|
||||
#include "ffenestri_linux.h"
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
func (a *Application) processPlatformSettings() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
6
v2/internal/ffenestri/ffenestri_linux.h
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
#ifndef FFENESTRI_LINUX_H
|
||||
#define FFENESTRI_LINUX_H
|
||||
|
||||
|
||||
#endif
|
||||
@@ -195,8 +195,8 @@ void execJS(struct Application* app, const char *script) {
|
||||
|
||||
void loadAssets(struct Application* app) {
|
||||
|
||||
// patch window.external.invoke
|
||||
std::string initialCode = std::string("window.external={invoke:s=>window.chrome.webview.postMessage(s)};");
|
||||
// setup window.wailsInvoke
|
||||
std::string initialCode = std::string("window.wailsInvoke=function(m){window.chrome.webview.postMessage(m)};");
|
||||
|
||||
// Load bindings
|
||||
initialCode += std::string(app->bindings);
|
||||
@@ -224,7 +224,7 @@ void loadAssets(struct Application* app) {
|
||||
initialCode += std::string("wails._.DisableDefaultContextMenu();");
|
||||
}
|
||||
|
||||
initialCode += std::string("window.external.invoke('completed');");
|
||||
initialCode += std::string("window.wailsInvoke('completed');");
|
||||
|
||||
// Keep a copy of the code
|
||||
app->initialCode = new char[initialCode.length()+1];
|
||||
@@ -304,8 +304,8 @@ bool initWebView2(struct Application *app, int debugEnabled, messageCallback cb)
|
||||
GetClientRect(app->window, &bounds);
|
||||
app->webviewController->put_Bounds(bounds);
|
||||
|
||||
// Callback hack
|
||||
app->webview->AddScriptToExecuteOnDocumentCreated(L"window.chrome.webview.postMessage('I');", nullptr);
|
||||
// Let the backend know we have initialised
|
||||
app->webview->AddScriptToExecuteOnDocumentCreated(L"window.chrome.webview.postMessage('initialised');", nullptr);
|
||||
// Load the HTML
|
||||
LPCWSTR html = (LPCWSTR) cstrToLPWSTR((char*)assets[0]);
|
||||
app->webview->Navigate(html);
|
||||
@@ -328,6 +328,8 @@ void Run(struct Application* app, int argc, char **argv) {
|
||||
wc.hInstance = hInstance;
|
||||
wc.lpszClassName = (LPCWSTR)"ffenestri";
|
||||
wc.lpfnWndProc = WndProc;
|
||||
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(100));
|
||||
wc.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(100));
|
||||
|
||||
// TODO: Menu
|
||||
// wc.lpszMenuName = nullptr;
|
||||
|
||||
@@ -15,6 +15,9 @@ import "C"
|
||||
func (a *Application) processPlatformSettings() error {
|
||||
|
||||
config := a.config.Windows
|
||||
if config == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check if the webview should be transparent
|
||||
if config.WebviewIsTransparent {
|
||||
|
||||
5
v2/internal/ffenestri/runtime_linux.c
Normal file
@@ -1,7 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
project(test C)
|
||||
project(test)
|
||||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(SOURCES ../../ffenestri_windows.cpp)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
|
||||
add_executable(test ${SOURCES} main.c)
|
||||
add_executable(test main.cpp)
|
||||
@@ -1 +0,0 @@
|
||||
g++ main.c ..\..\ffenestri_windows.cpp -lgdi32 -std=c++11
|
||||
BIN
v2/internal/ffenestri/windows/x64/webview.dll
Normal file
@@ -1,3 +1,5 @@
|
||||
// +build windows
|
||||
|
||||
package x64
|
||||
|
||||
import _ "embed"
|
||||
|
||||
9
v2/internal/ffenestri/windows/x64/x64_stub.go
Normal file
@@ -0,0 +1,9 @@
|
||||
// +build !windows
|
||||
|
||||
// This is a stub to define the following even though they don't exist
|
||||
// on non-Windows systems. Note: This is not the right way to handle this.
|
||||
package x64
|
||||
|
||||
var WebView2 []byte
|
||||
|
||||
var WebView2Loader []byte
|
||||
@@ -66,21 +66,12 @@ class wv2ComHandler
|
||||
completed(app);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
switch(m[0]) {
|
||||
|
||||
// Standard message for backend
|
||||
case 'S':
|
||||
printf("--> Message to backend: %s\n", &m[1]);
|
||||
messageFromWindowCallback(&m[1]);
|
||||
break;
|
||||
// DOM Initialised
|
||||
case 'I':
|
||||
else if (strcmp(m, "initialised") == 0) {
|
||||
loadAssets(app);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("----> Unknown message type: %c\n", m[0]);
|
||||
return S_OK;
|
||||
}
|
||||
else {
|
||||
messageFromWindowCallback(m);
|
||||
}
|
||||
delete[] m;
|
||||
return S_OK;
|
||||
|
||||
@@ -52,21 +52,13 @@ func (a *Asset) AsString() string {
|
||||
return a.Data
|
||||
}
|
||||
|
||||
// AsCHexData processes the asset data so it may be used by C
|
||||
func (a *Asset) AsCHexData() string {
|
||||
|
||||
// This will be our final string to hexify
|
||||
dataString := a.Data
|
||||
|
||||
func (a *Asset) minifiedData() (string, error) {
|
||||
switch a.Type {
|
||||
case AssetTypes.HTML:
|
||||
|
||||
// Escape HTML
|
||||
var re = regexp.MustCompile(`\s{2,}`)
|
||||
result := re.ReplaceAllString(a.Data, ``)
|
||||
result = strings.ReplaceAll(result, "\n", "")
|
||||
result = strings.ReplaceAll(result, "\r\n", "")
|
||||
result = strings.ReplaceAll(result, "\n", "")
|
||||
var re = regexp.MustCompile(`[\s]+`)
|
||||
result := re.ReplaceAllString(a.Data, ` `)
|
||||
|
||||
// Inject wailsloader code
|
||||
result = strings.Replace(result, `</body>`, `<script id='wailsloader'>window.wailsloader = { html: true, runtime: false, userjs: false, usercss: false };var self=document.querySelector('#wailsloader');self.parentNode.removeChild(self);</script></body>`, 1)
|
||||
@@ -75,7 +67,7 @@ func (a *Asset) AsCHexData() string {
|
||||
urlString := strings.ReplaceAll(url.String(), "/", "%2f")
|
||||
|
||||
// Save Data uRI string
|
||||
dataString = "data:text/html;charset=utf-8," + urlString
|
||||
return "data:text/html;charset=utf-8," + urlString, nil
|
||||
|
||||
case AssetTypes.CSS:
|
||||
|
||||
@@ -91,19 +83,28 @@ func (a *Asset) AsCHexData() string {
|
||||
result = strings.ReplaceAll(result, `'`, `\'`)
|
||||
result = strings.ReplaceAll(result, ` {`, `{`)
|
||||
result = strings.ReplaceAll(result, `: `, `:`)
|
||||
dataString = fmt.Sprintf("window.wails._.InjectCSS(\"%s\");", result)
|
||||
return fmt.Sprintf("window.wails._.InjectCSS(\"%s\");", result), nil
|
||||
|
||||
case AssetTypes.JS:
|
||||
m := minify.New()
|
||||
m.AddFunc("application/javascript", js.Minify)
|
||||
var err error
|
||||
dataString, err = m.String("application/javascript", a.Data+";")
|
||||
result, err := m.String("application/javascript", a.Data+";")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return "", err
|
||||
}
|
||||
a.Data = dataString
|
||||
return result, nil
|
||||
default:
|
||||
return "", fmt.Errorf("minification for asset type %s not implemented", a.Type)
|
||||
}
|
||||
}
|
||||
|
||||
// AsCHexData processes the asset data so it may be used by C
|
||||
func (a *Asset) AsCHexData() string {
|
||||
dataString, err := a.minifiedData()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// Get byte data of the string
|
||||
bytes := *(*[]byte)(unsafe.Pointer(&dataString))
|
||||
|
||||
|
||||
53
v2/internal/html/asset_test.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package html
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestAsset_minifiedData(t *testing.T) {
|
||||
type fields struct {
|
||||
Type string
|
||||
Path string
|
||||
Data string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "multi-line tag",
|
||||
fields: fields{
|
||||
Type: AssetTypes.HTML,
|
||||
Path: "foo.html",
|
||||
Data: "<link\n rel=\"stylesheet\"\n href=\"src/foo.css\"\n>\n",
|
||||
},
|
||||
want: "data:text/html;charset=utf-8,%3Clink%20rel=%22stylesheet%22%20href=%22src%2ffoo.css%22%20%3E%20",
|
||||
},
|
||||
{
|
||||
name: "multi-line tag no spaces",
|
||||
fields: fields{
|
||||
Type: AssetTypes.HTML,
|
||||
Path: "foo.html",
|
||||
Data: "<link\nrel=\"stylesheet\"\nhref=\"src/foo.css\"\n>\n",
|
||||
},
|
||||
want: "data:text/html;charset=utf-8,%3Clink%20rel=%22stylesheet%22%20href=%22src%2ffoo.css%22%20%3E%20",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
a := &Asset{
|
||||
Type: tt.fields.Type,
|
||||
Path: tt.fields.Path,
|
||||
Data: tt.fields.Data,
|
||||
}
|
||||
got, err := a.minifiedData()
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Asset.minifiedData() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("Asset.minifiedData() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -84,7 +84,7 @@ func (a *AssetBundle) processHTML(htmldata string) error {
|
||||
}
|
||||
|
||||
//process the token according to the token type...
|
||||
if tokenType == html.StartTagToken {
|
||||
if tokenType == html.StartTagToken || tokenType == html.SelfClosingTagToken {
|
||||
//get the token
|
||||
token := tokenizer.Token()
|
||||
|
||||
|
||||
73
v2/internal/html/assetbundle_test.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package html
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewAssetBundle(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
pathToHTML string
|
||||
wantAssets []string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "basic html",
|
||||
pathToHTML: "testdata/basic.html",
|
||||
wantAssets: []string{
|
||||
AssetTypes.HTML,
|
||||
AssetTypes.FAVICON,
|
||||
AssetTypes.JS,
|
||||
AssetTypes.CSS,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "self closing tags",
|
||||
pathToHTML: "testdata/self_closing.html",
|
||||
wantAssets: []string{
|
||||
AssetTypes.HTML,
|
||||
AssetTypes.FAVICON,
|
||||
AssetTypes.JS,
|
||||
AssetTypes.CSS,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "multi-line tags",
|
||||
pathToHTML: "testdata/self_closing.html",
|
||||
wantAssets: []string{
|
||||
AssetTypes.HTML,
|
||||
AssetTypes.FAVICON,
|
||||
AssetTypes.JS,
|
||||
AssetTypes.CSS,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := NewAssetBundle(tt.pathToHTML)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("NewAssetBundle() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if len(got.assets) != len(tt.wantAssets) {
|
||||
t.Errorf("NewAssetBundle() len(assets) = %d, want %d",
|
||||
len(got.assets), len(tt.wantAssets))
|
||||
}
|
||||
|
||||
for i := range tt.wantAssets {
|
||||
if i >= len(got.assets) {
|
||||
t.Errorf("NewAssetBundle() missing assets[%d].Type = %s",
|
||||
i, tt.wantAssets[i])
|
||||
} else {
|
||||
if got.assets[i].Type != tt.wantAssets[i] {
|
||||
t.Errorf("NewAssetBundle() assets[%d].Type = %s, want %s",
|
||||
i, got.assets[i].Type, tt.wantAssets[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
14
v2/internal/html/testdata/basic.html
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg"></link>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<script type="text/javascript" src="src/bundle.js"></script>
|
||||
<link rel="stylesheet" href="src/style.css"></link>
|
||||
<title>Vite App</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
17
v2/internal/html/testdata/multi_line.html
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<script type="text/javascript" src="src/bundle.js"></script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="src/style.css"
|
||||
/>
|
||||
<title>Vite App</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
14
v2/internal/html/testdata/self_closing.html
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<script type="text/javascript" src="src/bundle.js"></script>
|
||||
<link rel="stylesheet" href="src/style.css" />
|
||||
<title>Vite App</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
1
v2/internal/html/testdata/src/bundle.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
window.alert("I am JS!");
|
||||
8
v2/internal/html/testdata/src/favicon.svg
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
<svg version="1.1"
|
||||
baseProfile="full"
|
||||
width="300" height="200"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
|
||||
<rect width="100%" height="100%" fill="blue" />
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 172 B |
3
v2/internal/html/testdata/src/style.css
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
.body {
|
||||
background: blue;
|
||||
}
|
||||
@@ -39,12 +39,7 @@ func (p *Process) Start() error {
|
||||
|
||||
go func(cmd *exec.Cmd, running *bool, logger *clilogger.CLILogger, exitChannel chan bool) {
|
||||
logger.Println("Starting process (PID: %d)", cmd.Process.Pid)
|
||||
err := cmd.Wait()
|
||||
if err != nil {
|
||||
if err.Error() != "signal: killed" {
|
||||
logger.Fatal("Fatal error from app: " + err.Error())
|
||||
}
|
||||
}
|
||||
_ = cmd.Wait()
|
||||
logger.Println("Exiting process (PID: %d)", cmd.Process.Pid)
|
||||
*running = false
|
||||
exitChannel <- true
|
||||
@@ -59,6 +54,13 @@ func (p *Process) Kill() error {
|
||||
return nil
|
||||
}
|
||||
err := p.cmd.Process.Kill()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = p.cmd.Process.Release()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Wait for command to exit properly
|
||||
<-p.exitChannel
|
||||
|
||||
@@ -25,8 +25,8 @@ type Project struct {
|
||||
// The path to the project directory
|
||||
Path string
|
||||
|
||||
// Assets directory
|
||||
AssetsDir string `json:"assetsdir"`
|
||||
// Build directory
|
||||
BuildDir string `json:"builddir"`
|
||||
|
||||
// The output filename
|
||||
OutputFilename string `json:"outputfilename"`
|
||||
@@ -76,8 +76,8 @@ func Load(projectPath string) (*Project, error) {
|
||||
}
|
||||
|
||||
// Set default assets directory if none given
|
||||
if result.AssetsDir == "" {
|
||||
result.AssetsDir = filepath.Join(result.Path, "assets")
|
||||
if result.BuildDir == "" {
|
||||
result.BuildDir = filepath.Join(result.Path, "build")
|
||||
}
|
||||
|
||||
// Fix up OutputFilename
|
||||
|
||||
12
v2/internal/runtime/assets/assets.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package assets
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed desktop_darwin.js
|
||||
var desktopDarwinJS string
|
||||
|
||||
//go:embed desktop_windows.js
|
||||
var desktopWindowsJS string
|
||||
|
||||
//go:embed wails.js
|
||||
var wailsJS string
|
||||
1
v2/internal/runtime/assets/desktop_linux.js
Normal file
@@ -10,20 +10,6 @@ The lightweight framework for web-like apps
|
||||
/* jshint esversion: 6 */
|
||||
import { SetBindings } from './bindings';
|
||||
import { Init } from './main';
|
||||
import {RaiseError} from '../desktop/darwin';
|
||||
|
||||
// Setup global error handler
|
||||
window.onerror = function (msg, url, lineNo, columnNo, error) {
|
||||
const errorMessage = {
|
||||
message: msg,
|
||||
url: url,
|
||||
line: lineNo,
|
||||
column: columnNo,
|
||||
error: JSON.stringify(error),
|
||||
stack: function() { return JSON.stringify(new Error().stack); }(),
|
||||
};
|
||||
RaiseError(errorMessage);
|
||||
};
|
||||
|
||||
// Initialise the Runtime
|
||||
Init();
|
||||
|
||||
@@ -15,7 +15,7 @@ import * as Dialog from './dialog';
|
||||
import { On, Once, OnMultiple, Emit, Notify } from './events';
|
||||
import { Callback, SystemCall } from './calls';
|
||||
import { AddScript, InjectCSS, DisableDefaultContextMenu } from './utils';
|
||||
import { AddIPCListener } from 'ipc';
|
||||
import { AddIPCListener, SendMessage } from 'ipc';
|
||||
import * as Platform from 'platform';
|
||||
import * as Store from './store';
|
||||
import * as Tray from './tray';
|
||||
@@ -47,6 +47,7 @@ export function Init() {
|
||||
// Init,
|
||||
AddIPCListener,
|
||||
SystemCall,
|
||||
SendMessage,
|
||||
},
|
||||
Store,
|
||||
};
|
||||
|
||||
@@ -13,60 +13,53 @@ The lightweight framework for web-like apps
|
||||
* Initialises platform specific code
|
||||
*/
|
||||
|
||||
// import * as common from './common';
|
||||
const common = require('./common');
|
||||
|
||||
export const System = {
|
||||
...common,
|
||||
Platform: () => "darwin",
|
||||
}
|
||||
AppType: 'desktop',
|
||||
Platform: () => 'darwin',
|
||||
};
|
||||
|
||||
export function SendMessage(message) {
|
||||
window.webkit.messageHandlers.external.postMessage(message);
|
||||
}
|
||||
|
||||
export function RaiseError(message) {
|
||||
window.webkit.messageHandlers.error.postMessage(message);
|
||||
window.wailsInvoke(message);
|
||||
}
|
||||
|
||||
export function Init() {
|
||||
|
||||
// Setup drag handler
|
||||
// Based on code from: https://github.com/patr0nus/DeskGap
|
||||
window.addEventListener('mousedown', function (e) {
|
||||
let currentElement = e.target;
|
||||
while (currentElement != null) {
|
||||
if (currentElement.hasAttribute('data-wails-no-drag')) {
|
||||
break;
|
||||
} else if (currentElement.hasAttribute('data-wails-drag')) {
|
||||
window.webkit.messageHandlers.windowDrag.postMessage(null);
|
||||
break;
|
||||
}
|
||||
currentElement = currentElement.parentElement;
|
||||
}
|
||||
});
|
||||
// Setup drag handler
|
||||
// Based on code from: https://github.com/patr0nus/DeskGap
|
||||
window.addEventListener('mousedown', function (e) {
|
||||
let currentElement = e.target;
|
||||
while (currentElement != null) {
|
||||
if (currentElement.hasAttribute('data-wails-no-drag')) {
|
||||
break;
|
||||
} else if (currentElement.hasAttribute('data-wails-drag')) {
|
||||
window.wailsDrag(null);
|
||||
break;
|
||||
}
|
||||
currentElement = currentElement.parentElement;
|
||||
}
|
||||
});
|
||||
|
||||
// Setup context menu hook
|
||||
window.addEventListener('contextmenu', function (e) {
|
||||
let currentElement = e.target;
|
||||
let contextMenuId;
|
||||
while (currentElement != null) {
|
||||
contextMenuId = currentElement.dataset['wails-context-menu-id'];
|
||||
if (contextMenuId != null) {
|
||||
break;
|
||||
}
|
||||
currentElement = currentElement.parentElement;
|
||||
}
|
||||
if (contextMenuId != null || window.disableWailsDefaultContextMenu) {
|
||||
e.preventDefault();
|
||||
}
|
||||
if( contextMenuId != null ) {
|
||||
let contextData = currentElement.dataset['wails-context-menu-data'];
|
||||
let message = {
|
||||
id: contextMenuId,
|
||||
data: contextData || "",
|
||||
};
|
||||
window.webkit.messageHandlers.contextMenu.postMessage(JSON.stringify(message));
|
||||
}
|
||||
});
|
||||
// Setup context menu hook
|
||||
window.addEventListener('contextmenu', function (e) {
|
||||
let currentElement = e.target;
|
||||
let contextMenuId;
|
||||
while (currentElement != null) {
|
||||
contextMenuId = currentElement.dataset['wails-context-menu-id'];
|
||||
if (contextMenuId != null) {
|
||||
break;
|
||||
}
|
||||
currentElement = currentElement.parentElement;
|
||||
}
|
||||
if (contextMenuId != null || window.disableWailsDefaultContextMenu) {
|
||||
e.preventDefault();
|
||||
}
|
||||
if( contextMenuId != null ) {
|
||||
let contextData = currentElement.dataset['wails-context-menu-data'];
|
||||
let message = {
|
||||
id: contextMenuId,
|
||||
data: contextData || '',
|
||||
};
|
||||
window.wailsContextMenuMessage(JSON.stringify(message));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -14,28 +14,52 @@ The lightweight framework for web-like apps
|
||||
*/
|
||||
|
||||
export const System = {
|
||||
...common,
|
||||
Platform: () => "linux",
|
||||
}
|
||||
AppType: 'desktop',
|
||||
Platform: () => 'linux',
|
||||
};
|
||||
|
||||
export function SendMessage(message) {
|
||||
window.webkit.messageHandlers.external.postMessage(message);
|
||||
window.wailsInvoke(message);
|
||||
}
|
||||
|
||||
export function Init() {
|
||||
|
||||
// Setup drag handler
|
||||
// Based on code from: https://github.com/patr0nus/DeskGap
|
||||
window.addEventListener('mousedown', function (e) {
|
||||
let currentElement = e.target;
|
||||
while (currentElement != null) {
|
||||
if (currentElement.hasAttribute('data-wails-no-drag')) {
|
||||
break;
|
||||
} else if (currentElement.hasAttribute('data-wails-drag')) {
|
||||
window.webkit.messageHandlers.windowDrag.postMessage(null);
|
||||
break;
|
||||
}
|
||||
currentElement = currentElement.parentElement;
|
||||
}
|
||||
});
|
||||
// Setup drag handler
|
||||
// Based on code from: https://github.com/patr0nus/DeskGap
|
||||
window.addEventListener('mousedown', function (e) {
|
||||
let currentElement = e.target;
|
||||
while (currentElement != null) {
|
||||
if (currentElement.hasAttribute('data-wails-no-drag')) {
|
||||
break;
|
||||
} else if (currentElement.hasAttribute('data-wails-drag')) {
|
||||
window.wailsDrag(null);
|
||||
break;
|
||||
}
|
||||
currentElement = currentElement.parentElement;
|
||||
}
|
||||
});
|
||||
|
||||
// Setup context menu hook
|
||||
window.addEventListener('contextmenu', function (e) {
|
||||
let currentElement = e.target;
|
||||
let contextMenuId;
|
||||
while (currentElement != null) {
|
||||
contextMenuId = currentElement.dataset['wails-context-menu-id'];
|
||||
if (contextMenuId != null) {
|
||||
break;
|
||||
}
|
||||
currentElement = currentElement.parentElement;
|
||||
}
|
||||
if (contextMenuId != null || window.disableWailsDefaultContextMenu) {
|
||||
e.preventDefault();
|
||||
}
|
||||
if( contextMenuId != null ) {
|
||||
let contextData = currentElement.dataset['wails-context-menu-data'];
|
||||
let message = {
|
||||
id: contextMenuId,
|
||||
data: contextData || '',
|
||||
};
|
||||
window.wailsContextMenuMessage(JSON.stringify(message));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -13,20 +13,13 @@ The lightweight framework for web-like apps
|
||||
* Initialises platform specific code
|
||||
*/
|
||||
|
||||
// import * as common from './common';
|
||||
const common = require('./common');
|
||||
|
||||
export const System = {
|
||||
...common,
|
||||
AppType: 'desktop',
|
||||
Platform: () => 'windows',
|
||||
};
|
||||
|
||||
export function SendMessage(message) {
|
||||
window.chrome.webview.postMessage('S'+message);
|
||||
}
|
||||
|
||||
export function RaiseError(message) {
|
||||
window.chrome.webview.postMessage('E'+message);
|
||||
window.wailsInvoke(message);
|
||||
}
|
||||
|
||||
export function Init() {
|
||||
@@ -39,7 +32,7 @@ export function Init() {
|
||||
if (currentElement.hasAttribute('data-wails-no-drag')) {
|
||||
break;
|
||||
} else if (currentElement.hasAttribute('data-wails-drag')) {
|
||||
window.chrome.webview.postMessage('wails-drag');
|
||||
window.wailsInvoke('wails-drag');
|
||||
break;
|
||||
}
|
||||
currentElement = currentElement.parentElement;
|
||||
@@ -66,7 +59,7 @@ export function Init() {
|
||||
id: contextMenuId,
|
||||
data: contextData || '',
|
||||
};
|
||||
window.chrome.webview.postMessage('C'+JSON.stringify(message));
|
||||
window.wailsInvoke('C'+JSON.stringify(message));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -678,7 +678,7 @@
|
||||
function add_css() {
|
||||
var style = element("style");
|
||||
style.id = "svelte-9nqyfr-style";
|
||||
style.textContent = ".wails-reconnect-overlay.svelte-9nqyfr{position:fixed;top:0;left:0;width:100%;height:100%;backdrop-filter:blur(20px) saturate(160%) contrast(45%) brightness(140%);z-index:999999\n }.wails-reconnect-overlay-content.svelte-9nqyfr{position:relative;top:50%;transform:translateY(-50%);margin:0;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC8AAAAuCAMAAACPpbA7AAAAflBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQAAAAAAAAAAAABAQEEBAQAAAAAAAAEBAQAAAADAwMAAAABAQEAAAAAAAAAAAAAAAAAAAACAgICAgIBAQEAAAAAAAAAAAAAAAAAAAACAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBQWCC3waAAAAKXRSTlMALgUMIBk0+xEqJs70Xhb3lu3EjX2EZTlv5eHXvbarQj3cdmpXSqOeUDwaqNAAAAKCSURBVEjHjZTntqsgEIUPVVCwtxg1vfD+L3hHRe8K6snZf+KKn8OewvzsSSeXLruLnz+KHs0gr6DkT3xsRkU6VVn4Ha/UxLe1Z4y64i847sykPBh/AvQ7ry3eFN70oKrfcBJYvm/tQ1qxP4T3emXPeXAkvodPUvtdjbhk+Ft4c0hslTiXVOzxOJ15NWUblQhRsdu3E1AfCjj3Gdm18zSOsiH8Lk4TB480ksy62fiqNo4OpyU8O21l6+hyRtS6z8r1pHlmle5sR1/WXS6Mq2Nl+YeKt3vr+vdH/q4O68tzXuwkiZmngYb4R8Co1jh0+Ww2UTyWxBvtyxLO7QVjO3YOD/lWZpbXDGellFG2Mws58mMnjVZSn7p+XvZ6IF4nn02OJZV0aTO22arp/DgLPtrgpVoi6TPbZm4XQBjY159w02uO0BDdYsfrOEi0M2ulRXlCIPAOuN1NOVhi+riBR3dgwQplYsZRZJLXq23Mlo5njkbY0rZFu3oiNIYG2kqsbVz67OlNuZZIOlfxHDl0UpyRX86z/OYC/3qf1A1xTrMp/PWWM4ePzf8DDp1nesQRpcFk7BlwdzN08ZIALJpCaciQXO0f6k4dnuT/Ewg4l7qSTNzm2SykdHn6GJ12mWc6aCNj/g1cTXpB8YFfr0uVc96aFkkqiIiX4nO+salKwGtIkvfB+Ja8DxMeD3hIXP5mTOYPB4eVT0+32I5ykvPZjesnkGgIREgYnmLrPb0PdV3hoLup2TjcGBPM4mgsfF5BrawZR4/GpzYQzQfrUZCf0TCWYo2DqhdhTJBQ6j4xqmmLN5LjdRIY8LWExiFUsSrza/nmFBqw3I9tEZB9h0lIQSO9if8DkISDAj8CDawAAAAASUVORK5CYII=);background-repeat:no-repeat;background-position:center\n }.wails-reconnect-overlay-loadingspinner.svelte-9nqyfr{pointer-events:none;width:2.5em;height:2.5em;border:.4em solid transparent;border-color:#f00 #eee0 #f00 #eee0;border-radius:50%;animation:svelte-9nqyfr-loadingspin 1s linear infinite;margin:auto;padding:2.5em\n }@keyframes svelte-9nqyfr-loadingspin{100%{transform:rotate(360deg)}}";
|
||||
style.textContent = ".wails-reconnect-overlay.svelte-9nqyfr{position:fixed;top:0;left:0;width:100%;height:100%;backdrop-filter:blur(20px) saturate(160%) contrast(45%) brightness(140%);z-index:999999\r\n }.wails-reconnect-overlay-content.svelte-9nqyfr{position:relative;top:50%;transform:translateY(-50%);margin:0;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC8AAAAuCAMAAACPpbA7AAAAflBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQAAAAAAAAAAAABAQEEBAQAAAAAAAAEBAQAAAADAwMAAAABAQEAAAAAAAAAAAAAAAAAAAACAgICAgIBAQEAAAAAAAAAAAAAAAAAAAACAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBQWCC3waAAAAKXRSTlMALgUMIBk0+xEqJs70Xhb3lu3EjX2EZTlv5eHXvbarQj3cdmpXSqOeUDwaqNAAAAKCSURBVEjHjZTntqsgEIUPVVCwtxg1vfD+L3hHRe8K6snZf+KKn8OewvzsSSeXLruLnz+KHs0gr6DkT3xsRkU6VVn4Ha/UxLe1Z4y64i847sykPBh/AvQ7ry3eFN70oKrfcBJYvm/tQ1qxP4T3emXPeXAkvodPUvtdjbhk+Ft4c0hslTiXVOzxOJ15NWUblQhRsdu3E1AfCjj3Gdm18zSOsiH8Lk4TB480ksy62fiqNo4OpyU8O21l6+hyRtS6z8r1pHlmle5sR1/WXS6Mq2Nl+YeKt3vr+vdH/q4O68tzXuwkiZmngYb4R8Co1jh0+Ww2UTyWxBvtyxLO7QVjO3YOD/lWZpbXDGellFG2Mws58mMnjVZSn7p+XvZ6IF4nn02OJZV0aTO22arp/DgLPtrgpVoi6TPbZm4XQBjY159w02uO0BDdYsfrOEi0M2ulRXlCIPAOuN1NOVhi+riBR3dgwQplYsZRZJLXq23Mlo5njkbY0rZFu3oiNIYG2kqsbVz67OlNuZZIOlfxHDl0UpyRX86z/OYC/3qf1A1xTrMp/PWWM4ePzf8DDp1nesQRpcFk7BlwdzN08ZIALJpCaciQXO0f6k4dnuT/Ewg4l7qSTNzm2SykdHn6GJ12mWc6aCNj/g1cTXpB8YFfr0uVc96aFkkqiIiX4nO+salKwGtIkvfB+Ja8DxMeD3hIXP5mTOYPB4eVT0+32I5ykvPZjesnkGgIREgYnmLrPb0PdV3hoLup2TjcGBPM4mgsfF5BrawZR4/GpzYQzQfrUZCf0TCWYo2DqhdhTJBQ6j4xqmmLN5LjdRIY8LWExiFUsSrza/nmFBqw3I9tEZB9h0lIQSO9if8DkISDAj8CDawAAAAASUVORK5CYII=);background-repeat:no-repeat;background-position:center\r\n }.wails-reconnect-overlay-loadingspinner.svelte-9nqyfr{pointer-events:none;width:2.5em;height:2.5em;border:.4em solid transparent;border-color:#f00 #eee0 #f00 #eee0;border-radius:50%;animation:svelte-9nqyfr-loadingspin 1s linear infinite;margin:auto;padding:2.5em\r\n }@keyframes svelte-9nqyfr-loadingspin{100%{transform:rotate(360deg)}}";
|
||||
append(document.head, style);
|
||||
}
|
||||
|
||||
@@ -1543,154 +1543,148 @@
|
||||
|
||||
function StartWebsocket(userCallback) {
|
||||
|
||||
callback = userCallback;
|
||||
callback = userCallback;
|
||||
|
||||
window.onbeforeunload = function() {
|
||||
if( websocket ) {
|
||||
websocket.onclose = function () { };
|
||||
websocket.close();
|
||||
websocket = null;
|
||||
}
|
||||
};
|
||||
window.onbeforeunload = function() {
|
||||
if( websocket ) {
|
||||
websocket.onclose = function () { };
|
||||
websocket.close();
|
||||
websocket = null;
|
||||
}
|
||||
};
|
||||
|
||||
// ...and attempt to connect
|
||||
connect();
|
||||
// ...and attempt to connect
|
||||
connect();
|
||||
|
||||
}
|
||||
|
||||
function setupIPCBridge() {
|
||||
// darwin
|
||||
window.webkit = {
|
||||
messageHandlers: {
|
||||
external: {
|
||||
postMessage: (message) => {
|
||||
websocket.send(message);
|
||||
}
|
||||
},
|
||||
windowDrag: {
|
||||
postMessage: () => {
|
||||
// Ignore window drag events
|
||||
}
|
||||
}
|
||||
}
|
||||
window.wailsInvoke = (message) => {
|
||||
websocket.send(message);
|
||||
};
|
||||
window.wailsDrag = (message) => {
|
||||
websocket.send(message);
|
||||
};
|
||||
window.wailsContextMenuMessage = (message) => {
|
||||
websocket.send(message);
|
||||
};
|
||||
}
|
||||
|
||||
// Handles incoming websocket connections
|
||||
function handleConnect() {
|
||||
log('Connected to backend');
|
||||
setupIPCBridge();
|
||||
hideOverlay();
|
||||
clearInterval(connectTimer);
|
||||
websocket.onclose = handleDisconnect;
|
||||
websocket.onmessage = handleMessage;
|
||||
log('Connected to backend');
|
||||
setupIPCBridge();
|
||||
hideOverlay();
|
||||
clearInterval(connectTimer);
|
||||
websocket.onclose = handleDisconnect;
|
||||
websocket.onmessage = handleMessage;
|
||||
}
|
||||
|
||||
// Handles websocket disconnects
|
||||
function handleDisconnect() {
|
||||
log('Disconnected from backend');
|
||||
websocket = null;
|
||||
showOverlay();
|
||||
connect();
|
||||
log('Disconnected from backend');
|
||||
websocket = null;
|
||||
showOverlay();
|
||||
connect();
|
||||
}
|
||||
|
||||
// Try to connect to the backend every 1s (default value).
|
||||
function connect() {
|
||||
connectTimer = setInterval(function () {
|
||||
if (websocket == null) {
|
||||
websocket = new WebSocket('ws://' + window.location.hostname + ':34115/bridge');
|
||||
websocket.onopen = handleConnect;
|
||||
websocket.onerror = function (e) {
|
||||
e.stopImmediatePropagation();
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
websocket = null;
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}, 1000);
|
||||
connectTimer = setInterval(function () {
|
||||
if (websocket == null) {
|
||||
websocket = new WebSocket('ws://' + window.location.hostname + ':34115/bridge');
|
||||
websocket.onopen = handleConnect;
|
||||
websocket.onerror = function (e) {
|
||||
e.stopImmediatePropagation();
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
websocket = null;
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// Adds a script to the Dom.
|
||||
// Removes it if second parameter is true.
|
||||
function addScript(script, remove) {
|
||||
const s = document.createElement('script');
|
||||
s.setAttribute('type', 'text/javascript');
|
||||
s.textContent = script;
|
||||
document.head.appendChild(s);
|
||||
const s = document.createElement('script');
|
||||
s.setAttribute('type', 'text/javascript');
|
||||
s.textContent = script;
|
||||
document.head.appendChild(s);
|
||||
|
||||
// Remove internal messages from the DOM
|
||||
if (remove) {
|
||||
s.parentNode.removeChild(s);
|
||||
}
|
||||
// Remove internal messages from the DOM
|
||||
if (remove) {
|
||||
s.parentNode.removeChild(s);
|
||||
}
|
||||
}
|
||||
|
||||
function handleMessage(message) {
|
||||
// As a bridge we ignore js and css injections
|
||||
switch (message.data[0]) {
|
||||
// Wails library - inject!
|
||||
case 'b':
|
||||
message = message.data.slice(1);
|
||||
addScript(message);
|
||||
log('Loaded Wails Runtime');
|
||||
// As a bridge we ignore js and css injections
|
||||
switch (message.data[0]) {
|
||||
// Wails library - inject!
|
||||
case 'b':
|
||||
message = message.data.slice(1);
|
||||
addScript(message);
|
||||
log('Loaded Wails Runtime');
|
||||
|
||||
// We need to now send a message to the backend telling it
|
||||
// we have loaded (System Start)
|
||||
window.webkit.messageHandlers.external.postMessage("SS");
|
||||
// We need to now send a message to the backend telling it
|
||||
// we have loaded (System Start)
|
||||
window.wailsInvoke('SS');
|
||||
|
||||
// Now wails runtime is loaded, wails for the ready event
|
||||
// and callback to the main app
|
||||
// window.wails.Events.On('wails:loaded', function () {
|
||||
if (callback) {
|
||||
log('Notifying application');
|
||||
callback(window.wails);
|
||||
}
|
||||
// });
|
||||
break;
|
||||
// Notifications
|
||||
case 'n':
|
||||
window.wails._.Notify(message.data.slice(1));
|
||||
break;
|
||||
// // Binding
|
||||
// case 'b':
|
||||
// const binding = message.data.slice(1);
|
||||
// //log("Binding: " + binding)
|
||||
// window.wails._.NewBinding(binding);
|
||||
// break;
|
||||
// // Call back
|
||||
case 'c':
|
||||
const callbackData = message.data.slice(1);
|
||||
window.wails._.Callback(callbackData);
|
||||
break;
|
||||
// Tray
|
||||
case 'T':
|
||||
const trayMessage = message.data.slice(1);
|
||||
switch (trayMessage[0]) {
|
||||
case 'S':
|
||||
// Set tray
|
||||
const trayJSON = trayMessage.slice(1);
|
||||
let tray = JSON.parse(trayJSON);
|
||||
setTray(tray);
|
||||
break;
|
||||
case 'U':
|
||||
// Update label
|
||||
const updateTrayLabelJSON = trayMessage.slice(1);
|
||||
let trayLabelData = JSON.parse(updateTrayLabelJSON);
|
||||
updateTrayLabel(trayLabelData);
|
||||
break;
|
||||
case 'D':
|
||||
// Delete Tray Menu
|
||||
const id = trayMessage.slice(1);
|
||||
deleteTrayMenu(id);
|
||||
break;
|
||||
default:
|
||||
log('Unknown tray message: ' + message.data);
|
||||
}
|
||||
break;
|
||||
|
||||
// Now wails runtime is loaded, wails for the ready event
|
||||
// and callback to the main app
|
||||
// window.wails.Events.On('wails:loaded', function () {
|
||||
if (callback) {
|
||||
log('Notifying application');
|
||||
callback(window.wails);
|
||||
}
|
||||
// });
|
||||
break;
|
||||
// Notifications
|
||||
case 'n':
|
||||
window.wails._.Notify(message.data.slice(1));
|
||||
break;
|
||||
// // Binding
|
||||
// case 'b':
|
||||
// const binding = message.data.slice(1);
|
||||
// //log("Binding: " + binding)
|
||||
// window.wails._.NewBinding(binding);
|
||||
// break;
|
||||
// // Call back
|
||||
case 'c':
|
||||
const callbackData = message.data.slice(1);
|
||||
window.wails._.Callback(callbackData);
|
||||
break;
|
||||
// Tray
|
||||
case 'T':
|
||||
const trayMessage = message.data.slice(1);
|
||||
switch (trayMessage[0]) {
|
||||
case 'S':
|
||||
// Set tray
|
||||
const trayJSON = trayMessage.slice(1);
|
||||
let tray = JSON.parse(trayJSON);
|
||||
setTray(tray);
|
||||
break
|
||||
case 'U':
|
||||
// Update label
|
||||
const updateTrayLabelJSON = trayMessage.slice(1);
|
||||
let trayLabelData = JSON.parse(updateTrayLabelJSON);
|
||||
updateTrayLabel(trayLabelData);
|
||||
break
|
||||
case 'D':
|
||||
// Delete Tray Menu
|
||||
const id = trayMessage.slice(1);
|
||||
deleteTrayMenu(id);
|
||||
break
|
||||
default:
|
||||
log('Unknown tray message: ' + message.data);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
log('Unknown message: ' + message.data);
|
||||
}
|
||||
default:
|
||||
log('Unknown message: ' + message.data);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -9,7 +9,7 @@ The lightweight framework for web-like apps
|
||||
*/
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
import bridge from './bridge';
|
||||
const bridge = require('./bridge');
|
||||
|
||||
/**
|
||||
* ready will execute the callback when Wails has loaded
|
||||
|
||||
2
v2/internal/runtime/js/runtime/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@wails/runtime",
|
||||
"version": "1.2.24",
|
||||
"version": "1.3.15",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@wails/runtime",
|
||||
"version": "1.3.13",
|
||||
"version": "1.3.19",
|
||||
"description": "Wails V2 Javascript runtime library",
|
||||
"main": "main.js",
|
||||
"types": "runtime.d.ts",
|
||||
|
||||
610
v2/internal/runtime/js/runtime/src/package-lock.json
generated
@@ -1,616 +1,8 @@
|
||||
{
|
||||
"name": "bridge",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "bridge",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^17.1.0",
|
||||
"@rollup/plugin-node-resolve": "^11.1.1",
|
||||
"rollup": "^2.38.5",
|
||||
"rollup-plugin-svelte": "^7.1.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"svelte": "^3.32.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.12.13",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz",
|
||||
"integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/highlight": "^7.12.13"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-validator-identifier": {
|
||||
"version": "7.12.11",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz",
|
||||
"integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@babel/highlight": {
|
||||
"version": "7.12.13",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz",
|
||||
"integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/helper-validator-identifier": "^7.12.11",
|
||||
"chalk": "^2.0.0",
|
||||
"js-tokens": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/plugin-commonjs": {
|
||||
"version": "17.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-17.1.0.tgz",
|
||||
"integrity": "sha512-PoMdXCw0ZyvjpCMT5aV4nkL0QywxP29sODQsSGeDpr/oI49Qq9tRtAsb/LbYbDzFlOydVEqHmmZWFtXJEAX9ew==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@rollup/pluginutils": "^3.1.0",
|
||||
"commondir": "^1.0.1",
|
||||
"estree-walker": "^2.0.1",
|
||||
"glob": "^7.1.6",
|
||||
"is-reference": "^1.2.1",
|
||||
"magic-string": "^0.25.7",
|
||||
"resolve": "^1.17.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/plugin-commonjs/node_modules/estree-walker": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@rollup/plugin-node-resolve": {
|
||||
"version": "11.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.1.1.tgz",
|
||||
"integrity": "sha512-zlBXR4eRS+2m79TsUZWhsd0slrHUYdRx4JF+aVQm+MI0wsKdlpC2vlDVjmlGvtZY1vsefOT9w3JxvmWSBei+Lg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@rollup/pluginutils": "^3.1.0",
|
||||
"@types/resolve": "1.17.1",
|
||||
"builtin-modules": "^3.1.0",
|
||||
"deepmerge": "^4.2.2",
|
||||
"is-module": "^1.0.0",
|
||||
"resolve": "^1.19.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/pluginutils": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
|
||||
"integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "0.0.39",
|
||||
"estree-walker": "^1.0.1",
|
||||
"picomatch": "^2.2.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "0.0.39",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
|
||||
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "14.14.25",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.25.tgz",
|
||||
"integrity": "sha512-EPpXLOVqDvisVxtlbvzfyqSsFeQxltFbluZNRndIb8tr9KiBnYNLzrc1N3pyKUCww2RNrfHDViqDWWE1LCJQtQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/resolve": {
|
||||
"version": "1.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
|
||||
"integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-convert": "^1.9.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer-from": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
|
||||
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/builtin-modules": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz",
|
||||
"integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/commondir": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
|
||||
"integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/deepmerge": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
|
||||
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/estree-walker": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
|
||||
"integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "7.1.6",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
||||
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/has": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/is-core-module": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz",
|
||||
"integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/is-module": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
|
||||
"integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/is-reference": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz",
|
||||
"integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-worker": {
|
||||
"version": "26.6.2",
|
||||
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz",
|
||||
"integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"merge-stream": "^2.0.0",
|
||||
"supports-color": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-worker/node_modules/has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-worker/node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/magic-string": {
|
||||
"version": "0.25.7",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
|
||||
"integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"sourcemap-codec": "^1.4.4"
|
||||
}
|
||||
},
|
||||
"node_modules/merge-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/path-parse": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
|
||||
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
|
||||
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/require-relative": {
|
||||
"version": "0.8.7",
|
||||
"resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz",
|
||||
"integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz",
|
||||
"integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-core-module": "^2.1.0",
|
||||
"path-parse": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "2.38.5",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.38.5.tgz",
|
||||
"integrity": "sha512-VoWt8DysFGDVRGWuHTqZzT02J0ASgjVq/hPs9QcBOGMd7B+jfTr/iqMVEyOi901rE3xq+Deq66GzIT1yt7sGwQ==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/rollup-plugin-svelte": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup-plugin-svelte/-/rollup-plugin-svelte-7.1.0.tgz",
|
||||
"integrity": "sha512-vopCUq3G+25sKjwF5VilIbiY6KCuMNHP1PFvx2Vr3REBNMDllKHFZN2B9jwwC+MqNc3UPKkjXnceLPEjTjXGXg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"require-relative": "^0.8.7",
|
||||
"rollup-pluginutils": "^2.8.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/rollup-plugin-terser": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz",
|
||||
"integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.10.4",
|
||||
"jest-worker": "^26.2.1",
|
||||
"serialize-javascript": "^4.0.0",
|
||||
"terser": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/rollup-pluginutils": {
|
||||
"version": "2.8.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz",
|
||||
"integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"estree-walker": "^0.6.1"
|
||||
}
|
||||
},
|
||||
"node_modules/rollup-pluginutils/node_modules/estree-walker": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
|
||||
"integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/serialize-javascript": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
|
||||
"integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"randombytes": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
|
||||
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-support": {
|
||||
"version": "0.5.19",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
|
||||
"integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"source-map": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-support/node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/sourcemap-codec": {
|
||||
"version": "1.4.8",
|
||||
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
|
||||
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has-flag": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte": {
|
||||
"version": "3.32.2",
|
||||
"resolved": "https://registry.npmjs.org/svelte/-/svelte-3.32.2.tgz",
|
||||
"integrity": "sha512-Zxh1MQQl/+vnToKbU1Per+PoMN8Jb2MeKJcGxiOsCGR677hXw7jkMfbnNXq33+dxIzV/HfA4xtoSPJrqeB0VUg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/terser": {
|
||||
"version": "5.5.1",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.5.1.tgz",
|
||||
"integrity": "sha512-6VGWZNVP2KTUcltUQJ25TtNjx/XgdDsBDKGt8nN0MpydU36LmbPPcMBd2kmtZNNGVVDLg44k7GKeHHj+4zPIBQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"commander": "^2.20.0",
|
||||
"source-map": "~0.7.2",
|
||||
"source-map-support": "~0.5.19"
|
||||
},
|
||||
"bin": {
|
||||
"terser": "bin/terser"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||
"dev": true
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/code-frame": {
|
||||
"version": "7.12.13",
|
||||
|
||||
@@ -10,8 +10,8 @@ The lightweight framework for web-like apps
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
|
||||
import {setTray, hideOverlay, showOverlay, updateTrayLabel, deleteTrayMenu} from "./store";
|
||||
import {log} from "./log";
|
||||
import {setTray, hideOverlay, showOverlay, updateTrayLabel, deleteTrayMenu} from './store';
|
||||
import {log} from './log';
|
||||
|
||||
let websocket = null;
|
||||
let callback = null;
|
||||
@@ -19,152 +19,140 @@ let connectTimer;
|
||||
|
||||
export function StartWebsocket(userCallback) {
|
||||
|
||||
callback = userCallback;
|
||||
callback = userCallback;
|
||||
|
||||
window.onbeforeunload = function() {
|
||||
if( websocket ) {
|
||||
websocket.onclose = function () { };
|
||||
websocket.close();
|
||||
websocket = null;
|
||||
}
|
||||
}
|
||||
window.onbeforeunload = function() {
|
||||
if( websocket ) {
|
||||
websocket.onclose = function () { };
|
||||
websocket.close();
|
||||
websocket = null;
|
||||
}
|
||||
};
|
||||
|
||||
// ...and attempt to connect
|
||||
connect();
|
||||
// ...and attempt to connect
|
||||
connect();
|
||||
|
||||
}
|
||||
|
||||
function setupIPCBridge() {
|
||||
// darwin
|
||||
window.webkit = {
|
||||
messageHandlers: {
|
||||
external: {
|
||||
postMessage: (message) => {
|
||||
websocket.send(message);
|
||||
}
|
||||
},
|
||||
windowDrag: {
|
||||
postMessage: () => {
|
||||
// Ignore window drag events
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
window.wailsInvoke = (message) => {
|
||||
websocket.send(message);
|
||||
};
|
||||
}
|
||||
|
||||
// Handles incoming websocket connections
|
||||
function handleConnect() {
|
||||
log('Connected to backend');
|
||||
setupIPCBridge();
|
||||
hideOverlay();
|
||||
clearInterval(connectTimer);
|
||||
websocket.onclose = handleDisconnect;
|
||||
websocket.onmessage = handleMessage;
|
||||
log('Connected to backend');
|
||||
setupIPCBridge();
|
||||
hideOverlay();
|
||||
clearInterval(connectTimer);
|
||||
websocket.onclose = handleDisconnect;
|
||||
websocket.onmessage = handleMessage;
|
||||
}
|
||||
|
||||
// Handles websocket disconnects
|
||||
function handleDisconnect() {
|
||||
log('Disconnected from backend');
|
||||
websocket = null;
|
||||
showOverlay();
|
||||
connect();
|
||||
log('Disconnected from backend');
|
||||
websocket = null;
|
||||
showOverlay();
|
||||
connect();
|
||||
}
|
||||
|
||||
// Try to connect to the backend every 1s (default value).
|
||||
function connect() {
|
||||
connectTimer = setInterval(function () {
|
||||
if (websocket == null) {
|
||||
websocket = new WebSocket('ws://' + window.location.hostname + ':34115/bridge');
|
||||
websocket.onopen = handleConnect;
|
||||
websocket.onerror = function (e) {
|
||||
e.stopImmediatePropagation();
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
websocket = null;
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}, 1000);
|
||||
connectTimer = setInterval(function () {
|
||||
if (websocket == null) {
|
||||
websocket = new WebSocket('ws://' + window.location.hostname + ':34115/bridge');
|
||||
websocket.onopen = handleConnect;
|
||||
websocket.onerror = function (e) {
|
||||
e.stopImmediatePropagation();
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
websocket = null;
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// Adds a script to the Dom.
|
||||
// Removes it if second parameter is true.
|
||||
function addScript(script, remove) {
|
||||
const s = document.createElement('script');
|
||||
s.setAttribute('type', 'text/javascript');
|
||||
s.textContent = script;
|
||||
document.head.appendChild(s);
|
||||
const s = document.createElement('script');
|
||||
s.setAttribute('type', 'text/javascript');
|
||||
s.textContent = script;
|
||||
document.head.appendChild(s);
|
||||
|
||||
// Remove internal messages from the DOM
|
||||
if (remove) {
|
||||
s.parentNode.removeChild(s);
|
||||
}
|
||||
// Remove internal messages from the DOM
|
||||
if (remove) {
|
||||
s.parentNode.removeChild(s);
|
||||
}
|
||||
}
|
||||
|
||||
function handleMessage(message) {
|
||||
// As a bridge we ignore js and css injections
|
||||
switch (message.data[0]) {
|
||||
// Wails library - inject!
|
||||
case 'b':
|
||||
message = message.data.slice(1)
|
||||
addScript(message);
|
||||
log('Loaded Wails Runtime');
|
||||
// As a bridge we ignore js and css injections
|
||||
switch (message.data[0]) {
|
||||
// Wails library - inject!
|
||||
case 'b':
|
||||
message = message.data.slice(1);
|
||||
addScript(message);
|
||||
log('Loaded Wails Runtime');
|
||||
|
||||
// We need to now send a message to the backend telling it
|
||||
// we have loaded (System Start)
|
||||
window.webkit.messageHandlers.external.postMessage("SS");
|
||||
// We need to now send a message to the backend telling it
|
||||
// we have loaded (System Start)
|
||||
window.wailsInvoke('SS');
|
||||
|
||||
// Now wails runtime is loaded, wails for the ready event
|
||||
// and callback to the main app
|
||||
// window.wails.Events.On('wails:loaded', function () {
|
||||
if (callback) {
|
||||
log('Notifying application');
|
||||
callback(window.wails);
|
||||
}
|
||||
// });
|
||||
break;
|
||||
// Notifications
|
||||
case 'n':
|
||||
window.wails._.Notify(message.data.slice(1));
|
||||
break;
|
||||
// // Binding
|
||||
// case 'b':
|
||||
// const binding = message.data.slice(1);
|
||||
// //log("Binding: " + binding)
|
||||
// window.wails._.NewBinding(binding);
|
||||
// break;
|
||||
// // Call back
|
||||
case 'c':
|
||||
const callbackData = message.data.slice(1);
|
||||
window.wails._.Callback(callbackData);
|
||||
break;
|
||||
// Tray
|
||||
case 'T':
|
||||
const trayMessage = message.data.slice(1);
|
||||
switch (trayMessage[0]) {
|
||||
case 'S':
|
||||
// Set tray
|
||||
const trayJSON = trayMessage.slice(1);
|
||||
let tray = JSON.parse(trayJSON);
|
||||
setTray(tray);
|
||||
break;
|
||||
case 'U':
|
||||
// Update label
|
||||
const updateTrayLabelJSON = trayMessage.slice(1);
|
||||
let trayLabelData = JSON.parse(updateTrayLabelJSON);
|
||||
updateTrayLabel(trayLabelData);
|
||||
break;
|
||||
case 'D':
|
||||
// Delete Tray Menu
|
||||
const id = trayMessage.slice(1);
|
||||
deleteTrayMenu(id);
|
||||
break;
|
||||
default:
|
||||
log('Unknown tray message: ' + message.data);
|
||||
}
|
||||
break;
|
||||
|
||||
// Now wails runtime is loaded, wails for the ready event
|
||||
// and callback to the main app
|
||||
// window.wails.Events.On('wails:loaded', function () {
|
||||
if (callback) {
|
||||
log('Notifying application');
|
||||
callback(window.wails);
|
||||
}
|
||||
// });
|
||||
break;
|
||||
// Notifications
|
||||
case 'n':
|
||||
window.wails._.Notify(message.data.slice(1));
|
||||
break;
|
||||
// // Binding
|
||||
// case 'b':
|
||||
// const binding = message.data.slice(1);
|
||||
// //log("Binding: " + binding)
|
||||
// window.wails._.NewBinding(binding);
|
||||
// break;
|
||||
// // Call back
|
||||
case 'c':
|
||||
const callbackData = message.data.slice(1);
|
||||
window.wails._.Callback(callbackData);
|
||||
break;
|
||||
// Tray
|
||||
case 'T':
|
||||
const trayMessage = message.data.slice(1);
|
||||
switch (trayMessage[0]) {
|
||||
case 'S':
|
||||
// Set tray
|
||||
const trayJSON = trayMessage.slice(1);
|
||||
let tray = JSON.parse(trayJSON)
|
||||
setTray(tray)
|
||||
break
|
||||
case 'U':
|
||||
// Update label
|
||||
const updateTrayLabelJSON = trayMessage.slice(1);
|
||||
let trayLabelData = JSON.parse(updateTrayLabelJSON)
|
||||
updateTrayLabel(trayLabelData)
|
||||
break
|
||||
case 'D':
|
||||
// Delete Tray Menu
|
||||
const id = trayMessage.slice(1);
|
||||
deleteTrayMenu(id)
|
||||
break
|
||||
default:
|
||||
log('Unknown tray message: ' + message.data);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
log('Unknown message: ' + message.data);
|
||||
}
|
||||
default:
|
||||
log('Unknown message: ' + message.data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ func main() {
|
||||
|
||||
sourceDir := fs.RelativePath("../../../internal/runtime/js")
|
||||
|
||||
platforms := []string{"darwin", "windows"}
|
||||
platforms := []string{"darwin", "windows", "linux"}
|
||||
|
||||
for _, platform := range platforms {
|
||||
println("Building JS Runtime for " + platform)
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
package apps
|
||||
|
||||
func Find() []Apps {
|
||||
|
||||
}
|
||||
@@ -9,23 +9,23 @@ import (
|
||||
"github.com/wailsapp/wails/v2/internal/shell"
|
||||
)
|
||||
|
||||
// Yum represents the Yum manager
|
||||
type Yum struct {
|
||||
// Dnf represents the Dnf manager
|
||||
type Dnf struct {
|
||||
name string
|
||||
osid string
|
||||
}
|
||||
|
||||
// NewYum creates a new Yum instance
|
||||
func NewYum(osid string) *Yum {
|
||||
return &Yum{
|
||||
name: "yum",
|
||||
// NewDnf creates a new Dnf instance
|
||||
func NewDnf(osid string) *Dnf {
|
||||
return &Dnf{
|
||||
name: "dnf",
|
||||
osid: osid,
|
||||
}
|
||||
}
|
||||
|
||||
// Packages returns the libraries that we need for Wails to compile
|
||||
// They will potentially differ on different distributions or versions
|
||||
func (y *Yum) Packages() packagemap {
|
||||
func (y *Dnf) Packages() packagemap {
|
||||
return packagemap{
|
||||
"libgtk-3": []*Package{
|
||||
{Name: "gtk3-devel", SystemPackage: true, Library: true},
|
||||
@@ -43,6 +43,9 @@ func (y *Yum) Packages() packagemap {
|
||||
"npm": []*Package{
|
||||
{Name: "npm", SystemPackage: true},
|
||||
},
|
||||
"upx": []*Package{
|
||||
{Name: "upx", SystemPackage: true, Optional: true},
|
||||
},
|
||||
"docker": []*Package{
|
||||
{
|
||||
SystemPackage: false,
|
||||
@@ -57,16 +60,16 @@ func (y *Yum) Packages() packagemap {
|
||||
}
|
||||
|
||||
// Name returns the name of the package manager
|
||||
func (y *Yum) Name() string {
|
||||
func (y *Dnf) Name() string {
|
||||
return y.name
|
||||
}
|
||||
|
||||
// PackageInstalled tests if the given package name is installed
|
||||
func (y *Yum) PackageInstalled(pkg *Package) (bool, error) {
|
||||
func (y *Dnf) PackageInstalled(pkg *Package) (bool, error) {
|
||||
if pkg.SystemPackage == false {
|
||||
return false, nil
|
||||
}
|
||||
stdout, _, err := shell.RunCommand(".", "yum", "info", "installed", pkg.Name)
|
||||
stdout, _, err := shell.RunCommand(".", "dnf", "info", "installed", pkg.Name)
|
||||
if err != nil {
|
||||
_, ok := err.(*exec.ExitError)
|
||||
if ok {
|
||||
@@ -87,11 +90,11 @@ func (y *Yum) PackageInstalled(pkg *Package) (bool, error) {
|
||||
}
|
||||
|
||||
// PackageAvailable tests if the given package is available for installation
|
||||
func (y *Yum) PackageAvailable(pkg *Package) (bool, error) {
|
||||
func (y *Dnf) PackageAvailable(pkg *Package) (bool, error) {
|
||||
if pkg.SystemPackage == false {
|
||||
return false, nil
|
||||
}
|
||||
stdout, _, err := shell.RunCommand(".", "yum", "info", pkg.Name)
|
||||
stdout, _, err := shell.RunCommand(".", "dnf", "info", pkg.Name)
|
||||
// We add a space to ensure we get a full match, not partial match
|
||||
if err != nil {
|
||||
_, ok := err.(*exec.ExitError)
|
||||
@@ -111,14 +114,14 @@ func (y *Yum) PackageAvailable(pkg *Package) (bool, error) {
|
||||
}
|
||||
|
||||
// InstallCommand returns the package manager specific command to install a package
|
||||
func (y *Yum) InstallCommand(pkg *Package) string {
|
||||
func (y *Dnf) InstallCommand(pkg *Package) string {
|
||||
if pkg.SystemPackage == false {
|
||||
return pkg.InstallCommand[y.osid]
|
||||
}
|
||||
return "sudo yum install " + pkg.Name
|
||||
return "sudo dnf install " + pkg.Name
|
||||
}
|
||||
|
||||
func (y *Yum) getPackageVersion(pkg *Package, output string) {
|
||||
func (y *Dnf) getPackageVersion(pkg *Package, output string) {
|
||||
splitOutput := strings.Split(output, " ")
|
||||
if len(splitOutput) > 0 {
|
||||
pkg.Version = splitOutput[1]
|
||||
@@ -9,12 +9,11 @@ import (
|
||||
"github.com/wailsapp/wails/v2/internal/shell"
|
||||
)
|
||||
|
||||
|
||||
// A list of package manager commands
|
||||
var pmcommands = []string{
|
||||
"eopkg",
|
||||
"apt",
|
||||
"yum",
|
||||
"dnf",
|
||||
"pacman",
|
||||
"emerge",
|
||||
"zypper",
|
||||
@@ -38,8 +37,8 @@ func newPackageManager(pmname string, osid string) PackageManager {
|
||||
return NewEopkg(osid)
|
||||
case "apt":
|
||||
return NewApt(osid)
|
||||
case "yum":
|
||||
return NewYum(osid)
|
||||
case "dnf":
|
||||
return NewDnf(osid)
|
||||
case "pacman":
|
||||
return NewPacman(osid)
|
||||
case "emerge":
|
||||
@@ -77,7 +76,7 @@ func Dependancies(p PackageManager) (DependencyList, error) {
|
||||
if installed {
|
||||
dependency.Installed = true
|
||||
dependency.Version = pkg.Version
|
||||
if !pkg.Library {
|
||||
if !pkg.SystemPackage {
|
||||
dependency.Version = AppVersion(name)
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -21,7 +21,6 @@ type PackageManager interface {
|
||||
InstallCommand(*Package) string
|
||||
}
|
||||
|
||||
|
||||
// Dependancy represents a system package that we require
|
||||
type Dependancy struct {
|
||||
Name string
|
||||
@@ -36,20 +35,13 @@ type Dependancy struct {
|
||||
// DependencyList is a list of Dependency instances
|
||||
type DependencyList []*Dependancy
|
||||
|
||||
|
||||
// InstallAllRequiredCommand returns the command you need to use to install all required dependencies
|
||||
func (d DependencyList) InstallAllRequiredCommand() string {
|
||||
|
||||
result := ""
|
||||
for _, dependency := range d {
|
||||
if dependency.PackageName != "" {
|
||||
if !dependency.Installed && !dependency.Optional {
|
||||
if result == "" {
|
||||
result = dependency.InstallCommand
|
||||
} else {
|
||||
result += " " + dependency.PackageName
|
||||
}
|
||||
}
|
||||
if !dependency.Installed && !dependency.Optional {
|
||||
result += " - " + dependency.Name + ": " + dependency.InstallCommand + "\n"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,17 +53,10 @@ func (d DependencyList) InstallAllOptionalCommand() string {
|
||||
|
||||
result := ""
|
||||
for _, dependency := range d {
|
||||
if dependency.PackageName != "" {
|
||||
if !dependency.Installed && dependency.Optional {
|
||||
if result == "" {
|
||||
result = dependency.InstallCommand
|
||||
} else {
|
||||
result += " " + dependency.PackageName
|
||||
}
|
||||
}
|
||||
if !dependency.Installed && dependency.Optional {
|
||||
result += " - " + dependency.Name + ": " + dependency.InstallCommand + "\n"
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ package system
|
||||
import (
|
||||
"github.com/wailsapp/wails/v2/internal/system/operatingsystem"
|
||||
"github.com/wailsapp/wails/v2/internal/system/packagemanager"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Info holds information about the current operating system,
|
||||
@@ -24,3 +26,82 @@ func GetInfo() (*Info, error) {
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
func checkNPM() *packagemanager.Dependancy {
|
||||
|
||||
// Check for npm
|
||||
output, err := exec.Command("npm", "-version").Output()
|
||||
installed := true
|
||||
version := ""
|
||||
if err != nil {
|
||||
installed = false
|
||||
} else {
|
||||
version = strings.TrimSpace(strings.Split(string(output), "\n")[0])
|
||||
}
|
||||
return &packagemanager.Dependancy{
|
||||
Name: "npm ",
|
||||
PackageName: "N/A",
|
||||
Installed: installed,
|
||||
InstallCommand: "Available at https://nodejs.org/en/download/",
|
||||
Version: version,
|
||||
Optional: false,
|
||||
External: false,
|
||||
}
|
||||
}
|
||||
|
||||
func checkUPX() *packagemanager.Dependancy {
|
||||
|
||||
// Check for npm
|
||||
output, err := exec.Command("upx", "-V").Output()
|
||||
installed := true
|
||||
version := ""
|
||||
if err != nil {
|
||||
installed = false
|
||||
} else {
|
||||
version = strings.TrimSpace(strings.Split(string(output), "\n")[0])
|
||||
}
|
||||
return &packagemanager.Dependancy{
|
||||
Name: "upx ",
|
||||
PackageName: "N/A",
|
||||
Installed: installed,
|
||||
InstallCommand: "Available at https://upx.github.io/",
|
||||
Version: version,
|
||||
Optional: true,
|
||||
External: false,
|
||||
}
|
||||
}
|
||||
|
||||
func checkDocker() *packagemanager.Dependancy {
|
||||
|
||||
// Check for npm
|
||||
output, err := exec.Command("docker", "version").Output()
|
||||
installed := true
|
||||
version := ""
|
||||
|
||||
// Docker errors if it is not running so check for that
|
||||
if len(output) == 0 && err != nil {
|
||||
installed = false
|
||||
} else {
|
||||
// Version is in a line like: " Version: 20.10.5"
|
||||
versionOutput := strings.Split(string(output), "\n")
|
||||
for _, line := range versionOutput[1:] {
|
||||
splitLine := strings.Split(line, ":")
|
||||
if len(splitLine) > 1 {
|
||||
key := strings.TrimSpace(splitLine[0])
|
||||
if key == "Version" {
|
||||
version = strings.TrimSpace(splitLine[1])
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return &packagemanager.Dependancy{
|
||||
Name: "docker ",
|
||||
PackageName: "N/A",
|
||||
Installed: installed,
|
||||
InstallCommand: "Available at https://www.docker.com/products/docker-desktop",
|
||||
Version: version,
|
||||
Optional: true,
|
||||
External: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,14 @@
|
||||
|
||||
package system
|
||||
|
||||
import "github.com/wailsapp/wails/v2/internal/system/operatingsystem"
|
||||
import (
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/system/packagemanager"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/system/operatingsystem"
|
||||
)
|
||||
|
||||
func (i *Info) discover() error {
|
||||
var err error
|
||||
@@ -11,5 +18,29 @@ func (i *Info) discover() error {
|
||||
return err
|
||||
}
|
||||
i.OS = osinfo
|
||||
|
||||
// Check for xcode command line tools
|
||||
output, err := exec.Command("xcode-select", "-v").Output()
|
||||
installed := true
|
||||
version := ""
|
||||
if err != nil {
|
||||
installed = false
|
||||
} else {
|
||||
version = strings.TrimPrefix(string(output), "xcode-select version ")
|
||||
version = strings.TrimSpace(version)
|
||||
version = strings.TrimSuffix(version, ".")
|
||||
}
|
||||
xcodeDep := &packagemanager.Dependancy{
|
||||
Name: "xcode command line tools ",
|
||||
PackageName: "N/A",
|
||||
Installed: installed,
|
||||
InstallCommand: "xcode-select --install",
|
||||
Version: version,
|
||||
Optional: false,
|
||||
External: false,
|
||||
}
|
||||
i.Dependencies = append(i.Dependencies, xcodeDep)
|
||||
i.Dependencies = append(i.Dependencies, checkNPM())
|
||||
i.Dependencies = append(i.Dependencies, checkUPX())
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
|
||||
package system
|
||||
|
||||
import "github.com/wailsapp/wails/v2/internal/system/operatingsystem"
|
||||
import (
|
||||
"github.com/wailsapp/wails/v2/internal/system/operatingsystem"
|
||||
"github.com/wailsapp/wails/v2/internal/system/packagemanager"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (i *Info) discover() error {
|
||||
|
||||
@@ -12,5 +17,29 @@ func (i *Info) discover() error {
|
||||
return err
|
||||
}
|
||||
i.OS = osinfo
|
||||
|
||||
// Check for gcc
|
||||
output, err := exec.Command("gcc", "--version").Output()
|
||||
installed := true
|
||||
version := ""
|
||||
if err != nil {
|
||||
installed = false
|
||||
} else {
|
||||
version = strings.TrimSpace(strings.Split(string(output), "\n")[0])
|
||||
}
|
||||
gccDependency := &packagemanager.Dependancy{
|
||||
Name: "gcc ",
|
||||
PackageName: "N/A",
|
||||
Installed: installed,
|
||||
InstallCommand: "Available at https://jmeubank.github.io/tdm-gcc/",
|
||||
Version: version,
|
||||
Optional: false,
|
||||
External: false,
|
||||
}
|
||||
i.Dependencies = append(i.Dependencies, gccDependency)
|
||||
i.Dependencies = append(i.Dependencies, checkNPM())
|
||||
i.Dependencies = append(i.Dependencies, checkUPX())
|
||||
i.Dependencies = append(i.Dependencies, checkDocker())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
# Assets Directory
|
||||
# Build Directory
|
||||
|
||||
The assets directory is used to house all the assets of your application.
|
||||
The build directory is used to house all the build files and assets for your application.
|
||||
|
||||
The structure is:
|
||||
|
||||
* bin - Output directory
|
||||
* dialog - Icons for dialogs
|
||||
* tray - Icons for the system tray
|
||||
* mac - MacOS specific files
|
||||
BIN
v2/pkg/buildassets/build/appicon.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
14
v2/pkg/buildassets/build/darwin/Info.tmpl.plist
Normal file
@@ -0,0 +1,14 @@
|
||||
<!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>{{.Name}}</string>
|
||||
<key>CFBundleExecutable</key><string>{{.Name}}</string>
|
||||
<key>CFBundleIdentifier</key><string>com.wails.{{.Name}}</string>
|
||||
<key>CFBundleVersion</key><string>1.0.0</string>
|
||||
<key>CFBundleGetInfoString</key><string>Built using Wails (https://wails.app)</string>
|
||||
<key>CFBundleShortVersionString</key><string>1.0.0</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>Copyright.........</string>
|
||||
</dict></plist>
|
||||
3
v2/pkg/buildassets/build/dialog/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Default Dialog Icons
|
||||
|
||||
This directory contains the default dialog icons. These are pre-compiled into a single C file (`defaultDialogIcons.c`) which resides in the `ffenestri` directory. If these icons are ever updated, then there is a need to run: `go run build.go` in this directory. This will generate a new `defaultDialogIcons.c` file in the `ffenestri` directory.
|
||||
BIN
v2/pkg/buildassets/build/dialog/info-dark.png
Normal file
|
After Width: | Height: | Size: 780 B |
BIN
v2/pkg/buildassets/build/dialog/info-dark2x.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
v2/pkg/buildassets/build/dialog/info-light.png
Normal file
|
After Width: | Height: | Size: 764 B |
BIN
v2/pkg/buildassets/build/dialog/info-light2x.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
v2/pkg/buildassets/build/dialog/question-dark.png
Normal file
|
After Width: | Height: | Size: 941 B |
BIN
v2/pkg/buildassets/build/dialog/question-dark2x.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
v2/pkg/buildassets/build/dialog/question-light.png
Normal file
|
After Width: | Height: | Size: 930 B |
BIN
v2/pkg/buildassets/build/dialog/question-light2x.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
v2/pkg/buildassets/build/dialog/warning-dark.png
Normal file
|
After Width: | Height: | Size: 830 B |
BIN
v2/pkg/buildassets/build/dialog/warning-dark2x.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
v2/pkg/buildassets/build/dialog/warning-light.png
Normal file
|
After Width: | Height: | Size: 720 B |
BIN
v2/pkg/buildassets/build/dialog/warning-light2x.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
12
v2/pkg/buildassets/build/windows/wails.exe.manifest
Normal file
@@ -0,0 +1,12 @@
|
||||
<?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="MyApplication" version="1.0.0.0" processorArchitecture="amd64"/>
|
||||
|
||||
<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 -->
|
||||
<gdiScaling xmlns="http://schemas.microsoft.com/SMI/2017/WindowsSettings">true</gdiScaling> <!-- enables GDI DPI scaling -->
|
||||
</asmv3:windowsSettings>
|
||||
</asmv3:application>
|
||||
</assembly>
|
||||
2
v2/pkg/buildassets/build/windows/wails.rc.tmpl
Normal file
@@ -0,0 +1,2 @@
|
||||
100 ICON "app.ico"
|
||||
110 24 "{{.Name}}.exe.manifest"
|
||||
84
v2/pkg/buildassets/buildassets.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package buildassets
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"github.com/leaanthony/debme"
|
||||
"github.com/leaanthony/gosod"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
//go:embed build
|
||||
var assets embed.FS
|
||||
|
||||
type assetData struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
// Install will install all default project assets
|
||||
func Install(targetDir string, projectName string) error {
|
||||
templateDir := gosod.New(assets)
|
||||
err := templateDir.Extract(targetDir, &assetData{Name: projectName})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Rename the manifest file
|
||||
windowsDir := filepath.Join(targetDir, "build", "windows")
|
||||
manifest := filepath.Join(windowsDir, "wails.exe.manifest")
|
||||
targetFile := filepath.Join(windowsDir, projectName+".exe.manifest")
|
||||
err = os.Rename(manifest, targetFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Rename the rc file
|
||||
rc := filepath.Join(windowsDir, "wails.rc")
|
||||
targetFile = filepath.Join(windowsDir, projectName+".rc")
|
||||
err = os.Rename(rc, targetFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegenerateRCFile will recreate the RC file
|
||||
func RegenerateRCFile(projectDir string, projectName string) error {
|
||||
targetFile, err := os.OpenFile(filepath.Join(projectDir, "build", "windows", projectName+".rc"), os.O_CREATE, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data := &assetData{Name: projectName}
|
||||
templateData, err := assets.ReadFile("build/windows/wails.rc.tmpl")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tmpl, err := template.New("rc").Parse(string(templateData))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = tmpl.Execute(targetFile, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func RegenerateManifest(target string) error {
|
||||
a, err := debme.FS(assets, "build")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return a.CopyFile("windows/wails.exe.manifest", target, 0644)
|
||||
}
|
||||
|
||||
func RegenerateAppIcon(target string) error {
|
||||
a, err := debme.FS(assets, "build")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return a.CopyFile("appicon.png", target, 0644)
|
||||
}
|
||||
@@ -152,7 +152,16 @@ func (b *BaseBuilder) CleanUp() {
|
||||
func (b *BaseBuilder) OutputFilename(options *Options) string {
|
||||
outputFile := options.OutputFile
|
||||
if outputFile == "" {
|
||||
outputFile = b.projectData.OutputFilename
|
||||
target := strings.TrimSuffix(b.projectData.OutputFilename, ".exe")
|
||||
if b.projectData.OutputType != "desktop" {
|
||||
target += "-" + b.projectData.OutputType
|
||||
}
|
||||
switch b.options.Platform {
|
||||
case "windows":
|
||||
outputFile = b.projectData.OutputFilename
|
||||
case "darwin", "linux":
|
||||
outputFile = fmt.Sprintf("%s-%s-%s", target, b.options.Platform, b.options.Arch)
|
||||
}
|
||||
}
|
||||
return outputFile
|
||||
}
|
||||
@@ -306,7 +315,7 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
|
||||
println("Done.")
|
||||
// If we are targeting windows, dump the DLLs
|
||||
if options.Platform == "windows" {
|
||||
err := os.WriteFile(filepath.Join(appDir, "webview2.dll"), x64.WebView2, 0755)
|
||||
err := os.WriteFile(filepath.Join(appDir, "webview.dll"), x64.WebView2, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -328,16 +337,23 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if verbose {
|
||||
println("upx", "--best", "--no-color", "--no-progress", options.CompiledBinary)
|
||||
var args = []string{"--best", "--no-color", "--no-progress", options.CompiledBinary}
|
||||
|
||||
if options.CompressFlags != "" {
|
||||
args = strings.Split(options.CompressFlags, " ")
|
||||
args = append(args, options.CompiledBinary)
|
||||
}
|
||||
|
||||
output, err := exec.Command("upx", "--best", "--no-color", "--no-progress", options.CompiledBinary).Output()
|
||||
if verbose {
|
||||
println("upx", strings.Join(args, " "))
|
||||
}
|
||||
|
||||
output, err := exec.Command("upx", args...).Output()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Error during compression:")
|
||||
}
|
||||
if verbose {
|
||||
println(output)
|
||||
println(string(output))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package build
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
@@ -32,7 +33,7 @@ type Options struct {
|
||||
UserTags []string // Tags to pass to the Go compiler
|
||||
Logger *clilogger.CLILogger // All output to the logger
|
||||
OutputType string // EG: desktop, server....
|
||||
Mode Mode // release or debug
|
||||
Mode Mode // release or debug or dev
|
||||
ProjectData *project.Project // The project data
|
||||
Pack bool // Create a package for the app after building
|
||||
Platform string // The platform to build for
|
||||
@@ -46,6 +47,7 @@ type Options struct {
|
||||
KeepAssets bool // Keep the generated assets/files
|
||||
Verbosity int // Verbosity level (0 - silent, 1 - default, 2 - verbose)
|
||||
Compress bool // Compress the final binary
|
||||
CompressFlags string // Flags to pass to UPX
|
||||
AppleIdentity string
|
||||
}
|
||||
|
||||
@@ -74,7 +76,7 @@ func Build(options *Options) (string, error) {
|
||||
options.ProjectData = projectData
|
||||
|
||||
// Set build directory
|
||||
options.BuildDirectory = filepath.Join(options.ProjectData.Path, "build", options.Platform, options.OutputType)
|
||||
options.BuildDirectory = filepath.Join(options.ProjectData.Path, "build", "bin")
|
||||
|
||||
// Save the project type
|
||||
projectData.OutputType = options.OutputType
|
||||
@@ -121,6 +123,25 @@ func Build(options *Options) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// If we are building for windows, we will need to generate the asset bundle before
|
||||
// compilation. This will be a .syso file in the project root
|
||||
if options.Pack && options.Platform == "windows" {
|
||||
outputLogger.Print("Generating bundle assets: ")
|
||||
err := packageApplication(options)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
outputLogger.Println("Done.")
|
||||
|
||||
// When we finish, we will want to remove the syso file
|
||||
defer func() {
|
||||
err := os.Remove(filepath.Join(options.ProjectData.Path, options.ProjectData.Name+"-res.syso"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Compile the application
|
||||
outputLogger.Print("Compiling application: ")
|
||||
|
||||
@@ -161,8 +182,14 @@ func Build(options *Options) (string, error) {
|
||||
return "", fmt.Errorf("%s - %s", err.Error(), stderr)
|
||||
}
|
||||
// Remove temp binaries
|
||||
fs.DeleteFile(filepath.Join(options.BuildDirectory, amd64Filename))
|
||||
fs.DeleteFile(filepath.Join(options.BuildDirectory, arm64Filename))
|
||||
err = fs.DeleteFile(filepath.Join(options.BuildDirectory, amd64Filename))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
err = fs.DeleteFile(filepath.Join(options.BuildDirectory, arm64Filename))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
projectData.OutputFilename = outputFile
|
||||
options.CompiledBinary = filepath.Join(options.BuildDirectory, outputFile)
|
||||
} else {
|
||||
@@ -171,10 +198,9 @@ func Build(options *Options) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
outputLogger.Println("Done.")
|
||||
|
||||
// Do we need to pack the app?
|
||||
if options.Pack {
|
||||
// Do we need to pack the app for non-windows?
|
||||
if options.Pack && options.Platform != "windows" {
|
||||
|
||||
outputLogger.Print("Packaging application: ")
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package build
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/wailsapp/wails/v2/pkg/buildassets"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
|
||||
@@ -25,11 +26,9 @@ func (d *DesktopBuilder) BuildAssets(options *Options) error {
|
||||
var err error
|
||||
|
||||
// Check assets directory exists
|
||||
if !fs.DirExists(options.ProjectData.AssetsDir) {
|
||||
if !fs.DirExists(options.ProjectData.BuildDir) {
|
||||
// Path to default assets
|
||||
defaultAssets := fs.RelativePath("./internal/assets")
|
||||
// Copy the default assets directory
|
||||
err := fs.CopyDir(defaultAssets, options.ProjectData.AssetsDir)
|
||||
err := buildassets.Install(options.ProjectData.Path, options.ProjectData.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -106,9 +105,9 @@ func (d *DesktopBuilder) BuildBaseAssets(assets *html.AssetBundle, options *Opti
|
||||
func (d *DesktopBuilder) processApplicationIcon(assetDir string) error {
|
||||
|
||||
// Copy default icon if one doesn't exist
|
||||
iconFile := filepath.Join(d.projectData.AssetsDir, "appicon.png")
|
||||
iconFile := filepath.Join(d.projectData.BuildDir, "appicon.png")
|
||||
if !fs.FileExists(iconFile) {
|
||||
err := fs.CopyFile(defaultIconPath(), iconFile)
|
||||
err := buildassets.RegenerateAppIcon(iconFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ func (d *DesktopBuilder) processTrayIcons(assetDir string, options *Options) err
|
||||
var err error
|
||||
|
||||
// Get all the tray icon filenames
|
||||
trayIconDirectory := filepath.Join(options.ProjectData.AssetsDir, "tray")
|
||||
trayIconDirectory := filepath.Join(options.ProjectData.BuildDir, "tray")
|
||||
|
||||
// If the directory doesn't exist, create it
|
||||
if !fs.DirExists(trayIconDirectory) {
|
||||
@@ -116,7 +116,7 @@ func (d *DesktopBuilder) processDialogIcons(assetDir string, options *Options) e
|
||||
var err error
|
||||
|
||||
// Get all the dialog icon filenames
|
||||
dialogIconDirectory := filepath.Join(options.ProjectData.AssetsDir, "dialog")
|
||||
dialogIconDirectory := filepath.Join(options.ProjectData.BuildDir, "dialog")
|
||||
var dialogIconFilenames []string
|
||||
|
||||
// If the directory does not exist, create it
|
||||
|
||||
@@ -17,7 +17,7 @@ func (d *DesktopBuilder) compileIcon(assetDir string, iconFile string) error {
|
||||
|
||||
// Load icon into a databuffer
|
||||
targetFilename := "icon"
|
||||
targetFile := filepath.Join(assetDir, targetFilename+".c")
|
||||
targetFile := filepath.Join(assetDir, targetFilename+".h")
|
||||
|
||||
d.addFileToDelete(targetFile)
|
||||
|
||||
@@ -33,7 +33,10 @@ func (d *DesktopBuilder) compileIcon(assetDir string, iconFile string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f.Close()
|
||||
err = f.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var buf strings.Builder
|
||||
|
||||
@@ -52,3 +55,181 @@ func (d *DesktopBuilder) compileIcon(assetDir string, iconFile string) error {
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// We will compile all tray icons found at <projectdir>/assets/trayicons/*.png into the application
|
||||
func (d *DesktopBuilder) processTrayIcons(assetDir string, options *Options) error {
|
||||
//
|
||||
// var err error
|
||||
//
|
||||
// // Get all the tray icon filenames
|
||||
// trayIconDirectory := filepath.Join(options.ProjectData.BuildDir, "tray")
|
||||
//
|
||||
// // If the directory doesn't exist, create it
|
||||
// if !fs.DirExists(trayIconDirectory) {
|
||||
// err = fs.MkDirs(trayIconDirectory)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// var trayIconFilenames []string
|
||||
// trayIconFilenames, err = filepath.Glob(trayIconDirectory + "/*.png")
|
||||
// if err != nil {
|
||||
// log.Fatal(err)
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// // Setup target
|
||||
// targetFilename := "trayicons"
|
||||
// targetFile := filepath.Join(assetDir, targetFilename+".h")
|
||||
// d.addFileToDelete(targetFile)
|
||||
//
|
||||
// var dataBytes []byte
|
||||
//
|
||||
// // Use a strings builder
|
||||
// var cdata strings.Builder
|
||||
//
|
||||
// // Write header
|
||||
// header := `// trayicons.h
|
||||
//// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Ă‚ MODIWL.
|
||||
//// This file was auto-generated. DO NOT MODIFY.
|
||||
//
|
||||
//`
|
||||
// cdata.WriteString(header)
|
||||
//
|
||||
// var variableList slicer.StringSlicer
|
||||
//
|
||||
// // Loop over icons
|
||||
// for count, filename := range trayIconFilenames {
|
||||
//
|
||||
// // Load the tray icon
|
||||
// dataBytes, err = ioutil.ReadFile(filename)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// iconname := strings.TrimSuffix(filepath.Base(filename), ".png")
|
||||
// trayIconName := fmt.Sprintf("trayIcon%dName", count)
|
||||
// variableList.Add(trayIconName)
|
||||
// cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { %s0x00 };\n", trayIconName, d.convertToHexLiteral([]byte(iconname))))
|
||||
//
|
||||
// trayIconLength := fmt.Sprintf("trayIcon%dLength", count)
|
||||
// variableList.Add(trayIconLength)
|
||||
// lengthAsString := strconv.Itoa(len(dataBytes))
|
||||
// cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { %s0x00 };\n", trayIconLength, d.convertToHexLiteral([]byte(lengthAsString))))
|
||||
//
|
||||
// trayIconData := fmt.Sprintf("trayIcon%dData", count)
|
||||
// variableList.Add(trayIconData)
|
||||
// cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { ", trayIconData))
|
||||
//
|
||||
// // Convert each byte to hex
|
||||
// for _, b := range dataBytes {
|
||||
// cdata.WriteString(fmt.Sprintf("0x%x, ", b))
|
||||
// }
|
||||
//
|
||||
// cdata.WriteString("0x00 };\n")
|
||||
// }
|
||||
//
|
||||
// // Write out main trayIcons data
|
||||
// cdata.WriteString("const unsigned char *trayIcons[] = { ")
|
||||
// cdata.WriteString(variableList.Join(", "))
|
||||
// if len(trayIconFilenames) > 0 {
|
||||
// cdata.WriteString(", ")
|
||||
// }
|
||||
// cdata.WriteString("0x00 };\n")
|
||||
//
|
||||
// err = ioutil.WriteFile(targetFile, []byte(cdata.String()), 0600)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
return nil
|
||||
}
|
||||
|
||||
// We will compile all dialog icons found at <projectdir>/icons/dialog/*.png into the application
|
||||
func (d *DesktopBuilder) processDialogIcons(assetDir string, options *Options) error {
|
||||
|
||||
// var err error
|
||||
//
|
||||
// // Get all the dialog icon filenames
|
||||
// dialogIconDirectory := filepath.Join(options.ProjectData.BuildDir, "dialog")
|
||||
// var dialogIconFilenames []string
|
||||
//
|
||||
// // If the directory does not exist, create it
|
||||
// if !fs.DirExists(dialogIconDirectory) {
|
||||
// err = fs.MkDirs(dialogIconDirectory)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// dialogIconFilenames, err = filepath.Glob(dialogIconDirectory + "/*.png")
|
||||
// if err != nil {
|
||||
// log.Fatal(err)
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// // Setup target
|
||||
// targetFilename := "userdialogicons"
|
||||
// targetFile := filepath.Join(assetDir, targetFilename+".h")
|
||||
// d.addFileToDelete(targetFile)
|
||||
//
|
||||
// var dataBytes []byte
|
||||
//
|
||||
// // Use a strings builder
|
||||
// var cdata strings.Builder
|
||||
//
|
||||
// // Write header
|
||||
// header := `// userdialogicons.h
|
||||
//// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Ă‚ MODIWL.
|
||||
//// This file was auto-generated. DO NOT MODIFY.
|
||||
//
|
||||
//`
|
||||
// cdata.WriteString(header)
|
||||
//
|
||||
// var variableList slicer.StringSlicer
|
||||
//
|
||||
// // Loop over icons
|
||||
// for count, filename := range dialogIconFilenames {
|
||||
//
|
||||
// // Load the tray icon
|
||||
// dataBytes, err = ioutil.ReadFile(filename)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// iconname := strings.TrimSuffix(filepath.Base(filename), ".png")
|
||||
// dialogIconName := fmt.Sprintf("userDialogIcon%dName", count)
|
||||
// variableList.Add(dialogIconName)
|
||||
// cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { %s0x00 };\n", dialogIconName, d.convertToHexLiteral([]byte(iconname))))
|
||||
//
|
||||
// dialogIconLength := fmt.Sprintf("userDialogIcon%dLength", count)
|
||||
// variableList.Add(dialogIconLength)
|
||||
// lengthAsString := strconv.Itoa(len(dataBytes))
|
||||
// cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { %s0x00 };\n", dialogIconLength, d.convertToHexLiteral([]byte(lengthAsString))))
|
||||
//
|
||||
// dialogIconData := fmt.Sprintf("userDialogIcon%dData", count)
|
||||
// variableList.Add(dialogIconData)
|
||||
// cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { ", dialogIconData))
|
||||
//
|
||||
// // Convert each byte to hex
|
||||
// for _, b := range dataBytes {
|
||||
// cdata.WriteString(fmt.Sprintf("0x%x, ", b))
|
||||
// }
|
||||
//
|
||||
// cdata.WriteString("0x00 };\n")
|
||||
// }
|
||||
//
|
||||
// // Write out main dialogIcons data
|
||||
// cdata.WriteString("const unsigned char *userDialogIcons[] = { ")
|
||||
// cdata.WriteString(variableList.Join(", "))
|
||||
// if len(dialogIconFilenames) > 0 {
|
||||
// cdata.WriteString(", ")
|
||||
// }
|
||||
// cdata.WriteString("0x00 };\n")
|
||||
//
|
||||
// err = ioutil.WriteFile(targetFile, []byte(cdata.String()), 0600)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ func (d *DesktopBuilder) processTrayIcons(assetDir string, options *Options) err
|
||||
// var err error
|
||||
//
|
||||
// // Get all the tray icon filenames
|
||||
// trayIconDirectory := filepath.Join(options.ProjectData.AssetsDir, "tray")
|
||||
// trayIconDirectory := filepath.Join(options.ProjectData.BuildDir, "tray")
|
||||
//
|
||||
// // If the directory doesn't exist, create it
|
||||
// if !fs.DirExists(trayIconDirectory) {
|
||||
@@ -97,7 +97,7 @@ func (d *DesktopBuilder) processDialogIcons(assetDir string, options *Options) e
|
||||
// var err error
|
||||
//
|
||||
// // Get all the dialog icon filenames
|
||||
// dialogIconDirectory := filepath.Join(options.ProjectData.AssetsDir, "dialog")
|
||||
// dialogIconDirectory := filepath.Join(options.ProjectData.BuildDir, "dialog")
|
||||
// var dialogIconFilenames []string
|
||||
//
|
||||
// // If the directory does not exist, create it
|
||||
|
||||
@@ -30,12 +30,6 @@ func (b *HybridBuilder) BuildAssets(options *Options) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Build static assets
|
||||
err = b.buildCustomAssets(b.projectData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -63,18 +57,6 @@ func (b *HybridBuilder) BuildBaseAssets(options *Options) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Build desktop static assets
|
||||
err = b.desktop.buildCustomAssets(b.projectData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Build server static assets
|
||||
err = b.server.buildCustomAssets(b.projectData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
<plist version="1.0"><dict>
|
||||
<key>CFBundlePackageType</key><string>APPL</string>
|
||||
<key>CFBundleName</key><string>{{.Title}}</string>
|
||||
<key>CFBundleExecutable</key><string>{{.Exe}}</string>
|
||||
<key>CFBundleIdentifier</key><string>{{.PackageID}}</string>
|
||||
<key>CFBundleVersion</key><string>{{.Version}}</string>
|
||||
<key>CFBundleGetInfoString</key><string>Built by {{.Author}} using Wails (https://wails.app)</string>
|
||||
<key>CFBundleShortVersionString</key><string>{{.Version}}</string>
|
||||
<key>CFBundleExecutable</key><string>{{.Title}}</string>
|
||||
<key>CFBundleIdentifier</key><string>com.wails.{{.Title}}</string>
|
||||
<key>CFBundleVersion</key><string>1.0.0</string>
|
||||
<key>CFBundleGetInfoString</key><string>Built using Wails (https://wails.app)</string>
|
||||
<key>CFBundleShortVersionString</key><string>1.0.0</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>Copyright.........</string>
|
||||
</dict></plist>
|
||||