mirror of
https://github.com/taigrr/wails.git
synced 2026-04-17 12:15:02 -07:00
Compare commits
36 Commits
v2.0.0-alp
...
v2.0.0-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5231a6893b | ||
|
|
74f3ce990f | ||
|
|
998a913853 | ||
|
|
964844835c | ||
|
|
4e152bb849 | ||
|
|
51133d098c | ||
|
|
d4191e7d1b | ||
|
|
9c273bc745 | ||
|
|
c6f6ad6beb | ||
|
|
4362a14459 | ||
|
|
0080e9e311 | ||
|
|
83d9297cac | ||
|
|
d8ad250608 | ||
|
|
eac8880f6d | ||
|
|
f47100e71c | ||
|
|
9a81a57d13 | ||
|
|
354429bc28 | ||
|
|
99d4d9490c | ||
|
|
61afe711bd | ||
|
|
6e3cfc157f | ||
|
|
30d762372f | ||
|
|
2dbaabb74c | ||
|
|
f8bae0430f | ||
|
|
21c07497d7 | ||
|
|
9b9bcd657f | ||
|
|
02038aa543 | ||
|
|
9910d1127a | ||
|
|
21a0245985 | ||
|
|
e860f3a00e | ||
|
|
2e480d2c52 | ||
|
|
2c0f93d647 | ||
|
|
41f973c7d5 | ||
|
|
2d1447d558 | ||
|
|
7c22cbcf38 | ||
|
|
e4b03f510b | ||
|
|
8dfd206aa9 |
@@ -3,12 +3,12 @@
|
|||||||
"browser": true,
|
"browser": true,
|
||||||
"es6": true,
|
"es6": true,
|
||||||
"amd": true,
|
"amd": true,
|
||||||
"node": true,
|
"node": true
|
||||||
},
|
},
|
||||||
"extends": "eslint:recommended",
|
"extends": "eslint:recommended",
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
"ecmaVersion": 2016,
|
"ecmaVersion": 2016,
|
||||||
"sourceType": "module",
|
"sourceType": "module"
|
||||||
},
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
"indent": [
|
"indent": [
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
bridge.js
|
index.js
|
||||||
@@ -5,33 +5,42 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/internal/colour"
|
||||||
|
|
||||||
"github.com/fsnotify/fsnotify"
|
"github.com/fsnotify/fsnotify"
|
||||||
"github.com/leaanthony/clir"
|
"github.com/leaanthony/clir"
|
||||||
"github.com/leaanthony/slicer"
|
|
||||||
"github.com/wailsapp/wails/v2/internal/fs"
|
"github.com/wailsapp/wails/v2/internal/fs"
|
||||||
"github.com/wailsapp/wails/v2/internal/process"
|
"github.com/wailsapp/wails/v2/internal/process"
|
||||||
"github.com/wailsapp/wails/v2/pkg/clilogger"
|
"github.com/wailsapp/wails/v2/pkg/clilogger"
|
||||||
"github.com/wailsapp/wails/v2/pkg/commands/build"
|
"github.com/wailsapp/wails/v2/pkg/commands/build"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func LogGreen(message string, args ...interface{}) {
|
||||||
|
text := fmt.Sprintf(message, args...)
|
||||||
|
println(colour.Green(text))
|
||||||
|
}
|
||||||
|
|
||||||
|
func LogRed(message string, args ...interface{}) {
|
||||||
|
text := fmt.Sprintf(message, args...)
|
||||||
|
println(colour.Red(text))
|
||||||
|
}
|
||||||
|
|
||||||
|
func LogDarkYellow(message string, args ...interface{}) {
|
||||||
|
text := fmt.Sprintf(message, args...)
|
||||||
|
println(colour.DarkYellow(text))
|
||||||
|
}
|
||||||
|
|
||||||
// AddSubcommand adds the `dev` command for the Wails application
|
// AddSubcommand adds the `dev` command for the Wails application
|
||||||
func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
||||||
|
|
||||||
command := app.NewSubCommand("dev", "Development mode")
|
command := app.NewSubCommand("dev", "Development mode")
|
||||||
|
|
||||||
outputType := "desktop"
|
|
||||||
|
|
||||||
validTargetTypes := slicer.String([]string{"desktop", "hybrid", "server"})
|
|
||||||
|
|
||||||
// Setup target type flag
|
|
||||||
description := "Type of application to develop. Valid types: " + validTargetTypes.Join(",")
|
|
||||||
command.StringFlag("t", description, &outputType)
|
|
||||||
|
|
||||||
// Passthrough ldflags
|
// Passthrough ldflags
|
||||||
ldflags := ""
|
ldflags := ""
|
||||||
command.StringFlag("ldflags", "optional ldflags", &ldflags)
|
command.StringFlag("ldflags", "optional ldflags", &ldflags)
|
||||||
@@ -42,15 +51,17 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
|||||||
|
|
||||||
// extensions to trigger rebuilds
|
// extensions to trigger rebuilds
|
||||||
extensions := "go"
|
extensions := "go"
|
||||||
command.StringFlag("m", "Extensions to trigger rebuilds (comma separated) eg go,js,css,html", &extensions)
|
command.StringFlag("e", "Extensions to trigger rebuilds (comma separated) eg go,js,css,html", &extensions)
|
||||||
|
|
||||||
|
// extensions to trigger rebuilds
|
||||||
|
showWarnings := false
|
||||||
|
command.BoolFlag("w", "Show warnings", &showWarnings)
|
||||||
|
|
||||||
|
loglevel := ""
|
||||||
|
command.StringFlag("loglevel", "Loglevel to use - Trace, Debug, Info, Warning, Error", &loglevel)
|
||||||
|
|
||||||
command.Action(func() error {
|
command.Action(func() error {
|
||||||
|
|
||||||
// Validate inputs
|
|
||||||
if !validTargetTypes.Contains(outputType) {
|
|
||||||
return fmt.Errorf("output type '%s' is not valid", outputType)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create logger
|
// Create logger
|
||||||
logger := clilogger.New(w)
|
logger := clilogger.New(w)
|
||||||
app.PrintBanner()
|
app.PrintBanner()
|
||||||
@@ -64,7 +75,6 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
|||||||
defer watcher.Close()
|
defer watcher.Close()
|
||||||
|
|
||||||
var debugBinaryProcess *process.Process = nil
|
var debugBinaryProcess *process.Process = nil
|
||||||
var buildFrontend bool = true
|
|
||||||
var extensionsThatTriggerARebuild = strings.Split(extensions, ",")
|
var extensionsThatTriggerARebuild = strings.Split(extensions, ",")
|
||||||
|
|
||||||
// Setup signal handler
|
// Setup signal handler
|
||||||
@@ -75,8 +85,13 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
|||||||
|
|
||||||
// Do initial build
|
// Do initial build
|
||||||
logger.Println("Building application for development...")
|
logger.Println("Building application for development...")
|
||||||
debugBinaryProcess = restartApp(logger, outputType, ldflags, compilerCommand, buildFrontend, debugBinaryProcess)
|
newProcess, err := restartApp(logger, "dev", ldflags, compilerCommand, debugBinaryProcess, loglevel)
|
||||||
|
if newProcess != nil {
|
||||||
|
debugBinaryProcess = newProcess
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
go debounce(100*time.Millisecond, watcher.Events, debounceQuit, func(event fsnotify.Event) {
|
go debounce(100*time.Millisecond, watcher.Events, debounceQuit, func(event fsnotify.Event) {
|
||||||
// logger.Println("event: %+v", event)
|
// logger.Println("event: %+v", event)
|
||||||
|
|
||||||
@@ -89,7 +104,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatal("%s", err.Error())
|
logger.Fatal("%s", err.Error())
|
||||||
}
|
}
|
||||||
logger.Println("Watching directory: %s", event.Name)
|
LogGreen("[New Directory] Watching new directory: %s", event.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -98,38 +113,33 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
|||||||
// Check for file writes
|
// Check for file writes
|
||||||
if event.Op&fsnotify.Write == fsnotify.Write {
|
if event.Op&fsnotify.Write == fsnotify.Write {
|
||||||
|
|
||||||
// logger.Println("modified file: %s", event.Name)
|
|
||||||
var rebuild bool = false
|
var rebuild bool = false
|
||||||
|
|
||||||
// Iterate all file patterns
|
// Iterate all file patterns
|
||||||
for _, pattern := range extensionsThatTriggerARebuild {
|
for _, pattern := range extensionsThatTriggerARebuild {
|
||||||
rebuild = strings.HasSuffix(event.Name, pattern)
|
if strings.HasSuffix(event.Name, pattern) {
|
||||||
if err != nil {
|
rebuild = true
|
||||||
logger.Fatal(err.Error())
|
|
||||||
}
|
|
||||||
if rebuild {
|
|
||||||
// Only build frontend when the file isn't a Go file
|
|
||||||
buildFrontend = !strings.HasSuffix(event.Name, "go")
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !rebuild {
|
if !rebuild {
|
||||||
logger.Println("Filename change: %s did not match extension list %s", event.Name, extensions)
|
if showWarnings {
|
||||||
|
LogDarkYellow("[File change] %s did not match extension list (%s)", event.Name, extensions)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if buildFrontend {
|
LogGreen("[Attempting rebuild] %s updated", event.Name)
|
||||||
logger.Println("Full rebuild triggered: %s updated", event.Name)
|
|
||||||
} else {
|
|
||||||
logger.Println("Partial build triggered: %s updated", event.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do a rebuild
|
// Do a rebuild
|
||||||
|
|
||||||
// Try and build the app
|
// Try and build the app
|
||||||
newBinaryProcess := restartApp(logger, outputType, ldflags, compilerCommand, buildFrontend, debugBinaryProcess)
|
newBinaryProcess, err := restartApp(logger, "dev", ldflags, compilerCommand, debugBinaryProcess, loglevel)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error during build: %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
// If we have a new process, save it
|
// If we have a new process, save it
|
||||||
if newBinaryProcess != nil {
|
if newBinaryProcess != nil {
|
||||||
debugBinaryProcess = newBinaryProcess
|
debugBinaryProcess = newBinaryProcess
|
||||||
@@ -139,23 +149,28 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Get project dir
|
// Get project dir
|
||||||
dir, err := os.Getwd()
|
projectDir, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all subdirectories
|
// Get all subdirectories
|
||||||
dirs, err := fs.GetSubdirectories(dir)
|
dirs, err := fs.GetSubdirectories(projectDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LogGreen("Watching (sub)/directory: %s", projectDir)
|
||||||
|
|
||||||
// Setup a watcher for non-node_modules directories
|
// Setup a watcher for non-node_modules directories
|
||||||
dirs.Each(func(dir string) {
|
dirs.Each(func(dir string) {
|
||||||
if strings.Contains(dir, "node_modules") {
|
if strings.Contains(dir, "node_modules") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.Println("Watching directory: %s", dir)
|
// Ignore build directory
|
||||||
|
if strings.HasPrefix(dir, filepath.Join(projectDir, "build")) {
|
||||||
|
return
|
||||||
|
}
|
||||||
err = watcher.Add(dir)
|
err = watcher.Add(dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatal(err.Error())
|
logger.Fatal(err.Error())
|
||||||
@@ -167,7 +182,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
|||||||
for quit == false {
|
for quit == false {
|
||||||
select {
|
select {
|
||||||
case <-quitChannel:
|
case <-quitChannel:
|
||||||
println()
|
LogGreen("\nCaught quit")
|
||||||
// Notify debouncer to quit
|
// Notify debouncer to quit
|
||||||
debounceQuit <- true
|
debounceQuit <- true
|
||||||
quit = true
|
quit = true
|
||||||
@@ -182,7 +197,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Println("Development mode exited")
|
LogGreen("Development mode exited")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@@ -209,15 +224,15 @@ exit:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func restartApp(logger *clilogger.CLILogger, outputType string, ldflags string, compilerCommand string, buildFrontend bool, debugBinaryProcess *process.Process) *process.Process {
|
func restartApp(logger *clilogger.CLILogger, outputType string, ldflags string, compilerCommand string, debugBinaryProcess *process.Process, loglevel string) (*process.Process, error) {
|
||||||
|
|
||||||
appBinary, err := buildApp(logger, outputType, ldflags, compilerCommand, buildFrontend)
|
appBinary, err := buildApp(logger, outputType, ldflags, compilerCommand)
|
||||||
println()
|
println()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Println("[ERROR] Build Failed: %s", err.Error())
|
LogRed("Build error - continuing to run current version")
|
||||||
return nil
|
LogDarkYellow(err.Error())
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
logger.Println("Build new binary: %s", appBinary)
|
|
||||||
|
|
||||||
// Kill existing binary if need be
|
// Kill existing binary if need be
|
||||||
if debugBinaryProcess != nil {
|
if debugBinaryProcess != nil {
|
||||||
@@ -233,7 +248,7 @@ func restartApp(logger *clilogger.CLILogger, outputType string, ldflags string,
|
|||||||
// TODO: Generate `backend.js`
|
// TODO: Generate `backend.js`
|
||||||
|
|
||||||
// Start up new binary
|
// Start up new binary
|
||||||
newProcess := process.NewProcess(logger, appBinary)
|
newProcess := process.NewProcess(logger, appBinary, "-loglevel", loglevel)
|
||||||
err = newProcess.Start()
|
err = newProcess.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Remove binary
|
// Remove binary
|
||||||
@@ -244,13 +259,13 @@ func restartApp(logger *clilogger.CLILogger, outputType string, ldflags string,
|
|||||||
logger.Fatal("Unable to start application: %s", err.Error())
|
logger.Fatal("Unable to start application: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return newProcess
|
return newProcess, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildApp(logger *clilogger.CLILogger, outputType string, ldflags string, compilerCommand string, buildFrontend bool) (string, error) {
|
func buildApp(logger *clilogger.CLILogger, outputType string, ldflags string, compilerCommand string) (string, error) {
|
||||||
|
|
||||||
// Create random output file
|
// Create random output file
|
||||||
outputFile := fmt.Sprintf("debug-%d", time.Now().Unix())
|
outputFile := fmt.Sprintf("dev-%d", time.Now().Unix())
|
||||||
|
|
||||||
// Create BuildOptions
|
// Create BuildOptions
|
||||||
buildOptions := &build.Options{
|
buildOptions := &build.Options{
|
||||||
@@ -262,7 +277,7 @@ func buildApp(logger *clilogger.CLILogger, outputType string, ldflags string, co
|
|||||||
LDFlags: ldflags,
|
LDFlags: ldflags,
|
||||||
Compiler: compilerCommand,
|
Compiler: compilerCommand,
|
||||||
OutputFile: outputFile,
|
OutputFile: outputFile,
|
||||||
IgnoreFrontend: !buildFrontend,
|
IgnoreFrontend: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
return build.Build(buildOptions)
|
return build.Build(buildOptions)
|
||||||
|
|||||||
@@ -18,14 +18,14 @@ import (
|
|||||||
func AddSubcommand(app *clir.Cli, w io.Writer, currentVersion string) error {
|
func AddSubcommand(app *clir.Cli, w io.Writer, currentVersion string) error {
|
||||||
|
|
||||||
command := app.NewSubCommand("update", "Update the Wails CLI")
|
command := app.NewSubCommand("update", "Update the Wails CLI")
|
||||||
command.LongDescription(`This command allows you to update your version of Wails.`)
|
command.LongDescription(`This command allows you to update your version of the Wails CLI.`)
|
||||||
|
|
||||||
// Setup flags
|
// Setup flags
|
||||||
var prereleaseRequired bool
|
var prereleaseRequired bool
|
||||||
command.BoolFlag("pre", "Update to latest Prerelease", &prereleaseRequired)
|
command.BoolFlag("pre", "Update CLI to latest Prerelease", &prereleaseRequired)
|
||||||
|
|
||||||
var specificVersion string
|
var specificVersion string
|
||||||
command.StringFlag("version", "Install a specific version (Overrides other flags)", &specificVersion)
|
command.StringFlag("version", "Install a specific version (Overrides other flags) of the CLI", &specificVersion)
|
||||||
|
|
||||||
command.Action(func() error {
|
command.Action(func() error {
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ func updateToVersion(logger *clilogger.CLILogger, targetVersion *github.Semantic
|
|||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
logger.Print("Installing Wails " + desiredVersion + "...")
|
logger.Print("Installing Wails CLI " + desiredVersion + "...")
|
||||||
|
|
||||||
// Run command in non module directory
|
// Run command in non module directory
|
||||||
homeDir, err := os.UserHomeDir()
|
homeDir, err := os.UserHomeDir()
|
||||||
@@ -158,7 +158,7 @@ func updateToVersion(logger *clilogger.CLILogger, targetVersion *github.Semantic
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
logger.Println("Wails updated to " + desiredVersion)
|
logger.Println("Wails CLI updated to " + desiredVersion)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/internal/colour"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/cmd/wails/internal/commands/update"
|
"github.com/wailsapp/wails/v2/cmd/wails/internal/commands/update"
|
||||||
|
|
||||||
"github.com/leaanthony/clir"
|
"github.com/leaanthony/clir"
|
||||||
@@ -19,12 +22,18 @@ func fatal(message string) {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func banner(_ *clir.Cli) string {
|
||||||
|
return fmt.Sprintf("%s %s - Go/HTML Application Framework", colour.Yellow("Wails"), colour.DarkRed(version))
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
app := clir.NewCli("Wails", "Go/HTML Application Framework", version)
|
app := clir.NewCli("Wails", "Go/HTML Application Framework", version)
|
||||||
|
|
||||||
|
app.SetBannerFunction(banner)
|
||||||
|
|
||||||
build.AddBuildSubcommand(app, os.Stdout)
|
build.AddBuildSubcommand(app, os.Stdout)
|
||||||
err = initialise.AddSubcommand(app, os.Stdout)
|
err = initialise.AddSubcommand(app, os.Stdout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
var version = "v2.0.0-alpha.21"
|
var version = "v2.0.0-alpha.30"
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
module github.com/wailsapp/wails/v2
|
module github.com/wailsapp/wails/v2
|
||||||
|
|
||||||
go 1.15
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Masterminds/semver v1.5.0
|
github.com/Masterminds/semver v1.5.0
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/fatih/structtag v1.2.0
|
github.com/fatih/structtag v1.2.0
|
||||||
github.com/fsnotify/fsnotify v1.4.9
|
github.com/fsnotify/fsnotify v1.4.9
|
||||||
|
github.com/gorilla/websocket v1.4.1
|
||||||
github.com/imdario/mergo v0.3.11
|
github.com/imdario/mergo v0.3.11
|
||||||
github.com/jackmordaunt/icns v1.0.0
|
github.com/jackmordaunt/icns v1.0.0
|
||||||
github.com/leaanthony/clir v1.0.4
|
github.com/leaanthony/clir v1.0.4
|
||||||
@@ -14,16 +15,15 @@ require (
|
|||||||
github.com/leaanthony/slicer v1.5.0
|
github.com/leaanthony/slicer v1.5.0
|
||||||
github.com/matryer/is v1.4.0
|
github.com/matryer/is v1.4.0
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
|
||||||
github.com/olekukonko/tablewriter v0.0.4
|
github.com/olekukonko/tablewriter v0.0.4
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/tdewolff/minify v2.3.6+incompatible
|
github.com/tdewolff/minify v2.3.6+incompatible
|
||||||
github.com/tdewolff/parse v2.3.4+incompatible // indirect
|
github.com/tdewolff/parse v2.3.4+incompatible // indirect
|
||||||
github.com/tdewolff/test v1.0.6 // indirect
|
github.com/tdewolff/test v1.0.6 // indirect
|
||||||
|
github.com/wzshiming/ctc v1.2.3
|
||||||
github.com/xyproto/xpm v1.2.1
|
github.com/xyproto/xpm v1.2.1
|
||||||
golang.org/x/net v0.0.0-20200822124328-c89045814202
|
golang.org/x/net v0.0.0-20200822124328-c89045814202
|
||||||
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c
|
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c
|
||||||
golang.org/x/tools v0.0.0-20200902012652-d1954cc86c82
|
golang.org/x/tools v0.0.0-20200902012652-d1954cc86c82
|
||||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
|
|
||||||
nhooyr.io/websocket v1.8.6
|
nhooyr.io/websocket v1.8.6
|
||||||
)
|
)
|
||||||
|
|||||||
21
v2/go.sum
21
v2/go.sum
@@ -11,7 +11,6 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
|
|||||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
|
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
|
||||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
|
||||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||||
@@ -41,9 +40,6 @@ github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGn
|
|||||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/klauspost/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eTO0Q8=
|
github.com/klauspost/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eTO0Q8=
|
||||||
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|
||||||
github.com/leaanthony/clir v1.0.4 h1:Dov2y9zWJmZr7CjaCe86lKa4b5CSxskGAt2yBkoDyiU=
|
github.com/leaanthony/clir v1.0.4 h1:Dov2y9zWJmZr7CjaCe86lKa4b5CSxskGAt2yBkoDyiU=
|
||||||
github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0=
|
github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0=
|
||||||
github.com/leaanthony/gosod v0.0.4 h1:v4hepo4IyL8E8c9qzDsvYcA0KGh7Npf8As74K5ibQpI=
|
github.com/leaanthony/gosod v0.0.4 h1:v4hepo4IyL8E8c9qzDsvYcA0KGh7Npf8As74K5ibQpI=
|
||||||
@@ -64,17 +60,13 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLD
|
|||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
|
||||||
github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
|
github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
|
||||||
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
|
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/tdewolff/minify v2.3.6+incompatible h1:2hw5/9ZvxhWLvBUnHE06gElGYz+Jv9R4Eys0XUzItYo=
|
github.com/tdewolff/minify v2.3.6+incompatible h1:2hw5/9ZvxhWLvBUnHE06gElGYz+Jv9R4Eys0XUzItYo=
|
||||||
github.com/tdewolff/minify v2.3.6+incompatible/go.mod h1:9Ov578KJUmAWpS6NeZwRZyT56Uf6o3Mcz9CEsg8USYs=
|
github.com/tdewolff/minify v2.3.6+incompatible/go.mod h1:9Ov578KJUmAWpS6NeZwRZyT56Uf6o3Mcz9CEsg8USYs=
|
||||||
@@ -86,6 +78,10 @@ github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
|||||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||||
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
||||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||||
|
github.com/wzshiming/ctc v1.2.3 h1:q+hW3IQNsjIlOFBTGZZZeIXTElFM4grF4spW/errh/c=
|
||||||
|
github.com/wzshiming/ctc v1.2.3/go.mod h1:2tVAtIY7SUyraSk0JxvwmONNPFL4ARavPuEsg5+KA28=
|
||||||
|
github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae h1:tpXvBXC3hpQBDCc9OojJZCQMVRAbT3TTdUMP8WguXkY=
|
||||||
|
github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae/go.mod h1:VTAq37rkGeV+WOybvZwjXiJOicICdpLCN8ifpISjK20=
|
||||||
github.com/xyproto/xpm v1.2.1 h1:trdvGjjWBsOOKzBBUPT6JvaIQM3acJEEYfbxN7M96wg=
|
github.com/xyproto/xpm v1.2.1 h1:trdvGjjWBsOOKzBBUPT6JvaIQM3acJEEYfbxN7M96wg=
|
||||||
github.com/xyproto/xpm v1.2.1/go.mod h1:cMnesLsD0PBXLgjDfTDEaKr8XyTFsnP1QycSqRw7BiY=
|
github.com/xyproto/xpm v1.2.1/go.mod h1:cMnesLsD0PBXLgjDfTDEaKr8XyTFsnP1QycSqRw7BiY=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
@@ -102,33 +98,26 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9 h1:L2auWcuQIvxz9xSEqzESnV/QN/gNRXNApHi3fYwl2w0=
|
|
||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
|
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c h1:UIcGWL6/wpCfyGuJnRFJRurA+yj8RrW7Q6x2YMCXt6c=
|
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c h1:UIcGWL6/wpCfyGuJnRFJRurA+yj8RrW7Q6x2YMCXt6c=
|
||||||
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20200902012652-d1954cc86c82 h1:shxDsb9Dz27xzk3A0DxP0JuJnZMpKrdg8+E14eiUAX4=
|
golang.org/x/tools v0.0.0-20200902012652-d1954cc86c82 h1:shxDsb9Dz27xzk3A0DxP0JuJnZMpKrdg8+E14eiUAX4=
|
||||||
golang.org/x/tools v0.0.0-20200902012652-d1954cc86c82/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
golang.org/x/tools v0.0.0-20200902012652-d1954cc86c82/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"github.com/wailsapp/wails/v2/pkg/logger"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Init initialises the application for a debug environment
|
// Init initialises the application for a debug environment
|
||||||
@@ -19,10 +20,10 @@ func (a *App) Init() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set log levels
|
// Set log levels
|
||||||
greeting := flag.String("loglevel", "debug", "Loglevel to use - Trace, Debug, Info, Warning, Error")
|
loglevel := flag.String("loglevel", "debug", "Loglevel to use - Trace, Debug, Info, Warning, Error")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
if len(*greeting) > 0 {
|
if len(*loglevel) > 0 {
|
||||||
switch strings.ToLower(*greeting) {
|
switch strings.ToLower(*loglevel) {
|
||||||
case "trace":
|
case "trace":
|
||||||
a.logger.SetLogLevel(logger.TRACE)
|
a.logger.SetLogLevel(logger.TRACE)
|
||||||
case "info":
|
case "info":
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// +build !desktop,!hybrid,!server
|
// +build !desktop,!hybrid,!server,!dev
|
||||||
|
|
||||||
package app
|
package app
|
||||||
|
|
||||||
|
|||||||
@@ -231,7 +231,5 @@ func (a *App) Run() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
println("Desktop.Run() finished")
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
260
v2/internal/app/dev.go
Normal file
260
v2/internal/app/dev.go
Normal file
@@ -0,0 +1,260 @@
|
|||||||
|
// +build dev
|
||||||
|
|
||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"flag"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/internal/bridge"
|
||||||
|
"github.com/wailsapp/wails/v2/internal/menumanager"
|
||||||
|
|
||||||
|
clilogger "github.com/wailsapp/wails/v2/pkg/logger"
|
||||||
|
"github.com/wailsapp/wails/v2/pkg/options"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/internal/binding"
|
||||||
|
"github.com/wailsapp/wails/v2/internal/logger"
|
||||||
|
"github.com/wailsapp/wails/v2/internal/messagedispatcher"
|
||||||
|
"github.com/wailsapp/wails/v2/internal/runtime"
|
||||||
|
"github.com/wailsapp/wails/v2/internal/servicebus"
|
||||||
|
"github.com/wailsapp/wails/v2/internal/signal"
|
||||||
|
"github.com/wailsapp/wails/v2/internal/subsystem"
|
||||||
|
)
|
||||||
|
|
||||||
|
// App defines a Wails application structure
|
||||||
|
type App struct {
|
||||||
|
appType string
|
||||||
|
|
||||||
|
servicebus *servicebus.ServiceBus
|
||||||
|
logger *logger.Logger
|
||||||
|
signal *signal.Manager
|
||||||
|
options *options.App
|
||||||
|
|
||||||
|
// Subsystems
|
||||||
|
log *subsystem.Log
|
||||||
|
runtime *subsystem.Runtime
|
||||||
|
event *subsystem.Event
|
||||||
|
//binding *subsystem.Binding
|
||||||
|
call *subsystem.Call
|
||||||
|
menu *subsystem.Menu
|
||||||
|
dispatcher *messagedispatcher.Dispatcher
|
||||||
|
|
||||||
|
menuManager *menumanager.Manager
|
||||||
|
|
||||||
|
// Indicates if the app is in debug mode
|
||||||
|
debug bool
|
||||||
|
|
||||||
|
// This is our binding DB
|
||||||
|
bindings *binding.Bindings
|
||||||
|
|
||||||
|
// Application Stores
|
||||||
|
loglevelStore *runtime.Store
|
||||||
|
appconfigStore *runtime.Store
|
||||||
|
|
||||||
|
// Startup/Shutdown
|
||||||
|
startupCallback func(*runtime.Runtime)
|
||||||
|
shutdownCallback func()
|
||||||
|
|
||||||
|
// Bridge
|
||||||
|
bridge *bridge.Bridge
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create App
|
||||||
|
func CreateApp(appoptions *options.App) (*App, error) {
|
||||||
|
|
||||||
|
// Merge default options
|
||||||
|
options.MergeDefaults(appoptions)
|
||||||
|
|
||||||
|
// Set up logger
|
||||||
|
myLogger := logger.New(appoptions.Logger)
|
||||||
|
|
||||||
|
loglevel := flag.String("loglevel", "debug", "Loglevel to use - Trace, Debug, Info, Warning, Error")
|
||||||
|
flag.Parse()
|
||||||
|
if len(*loglevel) > 0 {
|
||||||
|
switch strings.ToLower(*loglevel) {
|
||||||
|
case "trace":
|
||||||
|
myLogger.SetLogLevel(clilogger.TRACE)
|
||||||
|
case "info":
|
||||||
|
myLogger.SetLogLevel(clilogger.INFO)
|
||||||
|
case "warning":
|
||||||
|
myLogger.SetLogLevel(clilogger.WARNING)
|
||||||
|
case "error":
|
||||||
|
myLogger.SetLogLevel(clilogger.ERROR)
|
||||||
|
default:
|
||||||
|
myLogger.SetLogLevel(appoptions.LogLevel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the menu manager
|
||||||
|
menuManager := menumanager.NewManager()
|
||||||
|
|
||||||
|
// Process the application menu
|
||||||
|
menuManager.SetApplicationMenu(options.GetApplicationMenu(appoptions))
|
||||||
|
|
||||||
|
// Process context menus
|
||||||
|
contextMenus := options.GetContextMenus(appoptions)
|
||||||
|
for _, contextMenu := range contextMenus {
|
||||||
|
menuManager.AddContextMenu(contextMenu)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process tray menus
|
||||||
|
trayMenus := options.GetTrayMenus(appoptions)
|
||||||
|
for _, trayMenu := range trayMenus {
|
||||||
|
menuManager.AddTrayMenu(trayMenu)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create binding exemptions - Ugly hack. There must be a better way
|
||||||
|
bindingExemptions := []interface{}{appoptions.Startup, appoptions.Shutdown}
|
||||||
|
|
||||||
|
result := &App{
|
||||||
|
appType: "dev",
|
||||||
|
bindings: binding.NewBindings(myLogger, appoptions.Bind, bindingExemptions),
|
||||||
|
logger: myLogger,
|
||||||
|
servicebus: servicebus.New(myLogger),
|
||||||
|
startupCallback: appoptions.Startup,
|
||||||
|
shutdownCallback: appoptions.Shutdown,
|
||||||
|
bridge: bridge.NewBridge(myLogger),
|
||||||
|
menuManager: menuManager,
|
||||||
|
}
|
||||||
|
|
||||||
|
result.options = appoptions
|
||||||
|
|
||||||
|
// Initialise the app
|
||||||
|
err := result.Init()
|
||||||
|
|
||||||
|
return result, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the application
|
||||||
|
func (a *App) Run() error {
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// Setup a context
|
||||||
|
var subsystemWaitGroup sync.WaitGroup
|
||||||
|
parentContext := context.WithValue(context.Background(), "waitgroup", &subsystemWaitGroup)
|
||||||
|
ctx, cancel := context.WithCancel(parentContext)
|
||||||
|
|
||||||
|
// Setup signal handler
|
||||||
|
signalsubsystem, err := signal.NewManager(ctx, cancel, a.servicebus, a.logger, a.shutdownCallback)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
a.signal = signalsubsystem
|
||||||
|
a.signal.Start()
|
||||||
|
|
||||||
|
// Start the service bus
|
||||||
|
a.servicebus.Debug()
|
||||||
|
err = a.servicebus.Start()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
runtimesubsystem, err := subsystem.NewRuntime(ctx, a.servicebus, a.logger, a.startupCallback, a.shutdownCallback)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
a.runtime = runtimesubsystem
|
||||||
|
err = a.runtime.Start()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Application Stores
|
||||||
|
a.loglevelStore = a.runtime.GoRuntime().Store.New("wails:loglevel", a.options.LogLevel)
|
||||||
|
a.appconfigStore = a.runtime.GoRuntime().Store.New("wails:appconfig", a.options)
|
||||||
|
|
||||||
|
// Start the logging subsystem
|
||||||
|
log, err := subsystem.NewLog(a.servicebus, a.logger, a.loglevelStore)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
a.log = log
|
||||||
|
err = a.log.Start()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the dispatcher
|
||||||
|
dispatcher, err := messagedispatcher.New(a.servicebus, a.logger)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
a.dispatcher = dispatcher
|
||||||
|
err = dispatcher.Start()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the eventing subsystem
|
||||||
|
eventsubsystem, err := subsystem.NewEvent(ctx, a.servicebus, a.logger)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
a.event = eventsubsystem
|
||||||
|
err = a.event.Start()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the menu subsystem
|
||||||
|
menusubsystem, err := subsystem.NewMenu(ctx, a.servicebus, a.logger, a.menuManager)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
a.menu = menusubsystem
|
||||||
|
err = a.menu.Start()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the call subsystem
|
||||||
|
callSubsystem, err := subsystem.NewCall(ctx, a.servicebus, a.logger, a.bindings.DB(), a.runtime.GoRuntime())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
a.call = callSubsystem
|
||||||
|
err = a.call.Start()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dump bindings as a debug
|
||||||
|
bindingDump, err := a.bindings.ToJSON()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate backend.js
|
||||||
|
a.bindings.GenerateBackendJS()
|
||||||
|
|
||||||
|
err = a.bridge.Run(dispatcher, a.menuManager, bindingDump, a.debug)
|
||||||
|
a.logger.Trace("Bridge.Run() exited")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close down all the subsystems
|
||||||
|
a.logger.Trace("Cancelling subsystems")
|
||||||
|
cancel()
|
||||||
|
subsystemWaitGroup.Wait()
|
||||||
|
|
||||||
|
a.logger.Trace("Cancelling dispatcher")
|
||||||
|
dispatcher.Close()
|
||||||
|
|
||||||
|
// Close log
|
||||||
|
a.logger.Trace("Stopping log")
|
||||||
|
log.Close()
|
||||||
|
|
||||||
|
a.logger.Trace("Stopping Service bus")
|
||||||
|
err = a.servicebus.Stop()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
11
v2/internal/binding/assets/package.json
Normal file
11
v2/internal/binding/assets/package.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"name": "backend",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Package to wrap backend method calls",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC"
|
||||||
|
}
|
||||||
174
v2/internal/binding/generate.go
Normal file
174
v2/internal/binding/generate.go
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
package binding
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
_ "embed"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/internal/fs"
|
||||||
|
|
||||||
|
"github.com/leaanthony/slicer"
|
||||||
|
)
|
||||||
|
|
||||||
|
const _comment = `
|
||||||
|
|
||||||
|
const backend = {
|
||||||
|
main: {
|
||||||
|
"xbarApp": {
|
||||||
|
"GetCategories": () => {
|
||||||
|
window.backend.main.xbarApp.GetCategories.call(arguments);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} arg1
|
||||||
|
*/
|
||||||
|
"InstallPlugin": (arg1) => {
|
||||||
|
window.backend.main.xbarApp.InstallPlugin.call(arguments);
|
||||||
|
},
|
||||||
|
"GetPlugins": () => {
|
||||||
|
window.backend.main.xbarApp.GetPlugins.call(arguments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default backend;`
|
||||||
|
|
||||||
|
//go:embed assets/package.json
|
||||||
|
var packageJSON []byte
|
||||||
|
|
||||||
|
func (b *Bindings) GenerateBackendJS() {
|
||||||
|
|
||||||
|
store := b.db.store
|
||||||
|
var output bytes.Buffer
|
||||||
|
|
||||||
|
output.WriteString(`// @ts-check
|
||||||
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Ă‚ MODIWL
|
||||||
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
const backend = {`)
|
||||||
|
output.WriteString("\n")
|
||||||
|
|
||||||
|
var sortedPackageNames slicer.StringSlicer
|
||||||
|
for packageName := range store {
|
||||||
|
sortedPackageNames.Add(packageName)
|
||||||
|
}
|
||||||
|
sortedPackageNames.Sort()
|
||||||
|
sortedPackageNames.Each(func(packageName string) {
|
||||||
|
packages := store[packageName]
|
||||||
|
output.WriteString(fmt.Sprintf(" \"%s\": {", packageName))
|
||||||
|
output.WriteString("\n")
|
||||||
|
var sortedStructNames slicer.StringSlicer
|
||||||
|
for structName := range packages {
|
||||||
|
sortedStructNames.Add(structName)
|
||||||
|
}
|
||||||
|
sortedStructNames.Sort()
|
||||||
|
|
||||||
|
sortedStructNames.Each(func(structName string) {
|
||||||
|
structs := packages[structName]
|
||||||
|
output.WriteString(fmt.Sprintf(" \"%s\": {", structName))
|
||||||
|
output.WriteString("\n")
|
||||||
|
|
||||||
|
var sortedMethodNames slicer.StringSlicer
|
||||||
|
for methodName := range structs {
|
||||||
|
sortedMethodNames.Add(methodName)
|
||||||
|
}
|
||||||
|
sortedMethodNames.Sort()
|
||||||
|
|
||||||
|
sortedMethodNames.Each(func(methodName string) {
|
||||||
|
methodDetails := structs[methodName]
|
||||||
|
output.WriteString(" /**\n")
|
||||||
|
output.WriteString(" * " + methodName + "\n")
|
||||||
|
var args slicer.StringSlicer
|
||||||
|
for count, input := range methodDetails.Inputs {
|
||||||
|
arg := fmt.Sprintf("arg%d", count+1)
|
||||||
|
args.Add(arg)
|
||||||
|
output.WriteString(fmt.Sprintf(" * @param {%s} %s - Go Type: %s\n", goTypeToJSDocType(input.TypeName), arg, input.TypeName))
|
||||||
|
}
|
||||||
|
returnType := "Promise"
|
||||||
|
returnTypeDetails := ""
|
||||||
|
if methodDetails.OutputCount() > 0 {
|
||||||
|
firstType := goTypeToJSDocType(methodDetails.Outputs[0].TypeName)
|
||||||
|
returnType += "<" + firstType
|
||||||
|
if methodDetails.OutputCount() == 2 {
|
||||||
|
secondType := goTypeToJSDocType(methodDetails.Outputs[1].TypeName)
|
||||||
|
returnType += "|" + secondType
|
||||||
|
}
|
||||||
|
returnType += ">"
|
||||||
|
returnTypeDetails = " - Go Type: " + methodDetails.Outputs[0].TypeName
|
||||||
|
}
|
||||||
|
output.WriteString(" * @returns {" + returnType + "} " + returnTypeDetails + "\n")
|
||||||
|
output.WriteString(" */\n")
|
||||||
|
argsString := args.Join(", ")
|
||||||
|
output.WriteString(fmt.Sprintf(" \"%s\": (%s) => {", methodName, argsString))
|
||||||
|
output.WriteString("\n")
|
||||||
|
output.WriteString(fmt.Sprintf(" return window.backend.%s.%s.%s(%s);", packageName, structName, methodName, argsString))
|
||||||
|
output.WriteString("\n")
|
||||||
|
output.WriteString(fmt.Sprintf(" },"))
|
||||||
|
output.WriteString("\n")
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
output.WriteString(fmt.Sprintf(" }"))
|
||||||
|
output.WriteString("\n")
|
||||||
|
})
|
||||||
|
|
||||||
|
output.WriteString(fmt.Sprintf(" }\n"))
|
||||||
|
output.WriteString("\n")
|
||||||
|
})
|
||||||
|
|
||||||
|
output.WriteString(`};
|
||||||
|
export default backend;`)
|
||||||
|
output.WriteString("\n")
|
||||||
|
|
||||||
|
dirname, err := fs.RelativeToCwd("frontend/src/backend")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !fs.DirExists(dirname) {
|
||||||
|
err := fs.Mkdir(dirname)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
packageJsonFile := filepath.Join(dirname, "package.json")
|
||||||
|
if !fs.FileExists(packageJsonFile) {
|
||||||
|
err := os.WriteFile(packageJsonFile, packageJSON, 0755)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
filename := filepath.Join(dirname, "index.js")
|
||||||
|
err = os.WriteFile(filename, output.Bytes(), 0755)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func goTypeToJSDocType(input string) string {
|
||||||
|
switch true {
|
||||||
|
case input == "string":
|
||||||
|
return "string"
|
||||||
|
case input == "error":
|
||||||
|
return "Error"
|
||||||
|
case
|
||||||
|
strings.HasPrefix(input, "int"),
|
||||||
|
strings.HasPrefix(input, "uint"),
|
||||||
|
strings.HasPrefix(input, "float"):
|
||||||
|
return "number"
|
||||||
|
case input == "bool":
|
||||||
|
return "boolean"
|
||||||
|
case strings.HasPrefix(input, "[]"):
|
||||||
|
arrayType := goTypeToJSDocType(input[2:])
|
||||||
|
return "Array.<" + arrayType + ">"
|
||||||
|
default:
|
||||||
|
return "any"
|
||||||
|
}
|
||||||
|
}
|
||||||
113
v2/internal/bridge/bridge.go
Normal file
113
v2/internal/bridge/bridge.go
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
package bridge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/internal/menumanager"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/internal/messagedispatcher"
|
||||||
|
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
"github.com/wailsapp/wails/v2/internal/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Bridge struct {
|
||||||
|
upgrader websocket.Upgrader
|
||||||
|
server *http.Server
|
||||||
|
myLogger *logger.Logger
|
||||||
|
|
||||||
|
bindings string
|
||||||
|
dispatcher *messagedispatcher.Dispatcher
|
||||||
|
|
||||||
|
mu sync.Mutex
|
||||||
|
sessions map[string]*session
|
||||||
|
|
||||||
|
ctx context.Context
|
||||||
|
cancel context.CancelFunc
|
||||||
|
|
||||||
|
// Dialog client
|
||||||
|
dialog *messagedispatcher.DispatchClient
|
||||||
|
|
||||||
|
// Menus
|
||||||
|
menumanager *menumanager.Manager
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBridge(myLogger *logger.Logger) *Bridge {
|
||||||
|
result := &Bridge{
|
||||||
|
myLogger: myLogger,
|
||||||
|
upgrader: websocket.Upgrader{CheckOrigin: func(r *http.Request) bool { return true }},
|
||||||
|
sessions: make(map[string]*session),
|
||||||
|
}
|
||||||
|
|
||||||
|
myLogger.SetLogLevel(1)
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
result.ctx = ctx
|
||||||
|
result.cancel = cancel
|
||||||
|
result.server = &http.Server{Addr: ":34115"}
|
||||||
|
http.HandleFunc("/bridge", result.wsBridgeHandler)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bridge) Run(dispatcher *messagedispatcher.Dispatcher, menumanager *menumanager.Manager, bindings string, debug bool) error {
|
||||||
|
|
||||||
|
// Ensure we cancel the context when we shutdown
|
||||||
|
defer b.cancel()
|
||||||
|
|
||||||
|
b.bindings = bindings
|
||||||
|
b.dispatcher = dispatcher
|
||||||
|
b.menumanager = menumanager
|
||||||
|
|
||||||
|
// Setup dialog handler
|
||||||
|
dialogClient := NewDialogClient(b.myLogger)
|
||||||
|
b.dialog = dispatcher.RegisterClient(dialogClient)
|
||||||
|
dialogClient.dispatcher = b.dialog
|
||||||
|
|
||||||
|
b.myLogger.Info("Bridge mode started.")
|
||||||
|
|
||||||
|
err := b.server.ListenAndServe()
|
||||||
|
if err != nil && err != http.ErrServerClosed {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bridge) wsBridgeHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
c, err := b.upgrader.Upgrade(w, r, nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Print("upgrade:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Could not open websocket connection", http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
b.myLogger.Info("Connection from frontend accepted [%s].", c.RemoteAddr().String())
|
||||||
|
b.startSession(c)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bridge) startSession(conn *websocket.Conn) {
|
||||||
|
|
||||||
|
// Create a new session for this connection
|
||||||
|
s := newSession(conn, b.menumanager, b.bindings, b.dispatcher, b.myLogger, b.ctx)
|
||||||
|
|
||||||
|
// Setup the close handler
|
||||||
|
conn.SetCloseHandler(func(int, string) error {
|
||||||
|
b.myLogger.Info("Connection dropped [%s].", s.Identifier())
|
||||||
|
b.dispatcher.RemoveClient(s.client)
|
||||||
|
b.mu.Lock()
|
||||||
|
delete(b.sessions, s.Identifier())
|
||||||
|
b.mu.Unlock()
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
b.mu.Lock()
|
||||||
|
go s.start(len(b.sessions) == 0)
|
||||||
|
b.sessions[s.Identifier()] = s
|
||||||
|
b.mu.Unlock()
|
||||||
|
}
|
||||||
130
v2/internal/bridge/client.go
Normal file
130
v2/internal/bridge/client.go
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
package bridge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/wailsapp/wails/v2/pkg/options/dialog"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BridgeClient struct {
|
||||||
|
session *session
|
||||||
|
|
||||||
|
// Tray menu cache to send to reconnecting clients
|
||||||
|
messageCache chan string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBridgeClient() *BridgeClient {
|
||||||
|
return &BridgeClient{
|
||||||
|
messageCache: make(chan string, 100),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) Quit() {
|
||||||
|
b.session.log.Info("Quit unsupported in Bridge mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) NotifyEvent(message string) {
|
||||||
|
//b.session.sendMessage("n" + message)
|
||||||
|
b.session.log.Info("NotifyEvent: %s", message)
|
||||||
|
b.session.log.Info("NotifyEvent unsupported in Bridge mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) CallResult(message string) {
|
||||||
|
b.session.sendMessage("c" + message)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) OpenDialog(dialogOptions *dialog.OpenDialog, callbackID string) {
|
||||||
|
// Handled by dialog_client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) SaveDialog(dialogOptions *dialog.SaveDialog, callbackID string) {
|
||||||
|
// Handled by dialog_client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) MessageDialog(dialogOptions *dialog.MessageDialog, callbackID string) {
|
||||||
|
// Handled by dialog_client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) WindowSetTitle(title string) {
|
||||||
|
b.session.log.Info("WindowSetTitle unsupported in Bridge mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) WindowShow() {
|
||||||
|
b.session.log.Info("WindowShow unsupported in Bridge mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) WindowHide() {
|
||||||
|
b.session.log.Info("WindowHide unsupported in Bridge mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) WindowCenter() {
|
||||||
|
b.session.log.Info("WindowCenter unsupported in Bridge mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) WindowMaximise() {
|
||||||
|
b.session.log.Info("WindowMaximise unsupported in Bridge mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) WindowUnmaximise() {
|
||||||
|
b.session.log.Info("WindowUnmaximise unsupported in Bridge mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) WindowMinimise() {
|
||||||
|
b.session.log.Info("WindowMinimise unsupported in Bridge mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) WindowUnminimise() {
|
||||||
|
b.session.log.Info("WindowUnminimise unsupported in Bridge mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) WindowPosition(x int, y int) {
|
||||||
|
b.session.log.Info("WindowPosition unsupported in Bridge mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) WindowSize(width int, height int) {
|
||||||
|
b.session.log.Info("WindowSize unsupported in Bridge mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) WindowSetMinSize(width int, height int) {
|
||||||
|
b.session.log.Info("WindowSetMinSize unsupported in Bridge mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) WindowSetMaxSize(width int, height int) {
|
||||||
|
b.session.log.Info("WindowSetMaxSize unsupported in Bridge mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) WindowFullscreen() {
|
||||||
|
b.session.log.Info("WindowFullscreen unsupported in Bridge mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) WindowUnFullscreen() {
|
||||||
|
b.session.log.Info("WindowUnFullscreen unsupported in Bridge mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) WindowSetColour(colour int) {
|
||||||
|
b.session.log.Info("WindowSetColour unsupported in Bridge mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) DarkModeEnabled(callbackID string) {
|
||||||
|
b.session.log.Info("DarkModeEnabled unsupported in Bridge mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) SetApplicationMenu(menuJSON string) {
|
||||||
|
b.session.log.Info("SetApplicationMenu unsupported in Bridge mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) SetTrayMenu(trayMenuJSON string) {
|
||||||
|
b.session.sendMessage("TS" + trayMenuJSON)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) UpdateTrayMenuLabel(trayMenuJSON string) {
|
||||||
|
b.session.sendMessage("TU" + trayMenuJSON)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BridgeClient) UpdateContextMenu(contextMenuJSON string) {
|
||||||
|
b.session.log.Info("UpdateContextMenu unsupported in Bridge mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBridgeClient(session *session) *BridgeClient {
|
||||||
|
return &BridgeClient{
|
||||||
|
session: session,
|
||||||
|
}
|
||||||
|
}
|
||||||
1
v2/internal/bridge/darwin.js
Normal file
1
v2/internal/bridge/darwin.js
Normal file
File diff suppressed because one or more lines are too long
141
v2/internal/bridge/dialog_client.go
Normal file
141
v2/internal/bridge/dialog_client.go
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
package bridge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/internal/messagedispatcher"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/internal/logger"
|
||||||
|
|
||||||
|
"github.com/leaanthony/slicer"
|
||||||
|
"github.com/wailsapp/wails/v2/pkg/options/dialog"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DialogClient struct {
|
||||||
|
dispatcher *messagedispatcher.DispatchClient
|
||||||
|
log *logger.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDialogClient(log *logger.Logger) *DialogClient {
|
||||||
|
return &DialogClient{
|
||||||
|
log: log,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) Quit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) NotifyEvent(message string) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) CallResult(message string) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) OpenDialog(dialogOptions *dialog.OpenDialog, callbackID string) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) SaveDialog(dialogOptions *dialog.SaveDialog, callbackID string) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) MessageDialog(dialogOptions *dialog.MessageDialog, callbackID string) {
|
||||||
|
|
||||||
|
osa, err := exec.LookPath("osascript")
|
||||||
|
if err != nil {
|
||||||
|
d.log.Info("MessageDialog unavailable (osascript not found)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var btns slicer.StringSlicer
|
||||||
|
defaultButton := ""
|
||||||
|
cancelButton := ""
|
||||||
|
for index, btn := range dialogOptions.Buttons {
|
||||||
|
btns.Add(strconv.Quote(btn))
|
||||||
|
if btn == dialogOptions.DefaultButton {
|
||||||
|
defaultButton = fmt.Sprintf("default button %d", index+1)
|
||||||
|
}
|
||||||
|
if btn == dialogOptions.CancelButton {
|
||||||
|
cancelButton = fmt.Sprintf("cancel button %d", index+1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buttons := "{" + btns.Join(",") + "}"
|
||||||
|
script := fmt.Sprintf("display dialog \"%s\" buttons %s %s %s with title \"%s\"", dialogOptions.Message, buttons, defaultButton, cancelButton, dialogOptions.Title)
|
||||||
|
go func() {
|
||||||
|
out, err := exec.Command(osa, "-e", script).Output()
|
||||||
|
if err != nil {
|
||||||
|
// Assume user has pressed cancel button
|
||||||
|
if dialogOptions.CancelButton != "" {
|
||||||
|
d.dispatcher.DispatchMessage("DM" + callbackID + "|" + dialogOptions.CancelButton)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
d.log.Error("Dialog had bad exit code. If this was a Cancel button, add 'CancelButton' to the dialog.MessageDialog struct. Error: %s", err.Error())
|
||||||
|
d.dispatcher.DispatchMessage("DM" + callbackID + "|error - check logs")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonPressed := strings.TrimSpace(strings.TrimPrefix(string(out), "button returned:"))
|
||||||
|
d.dispatcher.DispatchMessage("DM" + callbackID + "|" + buttonPressed)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) WindowSetTitle(title string) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) WindowShow() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) WindowHide() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) WindowCenter() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) WindowMaximise() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) WindowUnmaximise() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) WindowMinimise() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) WindowUnminimise() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) WindowPosition(x int, y int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) WindowSize(width int, height int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) WindowSetMinSize(width int, height int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) WindowSetMaxSize(width int, height int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) WindowFullscreen() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) WindowUnFullscreen() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) WindowSetColour(colour int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) DarkModeEnabled(callbackID string) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) SetApplicationMenu(menuJSON string) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) SetTrayMenu(trayMenuJSON string) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) UpdateTrayMenuLabel(trayMenuJSON string) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialogClient) UpdateContextMenu(contextMenuJSON string) {
|
||||||
|
}
|
||||||
162
v2/internal/bridge/session.go
Normal file
162
v2/internal/bridge/session.go
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
package bridge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
_ "embed"
|
||||||
|
"log"
|
||||||
|
"runtime"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/internal/menumanager"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/internal/messagedispatcher"
|
||||||
|
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
"github.com/wailsapp/wails/v2/internal/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed darwin.js
|
||||||
|
var darwinRuntime string
|
||||||
|
|
||||||
|
// session represents a single websocket session
|
||||||
|
type session struct {
|
||||||
|
bindings string
|
||||||
|
conn *websocket.Conn
|
||||||
|
//eventManager interfaces.EventManager
|
||||||
|
log *logger.Logger
|
||||||
|
//ipc interfaces.IPCManager
|
||||||
|
|
||||||
|
// Mutex for writing to the socket
|
||||||
|
shutdown chan bool
|
||||||
|
writeChan chan []byte
|
||||||
|
|
||||||
|
done bool
|
||||||
|
|
||||||
|
// context
|
||||||
|
ctx context.Context
|
||||||
|
|
||||||
|
// client
|
||||||
|
client *messagedispatcher.DispatchClient
|
||||||
|
|
||||||
|
// Menus
|
||||||
|
menumanager *menumanager.Manager
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSession(conn *websocket.Conn, menumanager *menumanager.Manager, bindings string, dispatcher *messagedispatcher.Dispatcher, logger *logger.Logger, ctx context.Context) *session {
|
||||||
|
result := &session{
|
||||||
|
conn: conn,
|
||||||
|
bindings: bindings,
|
||||||
|
log: logger,
|
||||||
|
shutdown: make(chan bool),
|
||||||
|
writeChan: make(chan []byte, 100),
|
||||||
|
ctx: ctx,
|
||||||
|
menumanager: menumanager,
|
||||||
|
}
|
||||||
|
|
||||||
|
result.client = dispatcher.RegisterClient(newBridgeClient(result))
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identifier returns a string identifier for the remote connection.
|
||||||
|
// Taking the form of the client's <ip address>:<port>.
|
||||||
|
func (s *session) Identifier() string {
|
||||||
|
if s.conn != nil {
|
||||||
|
return s.conn.RemoteAddr().String()
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *session) sendMessage(msg string) error {
|
||||||
|
if !s.done {
|
||||||
|
s.writeChan <- []byte(msg)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *session) start(firstSession bool) {
|
||||||
|
s.log.SetLogLevel(1)
|
||||||
|
s.log.Info("Connected to frontend.")
|
||||||
|
go s.writePump()
|
||||||
|
|
||||||
|
var wailsRuntime string
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin":
|
||||||
|
wailsRuntime = darwinRuntime
|
||||||
|
default:
|
||||||
|
log.Fatal("platform not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
bindingsMessage := "window.wailsbindings = `" + s.bindings + "`;"
|
||||||
|
s.log.Info(bindingsMessage)
|
||||||
|
bootstrapMessage := bindingsMessage + wailsRuntime
|
||||||
|
|
||||||
|
s.sendMessage("b" + bootstrapMessage)
|
||||||
|
|
||||||
|
// Send menus
|
||||||
|
traymenus, err := s.menumanager.GetTrayMenus()
|
||||||
|
if err != nil {
|
||||||
|
s.log.Error(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, trayMenu := range traymenus {
|
||||||
|
s.sendMessage("TS" + trayMenu)
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
messageType, buffer, err := s.conn.ReadMessage()
|
||||||
|
if messageType == -1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
s.log.Error("Error reading message: %v", err)
|
||||||
|
err = s.conn.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
message := string(buffer)
|
||||||
|
|
||||||
|
s.log.Debug("Got message: %#v\n", message)
|
||||||
|
|
||||||
|
// Dispatch message as normal
|
||||||
|
s.client.DispatchMessage(message)
|
||||||
|
|
||||||
|
if s.done {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shutdown
|
||||||
|
func (s *session) Shutdown() {
|
||||||
|
s.conn.Close()
|
||||||
|
s.done = true
|
||||||
|
s.log.Info("session %v exit", s.Identifier())
|
||||||
|
}
|
||||||
|
|
||||||
|
// writePump pulls messages from the writeChan and sends them to the client
|
||||||
|
// since it uses a channel to read the messages the socket is protected without locks
|
||||||
|
func (s *session) writePump() {
|
||||||
|
s.log.Debug("Session %v - writePump start", s.Identifier())
|
||||||
|
defer s.log.Debug("Session %v - writePump shutdown", s.Identifier())
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-s.ctx.Done():
|
||||||
|
s.Shutdown()
|
||||||
|
return
|
||||||
|
case msg, ok := <-s.writeChan:
|
||||||
|
s.conn.SetWriteDeadline(time.Now().Add(1 * time.Second))
|
||||||
|
if !ok {
|
||||||
|
s.log.Debug("writeChan was closed!")
|
||||||
|
s.conn.WriteMessage(websocket.CloseMessage, []byte{})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.conn.WriteMessage(websocket.TextMessage, msg); err != nil {
|
||||||
|
s.log.Debug(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
89
v2/internal/colour/colour.go
Normal file
89
v2/internal/colour/colour.go
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
package colour
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/wzshiming/ctc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Col(col ctc.Color, text string) string {
|
||||||
|
return fmt.Sprintf("%s%s%s", col, text, ctc.Reset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Yellow(text string) string {
|
||||||
|
return Col(ctc.ForegroundBrightYellow, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Red(text string) string {
|
||||||
|
return Col(ctc.ForegroundBrightRed, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Blue(text string) string {
|
||||||
|
return Col(ctc.ForegroundBrightBlue, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Green(text string) string {
|
||||||
|
return Col(ctc.ForegroundBrightGreen, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Cyan(text string) string {
|
||||||
|
return Col(ctc.ForegroundBrightCyan, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Magenta(text string) string {
|
||||||
|
return Col(ctc.ForegroundBrightMagenta, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func White(text string) string {
|
||||||
|
return Col(ctc.ForegroundBrightWhite, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Black(text string) string {
|
||||||
|
return Col(ctc.ForegroundBrightBlack, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DarkYellow(text string) string {
|
||||||
|
return Col(ctc.ForegroundYellow, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DarkRed(text string) string {
|
||||||
|
return Col(ctc.ForegroundRed, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DarkBlue(text string) string {
|
||||||
|
return Col(ctc.ForegroundBlue, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DarkGreen(text string) string {
|
||||||
|
return Col(ctc.ForegroundGreen, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DarkCyan(text string) string {
|
||||||
|
return Col(ctc.ForegroundCyan, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DarkMagenta(text string) string {
|
||||||
|
return Col(ctc.ForegroundMagenta, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DarkWhite(text string) string {
|
||||||
|
return Col(ctc.ForegroundWhite, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DarkBlack(text string) string {
|
||||||
|
return Col(ctc.ForegroundBlack, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
var rainbowCols = []func(string) string{Red, Yellow, Green, Cyan, Blue, Magenta}
|
||||||
|
|
||||||
|
func Rainbow(text string) string {
|
||||||
|
var builder strings.Builder
|
||||||
|
|
||||||
|
for i := 0; i < len(text); i++ {
|
||||||
|
fn := rainbowCols[i%len(rainbowCols)]
|
||||||
|
builder.WriteString(fn(text[i : i+1]))
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.String()
|
||||||
|
}
|
||||||
@@ -169,7 +169,6 @@ func (a *Application) Run(incomingDispatcher Dispatcher, bindings string, debug
|
|||||||
// Yes - Save memory reference and run app, cleaning up afterwards
|
// Yes - Save memory reference and run app, cleaning up afterwards
|
||||||
a.saveMemoryReference(unsafe.Pointer(app))
|
a.saveMemoryReference(unsafe.Pointer(app))
|
||||||
C.Run(app, 0, nil)
|
C.Run(app, 0, nil)
|
||||||
println("Back in ffenestri.go")
|
|
||||||
} else {
|
} else {
|
||||||
// Oh no! We couldn't initialise the application
|
// Oh no! We couldn't initialise the application
|
||||||
a.logger.Fatal("Cannot initialise Application.")
|
a.logger.Fatal("Cannot initialise Application.")
|
||||||
|
|||||||
@@ -785,7 +785,7 @@ extern void MessageDialog(struct Application *app, char *callbackID, char *type,
|
|||||||
buttonPressed = button4;
|
buttonPressed = button4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct callback message. Format "DS<callbackID>|<selected button index>"
|
// Construct callback message. Format "DM<callbackID>|<selected button index>"
|
||||||
const char *callback = concat("DM", callbackID);
|
const char *callback = concat("DM", callbackID);
|
||||||
const char *header = concat(callback, "|");
|
const char *header = concat(callback, "|");
|
||||||
const char *responseMessage = concat(header, buttonPressed);
|
const char *responseMessage = concat(header, buttonPressed);
|
||||||
|
|||||||
@@ -180,151 +180,151 @@ id processAcceleratorKey(const char *key) {
|
|||||||
return str("");
|
return str("");
|
||||||
}
|
}
|
||||||
|
|
||||||
if( STREQ(key, "Backspace") ) {
|
if( STREQ(key, "backspace") ) {
|
||||||
return strunicode(0x0008);
|
return strunicode(0x0008);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "Tab") ) {
|
if( STREQ(key, "tab") ) {
|
||||||
return strunicode(0x0009);
|
return strunicode(0x0009);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "Return") ) {
|
if( STREQ(key, "return") ) {
|
||||||
return strunicode(0x000d);
|
return strunicode(0x000d);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "Escape") ) {
|
if( STREQ(key, "escape") ) {
|
||||||
return strunicode(0x001b);
|
return strunicode(0x001b);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "Left") ) {
|
if( STREQ(key, "left") ) {
|
||||||
return strunicode(0x001c);
|
return strunicode(0x001c);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "Right") ) {
|
if( STREQ(key, "right") ) {
|
||||||
return strunicode(0x001d);
|
return strunicode(0x001d);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "Up") ) {
|
if( STREQ(key, "up") ) {
|
||||||
return strunicode(0x001e);
|
return strunicode(0x001e);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "Down") ) {
|
if( STREQ(key, "down") ) {
|
||||||
return strunicode(0x001f);
|
return strunicode(0x001f);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "Space") ) {
|
if( STREQ(key, "space") ) {
|
||||||
return strunicode(0x0020);
|
return strunicode(0x0020);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "Delete") ) {
|
if( STREQ(key, "delete") ) {
|
||||||
return strunicode(0x007f);
|
return strunicode(0x007f);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "Home") ) {
|
if( STREQ(key, "home") ) {
|
||||||
return strunicode(0x2196);
|
return strunicode(0x2196);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "End") ) {
|
if( STREQ(key, "end") ) {
|
||||||
return strunicode(0x2198);
|
return strunicode(0x2198);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "Page Up") ) {
|
if( STREQ(key, "page up") ) {
|
||||||
return strunicode(0x21de);
|
return strunicode(0x21de);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "Page Down") ) {
|
if( STREQ(key, "page down") ) {
|
||||||
return strunicode(0x21df);
|
return strunicode(0x21df);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F1") ) {
|
if( STREQ(key, "f1") ) {
|
||||||
return strunicode(0xf704);
|
return strunicode(0xf704);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F2") ) {
|
if( STREQ(key, "f2") ) {
|
||||||
return strunicode(0xf705);
|
return strunicode(0xf705);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F3") ) {
|
if( STREQ(key, "f3") ) {
|
||||||
return strunicode(0xf706);
|
return strunicode(0xf706);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F4") ) {
|
if( STREQ(key, "f4") ) {
|
||||||
return strunicode(0xf707);
|
return strunicode(0xf707);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F5") ) {
|
if( STREQ(key, "f5") ) {
|
||||||
return strunicode(0xf708);
|
return strunicode(0xf708);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F6") ) {
|
if( STREQ(key, "f6") ) {
|
||||||
return strunicode(0xf709);
|
return strunicode(0xf709);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F7") ) {
|
if( STREQ(key, "f7") ) {
|
||||||
return strunicode(0xf70a);
|
return strunicode(0xf70a);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F8") ) {
|
if( STREQ(key, "f8") ) {
|
||||||
return strunicode(0xf70b);
|
return strunicode(0xf70b);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F9") ) {
|
if( STREQ(key, "f9") ) {
|
||||||
return strunicode(0xf70c);
|
return strunicode(0xf70c);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F10") ) {
|
if( STREQ(key, "f10") ) {
|
||||||
return strunicode(0xf70d);
|
return strunicode(0xf70d);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F11") ) {
|
if( STREQ(key, "f11") ) {
|
||||||
return strunicode(0xf70e);
|
return strunicode(0xf70e);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F12") ) {
|
if( STREQ(key, "f12") ) {
|
||||||
return strunicode(0xf70f);
|
return strunicode(0xf70f);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F13") ) {
|
if( STREQ(key, "f13") ) {
|
||||||
return strunicode(0xf710);
|
return strunicode(0xf710);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F14") ) {
|
if( STREQ(key, "f14") ) {
|
||||||
return strunicode(0xf711);
|
return strunicode(0xf711);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F15") ) {
|
if( STREQ(key, "f15") ) {
|
||||||
return strunicode(0xf712);
|
return strunicode(0xf712);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F16") ) {
|
if( STREQ(key, "f16") ) {
|
||||||
return strunicode(0xf713);
|
return strunicode(0xf713);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F17") ) {
|
if( STREQ(key, "f17") ) {
|
||||||
return strunicode(0xf714);
|
return strunicode(0xf714);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F18") ) {
|
if( STREQ(key, "f18") ) {
|
||||||
return strunicode(0xf715);
|
return strunicode(0xf715);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F19") ) {
|
if( STREQ(key, "f19") ) {
|
||||||
return strunicode(0xf716);
|
return strunicode(0xf716);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F20") ) {
|
if( STREQ(key, "f20") ) {
|
||||||
return strunicode(0xf717);
|
return strunicode(0xf717);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F21") ) {
|
if( STREQ(key, "f21") ) {
|
||||||
return strunicode(0xf718);
|
return strunicode(0xf718);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F22") ) {
|
if( STREQ(key, "f22") ) {
|
||||||
return strunicode(0xf719);
|
return strunicode(0xf719);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F23") ) {
|
if( STREQ(key, "f23") ) {
|
||||||
return strunicode(0xf71a);
|
return strunicode(0xf71a);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F24") ) {
|
if( STREQ(key, "f24") ) {
|
||||||
return strunicode(0xf71b);
|
return strunicode(0xf71b);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F25") ) {
|
if( STREQ(key, "f25") ) {
|
||||||
return strunicode(0xf71c);
|
return strunicode(0xf71c);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F26") ) {
|
if( STREQ(key, "f26") ) {
|
||||||
return strunicode(0xf71d);
|
return strunicode(0xf71d);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F27") ) {
|
if( STREQ(key, "f27") ) {
|
||||||
return strunicode(0xf71e);
|
return strunicode(0xf71e);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F28") ) {
|
if( STREQ(key, "f28") ) {
|
||||||
return strunicode(0xf71f);
|
return strunicode(0xf71f);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F29") ) {
|
if( STREQ(key, "f29") ) {
|
||||||
return strunicode(0xf720);
|
return strunicode(0xf720);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F30") ) {
|
if( STREQ(key, "f30") ) {
|
||||||
return strunicode(0xf721);
|
return strunicode(0xf721);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F31") ) {
|
if( STREQ(key, "f31") ) {
|
||||||
return strunicode(0xf722);
|
return strunicode(0xf722);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F32") ) {
|
if( STREQ(key, "f32") ) {
|
||||||
return strunicode(0xf723);
|
return strunicode(0xf723);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F33") ) {
|
if( STREQ(key, "f33") ) {
|
||||||
return strunicode(0xf724);
|
return strunicode(0xf724);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F34") ) {
|
if( STREQ(key, "f34") ) {
|
||||||
return strunicode(0xf725);
|
return strunicode(0xf725);
|
||||||
}
|
}
|
||||||
if( STREQ(key, "F35") ) {
|
if( STREQ(key, "f35") ) {
|
||||||
return strunicode(0xf726);
|
return strunicode(0xf726);
|
||||||
}
|
}
|
||||||
// if( STREQ(key, "Insert") ) {
|
// if( STREQ(key, "Insert") ) {
|
||||||
@@ -336,7 +336,7 @@ id processAcceleratorKey(const char *key) {
|
|||||||
// if( STREQ(key, "ScrollLock") ) {
|
// if( STREQ(key, "ScrollLock") ) {
|
||||||
// return strunicode(0xf72f);
|
// return strunicode(0xf72f);
|
||||||
// }
|
// }
|
||||||
if( STREQ(key, "NumLock") ) {
|
if( STREQ(key, "numLock") ) {
|
||||||
return strunicode(0xf739);
|
return strunicode(0xf739);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,19 +509,19 @@ unsigned long parseModifiers(const char **modifiers) {
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
while( thisModifier != NULL ) {
|
while( thisModifier != NULL ) {
|
||||||
// Determine flags
|
// Determine flags
|
||||||
if( STREQ(thisModifier, "CmdOrCtrl") ) {
|
if( STREQ(thisModifier, "cmdorctrl") ) {
|
||||||
result |= NSEventModifierFlagCommand;
|
result |= NSEventModifierFlagCommand;
|
||||||
}
|
}
|
||||||
if( STREQ(thisModifier, "OptionOrAlt") ) {
|
if( STREQ(thisModifier, "optionoralt") ) {
|
||||||
result |= NSEventModifierFlagOption;
|
result |= NSEventModifierFlagOption;
|
||||||
}
|
}
|
||||||
if( STREQ(thisModifier, "Shift") ) {
|
if( STREQ(thisModifier, "shift") ) {
|
||||||
result |= NSEventModifierFlagShift;
|
result |= NSEventModifierFlagShift;
|
||||||
}
|
}
|
||||||
if( STREQ(thisModifier, "Super") ) {
|
if( STREQ(thisModifier, "super") ) {
|
||||||
result |= NSEventModifierFlagCommand;
|
result |= NSEventModifierFlagCommand;
|
||||||
}
|
}
|
||||||
if( STREQ(thisModifier, "Control") ) {
|
if( STREQ(thisModifier, "control") ) {
|
||||||
result |= NSEventModifierFlagControl;
|
result |= NSEventModifierFlagControl;
|
||||||
}
|
}
|
||||||
count++;
|
count++;
|
||||||
@@ -575,7 +575,7 @@ id processCheckboxMenuItem(Menu *menu, id parentmenu, const char *title, const c
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
id processTextMenuItem(Menu *menu, id parentMenu, const char *title, const char *menuid, bool disabled, const char *acceleratorkey, const char **modifiers, const char* tooltip, const char* image, const char* fontName, int fontSize, const char* RGBA) {
|
id processTextMenuItem(Menu *menu, id parentMenu, const char *title, const char *menuid, bool disabled, const char *acceleratorkey, const char **modifiers, const char* tooltip, const char* image, const char* fontName, int fontSize, const char* RGBA, bool templateImage) {
|
||||||
id item = ALLOC("NSMenuItem");
|
id item = ALLOC("NSMenuItem");
|
||||||
|
|
||||||
// Create a MenuItemCallbackData
|
// Create a MenuItemCallbackData
|
||||||
@@ -598,6 +598,9 @@ id processTextMenuItem(Menu *menu, id parentMenu, const char *title, const char
|
|||||||
id imageData = msg(data, s("initWithBase64EncodedString:options:"), str(image), 0);
|
id imageData = msg(data, s("initWithBase64EncodedString:options:"), str(image), 0);
|
||||||
id nsimage = ALLOC("NSImage");
|
id nsimage = ALLOC("NSImage");
|
||||||
msg(nsimage, s("initWithData:"), imageData);
|
msg(nsimage, s("initWithData:"), imageData);
|
||||||
|
if( templateImage ) {
|
||||||
|
msg(nsimage, s("template"), YES);
|
||||||
|
}
|
||||||
msg(item, s("setImage:"), nsimage);
|
msg(item, s("setImage:"), nsimage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -740,6 +743,9 @@ void processMenuItem(Menu *menu, id parentMenu, JsonNode *item) {
|
|||||||
const char *image = getJSONString(item, "Image");
|
const char *image = getJSONString(item, "Image");
|
||||||
const char *fontName = getJSONString(item, "FontName");
|
const char *fontName = getJSONString(item, "FontName");
|
||||||
const char *RGBA = getJSONString(item, "RGBA");
|
const char *RGBA = getJSONString(item, "RGBA");
|
||||||
|
bool templateImage = false;
|
||||||
|
getJSONBool(item, "MacTemplateImage", &templateImage);
|
||||||
|
|
||||||
int fontSize = 12;
|
int fontSize = 12;
|
||||||
getJSONInt(item, "FontSize", &fontSize);
|
getJSONInt(item, "FontSize", &fontSize);
|
||||||
|
|
||||||
@@ -775,7 +781,7 @@ void processMenuItem(Menu *menu, id parentMenu, JsonNode *item) {
|
|||||||
if( type != NULL ) {
|
if( type != NULL ) {
|
||||||
|
|
||||||
if( STREQ(type->string_, "Text")) {
|
if( STREQ(type->string_, "Text")) {
|
||||||
processTextMenuItem(menu, parentMenu, label, menuid, disabled, acceleratorkey, modifiers, tooltip, image, fontName, fontSize, RGBA);
|
processTextMenuItem(menu, parentMenu, label, menuid, disabled, acceleratorkey, modifiers, tooltip, image, fontName, fontSize, RGBA, templateImage);
|
||||||
}
|
}
|
||||||
else if ( STREQ(type->string_, "Separator")) {
|
else if ( STREQ(type->string_, "Separator")) {
|
||||||
addSeparator(parentMenu);
|
addSeparator(parentMenu);
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ id processRadioMenuItem(Menu *menu, id parentmenu, const char *title, const char
|
|||||||
|
|
||||||
id processCheckboxMenuItem(Menu *menu, id parentmenu, const char *title, const char *menuid, bool disabled, bool checked, const char *key);
|
id processCheckboxMenuItem(Menu *menu, id parentmenu, const char *title, const char *menuid, bool disabled, bool checked, const char *key);
|
||||||
|
|
||||||
id processTextMenuItem(Menu *menu, id parentMenu, const char *title, const char *menuid, bool disabled, const char *acceleratorkey, const char **modifiers, const char* tooltip, const char* image, const char* fontName, int fontSize, const char* RGBA);
|
id processTextMenuItem(Menu *menu, id parentMenu, const char *title, const char *menuid, bool disabled, const char *acceleratorkey, const char **modifiers, const char* tooltip, const char* image, const char* fontName, int fontSize, const char* RGBA, bool templateImage);
|
||||||
void processMenuItem(Menu *menu, id parentMenu, JsonNode *item);
|
void processMenuItem(Menu *menu, id parentMenu, JsonNode *item);
|
||||||
void processMenuData(Menu *menu, JsonNode *menuData);
|
void processMenuData(Menu *menu, JsonNode *menuData);
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -2,6 +2,7 @@ package menumanager
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||||
"github.com/wailsapp/wails/v2/pkg/menu/keys"
|
"github.com/wailsapp/wails/v2/pkg/menu/keys"
|
||||||
)
|
)
|
||||||
@@ -34,7 +35,8 @@ type ProcessedMenuItem struct {
|
|||||||
FontName string `json:",omitempty"`
|
FontName string `json:",omitempty"`
|
||||||
|
|
||||||
// Image - base64 image data
|
// Image - base64 image data
|
||||||
Image string `json:",omitempty"`
|
Image string `json:",omitempty"`
|
||||||
|
MacTemplateImage bool `json:", omitempty"`
|
||||||
|
|
||||||
// Tooltip
|
// Tooltip
|
||||||
Tooltip string `json:",omitempty"`
|
Tooltip string `json:",omitempty"`
|
||||||
@@ -44,20 +46,21 @@ func NewProcessedMenuItem(menuItemMap *MenuItemMap, menuItem *menu.MenuItem) *Pr
|
|||||||
|
|
||||||
ID := menuItemMap.menuItemToIDMap[menuItem]
|
ID := menuItemMap.menuItemToIDMap[menuItem]
|
||||||
result := &ProcessedMenuItem{
|
result := &ProcessedMenuItem{
|
||||||
ID: ID,
|
ID: ID,
|
||||||
Label: menuItem.Label,
|
Label: menuItem.Label,
|
||||||
Role: menuItem.Role,
|
Role: menuItem.Role,
|
||||||
Accelerator: menuItem.Accelerator,
|
Accelerator: menuItem.Accelerator,
|
||||||
Type: menuItem.Type,
|
Type: menuItem.Type,
|
||||||
Disabled: menuItem.Disabled,
|
Disabled: menuItem.Disabled,
|
||||||
Hidden: menuItem.Hidden,
|
Hidden: menuItem.Hidden,
|
||||||
Checked: menuItem.Checked,
|
Checked: menuItem.Checked,
|
||||||
SubMenu: nil,
|
SubMenu: nil,
|
||||||
RGBA: menuItem.RGBA,
|
RGBA: menuItem.RGBA,
|
||||||
FontSize: menuItem.FontSize,
|
FontSize: menuItem.FontSize,
|
||||||
FontName: menuItem.FontName,
|
FontName: menuItem.FontName,
|
||||||
Image: menuItem.Image,
|
Image: menuItem.Image,
|
||||||
Tooltip: menuItem.Tooltip,
|
MacTemplateImage: menuItem.MacTemplateImage,
|
||||||
|
Tooltip: menuItem.Tooltip,
|
||||||
}
|
}
|
||||||
|
|
||||||
if menuItem.SubMenu != nil {
|
if menuItem.SubMenu != nil {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ func dialogMessageParser(message string) (*parsedMessage, error) {
|
|||||||
if idx < 0 {
|
if idx < 0 {
|
||||||
return nil, fmt.Errorf("Invalid dialog response message format: %+v", message)
|
return nil, fmt.Errorf("Invalid dialog response message format: %+v", message)
|
||||||
}
|
}
|
||||||
callbackID := message[:idx+1]
|
callbackID := message[:idx]
|
||||||
payloadData := message[idx+1:]
|
payloadData := message[idx+1:]
|
||||||
|
|
||||||
switch dialogType {
|
switch dialogType {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package process
|
package process
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/pkg/clilogger"
|
"github.com/wailsapp/wails/v2/pkg/clilogger"
|
||||||
@@ -16,11 +17,14 @@ type Process struct {
|
|||||||
|
|
||||||
// NewProcess creates a new process struct
|
// NewProcess creates a new process struct
|
||||||
func NewProcess(logger *clilogger.CLILogger, cmd string, args ...string) *Process {
|
func NewProcess(logger *clilogger.CLILogger, cmd string, args ...string) *Process {
|
||||||
return &Process{
|
result := &Process{
|
||||||
logger: logger,
|
logger: logger,
|
||||||
cmd: exec.Command(cmd, args...),
|
cmd: exec.Command(cmd, args...),
|
||||||
exitChannel: make(chan bool, 1),
|
exitChannel: make(chan bool, 1),
|
||||||
}
|
}
|
||||||
|
result.cmd.Stdout = os.Stdout
|
||||||
|
result.cmd.Stderr = os.Stderr
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the process
|
// Start the process
|
||||||
@@ -35,7 +39,12 @@ func (p *Process) Start() error {
|
|||||||
|
|
||||||
go func(cmd *exec.Cmd, running *bool, logger *clilogger.CLILogger, exitChannel chan bool) {
|
go func(cmd *exec.Cmd, running *bool, logger *clilogger.CLILogger, exitChannel chan bool) {
|
||||||
logger.Println("Starting process (PID: %d)", cmd.Process.Pid)
|
logger.Println("Starting process (PID: %d)", cmd.Process.Pid)
|
||||||
cmd.Wait()
|
err := cmd.Wait()
|
||||||
|
if err != nil {
|
||||||
|
if err.Error() != "signal: killed" {
|
||||||
|
logger.Fatal("Fatal error from app: " + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
logger.Println("Exiting process (PID: %d)", cmd.Process.Pid)
|
logger.Println("Exiting process (PID: %d)", cmd.Process.Pid)
|
||||||
*running = false
|
*running = false
|
||||||
exitChannel <- true
|
exitChannel <- true
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ export function SetBindings(bindingsMap) {
|
|||||||
window.backend[packageName][structName][methodName] = function () {
|
window.backend[packageName][structName][methodName] = function () {
|
||||||
|
|
||||||
// No timeout by default
|
// No timeout by default
|
||||||
var timeout = 0;
|
let timeout = 0;
|
||||||
|
|
||||||
// Actual function
|
// Actual function
|
||||||
function dynamic() {
|
function dynamic() {
|
||||||
@@ -89,19 +89,3 @@ export function SetBindings(bindingsMap) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// /**
|
|
||||||
// * Determines if the given identifier is valid Javascript
|
|
||||||
// *
|
|
||||||
// * @param {boolean} name
|
|
||||||
// * @returns
|
|
||||||
// */
|
|
||||||
// function isValidIdentifier(name) {
|
|
||||||
// // Don't xss yourself :-)
|
|
||||||
// try {
|
|
||||||
// new Function('var ' + name);
|
|
||||||
// return true;
|
|
||||||
// } catch (e) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { Error } from './log';
|
|||||||
import { SendMessage } from 'ipc';
|
import { SendMessage } from 'ipc';
|
||||||
|
|
||||||
// Defines a single listener with a maximum number of times to callback
|
// Defines a single listener with a maximum number of times to callback
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Listener class defines a listener! :-)
|
* The Listener class defines a listener! :-)
|
||||||
*
|
*
|
||||||
@@ -43,7 +44,7 @@ class Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var eventListeners = {};
|
let eventListeners = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers an event listener that will be invoked `maxCallbacks` times before being destroyed
|
* Registers an event listener that will be invoked `maxCallbacks` times before being destroyed
|
||||||
@@ -96,7 +97,7 @@ export function Once(eventName, callback) {
|
|||||||
function notifyListeners(eventData) {
|
function notifyListeners(eventData) {
|
||||||
|
|
||||||
// Get the event name
|
// Get the event name
|
||||||
var eventName = eventData.name;
|
let eventName = eventData.name;
|
||||||
|
|
||||||
// Check if we have any listeners for this event
|
// Check if we have any listeners for this event
|
||||||
if (eventListeners[eventName]) {
|
if (eventListeners[eventName]) {
|
||||||
@@ -110,7 +111,7 @@ function notifyListeners(eventData) {
|
|||||||
// Get next listener
|
// Get next listener
|
||||||
const listener = eventListeners[eventName][count];
|
const listener = eventListeners[eventName][count];
|
||||||
|
|
||||||
var data = eventData.data;
|
let data = eventData.data;
|
||||||
|
|
||||||
// Do the callback
|
// Do the callback
|
||||||
const destroy = listener.Callback(data);
|
const destroy = listener.Callback(data);
|
||||||
@@ -120,7 +121,7 @@ function notifyListeners(eventData) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update callbacks with new list of listners
|
// Update callbacks with new list of listeners
|
||||||
eventListeners[eventName] = newEventListenerList;
|
eventListeners[eventName] = newEventListenerList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,4 @@ export function Init() {
|
|||||||
|
|
||||||
// Do platform specific Init
|
// Do platform specific Init
|
||||||
Platform.Init();
|
Platform.Init();
|
||||||
|
|
||||||
window.wailsloader.runtime = true;
|
|
||||||
}
|
}
|
||||||
@@ -27,7 +27,7 @@ export function Init() {
|
|||||||
// Setup drag handler
|
// Setup drag handler
|
||||||
// Based on code from: https://github.com/patr0nus/DeskGap
|
// Based on code from: https://github.com/patr0nus/DeskGap
|
||||||
window.addEventListener('mousedown', function (e) {
|
window.addEventListener('mousedown', function (e) {
|
||||||
var currentElement = e.target;
|
let currentElement = e.target;
|
||||||
while (currentElement != null) {
|
while (currentElement != null) {
|
||||||
if (currentElement.hasAttribute('data-wails-no-drag')) {
|
if (currentElement.hasAttribute('data-wails-no-drag')) {
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
bridge.js
|
src
|
||||||
1693
v2/internal/runtime/js/runtime/bridge.js
Normal file
1693
v2/internal/runtime/js/runtime/bridge.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -9,13 +9,25 @@ The lightweight framework for web-like apps
|
|||||||
*/
|
*/
|
||||||
/* jshint esversion: 6 */
|
/* jshint esversion: 6 */
|
||||||
|
|
||||||
|
import bridge from './bridge';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialises the Wails runtime
|
* ready will execute the callback when Wails has loaded
|
||||||
|
* and initialised.
|
||||||
*
|
*
|
||||||
* @param {function} callback
|
* @param {function} callback
|
||||||
*/
|
*/
|
||||||
function Init(callback) {
|
function ready(callback) {
|
||||||
window.wails._.Init(callback);
|
|
||||||
|
// If window.wails exists, we are ready
|
||||||
|
if( window.wails ) {
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not we need to setup the bridge
|
||||||
|
bridge.InitBridge(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Init;
|
module.exports = {
|
||||||
|
ready: ready,
|
||||||
|
};
|
||||||
@@ -23,7 +23,7 @@ module.exports = {
|
|||||||
Browser: Browser,
|
Browser: Browser,
|
||||||
Dialog: Dialog,
|
Dialog: Dialog,
|
||||||
Events: Events,
|
Events: Events,
|
||||||
Init: Init,
|
ready: Init.ready,
|
||||||
Log: Log,
|
Log: Log,
|
||||||
System: System,
|
System: System,
|
||||||
Store: Store,
|
Store: Store,
|
||||||
|
|||||||
2
v2/internal/runtime/js/runtime/package-lock.json
generated
2
v2/internal/runtime/js/runtime/package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wails/runtime",
|
"name": "@wails/runtime",
|
||||||
"version": "1.2.13",
|
"version": "1.2.24",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wails/runtime",
|
"name": "@wails/runtime",
|
||||||
"version": "1.2.22",
|
"version": "1.3.9",
|
||||||
"description": "Wails V2 Javascript runtime library",
|
"description": "Wails V2 Javascript runtime library",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"types": "runtime.d.ts",
|
"types": "runtime.d.ts",
|
||||||
|
|||||||
56
v2/internal/runtime/js/runtime/src/Menu.svelte
Normal file
56
v2/internal/runtime/js/runtime/src/Menu.svelte
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<script>
|
||||||
|
|
||||||
|
export let menu;
|
||||||
|
|
||||||
|
export let hidden = true;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if !hidden}
|
||||||
|
<div class="menu">
|
||||||
|
{#if menu.Menu }
|
||||||
|
{#each menu.Menu.Items as menuItem}
|
||||||
|
<div class="menuitem">
|
||||||
|
{#if menuItem.Image }
|
||||||
|
<div><img alt="" src="data:image/png;base64,{menuItem.Image}"/></div>
|
||||||
|
{/if}
|
||||||
|
<div class="menulabel">{menuItem.Label}</div>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
.menu {
|
||||||
|
padding: 3px;
|
||||||
|
background-color: #0008;
|
||||||
|
color: #EEF;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin-top: 5px;
|
||||||
|
position: absolute;
|
||||||
|
backdrop-filter: blur(3px) saturate(160%) contrast(45%) brightness(140%);
|
||||||
|
border: 1px solid rgb(88,88,88);
|
||||||
|
box-shadow: 0 0 1px rgb(146,146,148) inset;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.menuitem {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 1px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menuitem:hover {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background-color: rgb(57,131,223);
|
||||||
|
padding: 1px 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menuitem img {
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
61
v2/internal/runtime/js/runtime/src/Menubar.svelte
Normal file
61
v2/internal/runtime/js/runtime/src/Menubar.svelte
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<script>
|
||||||
|
|
||||||
|
import {menuVisible} from './store'
|
||||||
|
import {fade} from 'svelte/transition';
|
||||||
|
|
||||||
|
import {trays} from './store'
|
||||||
|
import TrayMenu from "./TrayMenu.svelte";
|
||||||
|
import {onMount} from "svelte";
|
||||||
|
|
||||||
|
let time = new Date();
|
||||||
|
$: day = time.toLocaleString("default", { weekday: "short" })
|
||||||
|
$: dom = time.getDate()
|
||||||
|
$: mon = time.toLocaleString("default", { month: "short" })
|
||||||
|
$: currentTime = time.toLocaleString('en-US', { hour: 'numeric', minute: 'numeric', hour12: true }).toLowerCase()
|
||||||
|
$: dateTimeString = `${day} ${dom} ${mon} ${currentTime}`
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
time = new Date();
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearInterval(interval);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if $menuVisible }
|
||||||
|
<div class="wails-menubar" transition:fade>
|
||||||
|
<span class="tray-menus">
|
||||||
|
{#each $trays as tray}
|
||||||
|
<TrayMenu {tray}/>
|
||||||
|
{/each}
|
||||||
|
<span class="time">{dateTimeString}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
.tray-menus {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
.wails-menubar { position: relative;
|
||||||
|
display: block;
|
||||||
|
top: 0;
|
||||||
|
height: 2rem;
|
||||||
|
width: 100%;
|
||||||
|
border-bottom: 1px solid #b3b3b3;
|
||||||
|
box-shadow: 0 0 10px 0 #33333360;
|
||||||
|
}
|
||||||
|
.time {
|
||||||
|
padding-left: 0.5rem;
|
||||||
|
padding-right: 1.5rem;
|
||||||
|
overflow: visible;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
55
v2/internal/runtime/js/runtime/src/Overlay.svelte
Normal file
55
v2/internal/runtime/js/runtime/src/Overlay.svelte
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
<script>
|
||||||
|
|
||||||
|
import { overlayVisible } from './store'
|
||||||
|
import { fade, } from 'svelte/transition';
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if $overlayVisible }
|
||||||
|
<div class="wails-reconnect-overlay" transition:fade="{{ duration: 200 }}">
|
||||||
|
<div class="wails-reconnect-overlay-content">
|
||||||
|
<div class="wails-reconnect-overlay-loadingspinner"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.wails-reconnect-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
backdrop-filter: blur(20px) saturate(160%) contrast(45%) brightness(140%);
|
||||||
|
z-index: 999999
|
||||||
|
}
|
||||||
|
|
||||||
|
.wails-reconnect-overlay-content {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
.wails-reconnect-overlay-loadingspinner {
|
||||||
|
pointer-events: none;
|
||||||
|
width: 2.5em;
|
||||||
|
height: 2.5em;
|
||||||
|
border: .4em solid transparent;
|
||||||
|
border-color: #f00 #eee0 #f00 #eee0;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: loadingspin 1s linear infinite;
|
||||||
|
margin: auto;
|
||||||
|
padding: 2.5em
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes loadingspin {
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
65
v2/internal/runtime/js/runtime/src/TrayMenu.svelte
Normal file
65
v2/internal/runtime/js/runtime/src/TrayMenu.svelte
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<script>
|
||||||
|
import Menu from "./Menu.svelte";
|
||||||
|
import { selectedMenu } from "./store";
|
||||||
|
|
||||||
|
export let tray = null;
|
||||||
|
|
||||||
|
$: hidden = $selectedMenu !== tray;
|
||||||
|
|
||||||
|
function closeMenu() {
|
||||||
|
selectedMenu.set(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function trayClicked() {
|
||||||
|
if ( $selectedMenu !== tray ) {
|
||||||
|
selectedMenu.set(tray);
|
||||||
|
} else {
|
||||||
|
selectedMenu.set(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Source: https://svelte.dev/repl/0ace7a508bd843b798ae599940a91783?version=3.16.7
|
||||||
|
/** Dispatch event on click outside of node */
|
||||||
|
function clickOutside(node) {
|
||||||
|
|
||||||
|
const handleClick = event => {
|
||||||
|
if (node && !node.contains(event.target) && !event.defaultPrevented) {
|
||||||
|
node.dispatchEvent(
|
||||||
|
new CustomEvent('click_outside', node)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('click', handleClick, true);
|
||||||
|
|
||||||
|
return {
|
||||||
|
destroy() {
|
||||||
|
document.removeEventListener('click', handleClick, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<span class="tray-menu" use:clickOutside on:click_outside={closeMenu}>
|
||||||
|
<!--{#if tray.Image && tray.Image.length > 0}-->
|
||||||
|
<!-- <img alt="" src="data:image/png;base64,{tray.Image}"/>-->
|
||||||
|
<!--{/if}-->
|
||||||
|
<span class="label" on:click={trayClicked}>{tray.Label}</span>
|
||||||
|
{#if tray.ProcessedMenu }
|
||||||
|
<Menu menu="{tray.ProcessedMenu}" {hidden}/>
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
.tray-menu {
|
||||||
|
padding-left: 0.5rem;
|
||||||
|
padding-right: 0.5rem;
|
||||||
|
overflow: visible;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
9
v2/internal/runtime/js/runtime/src/log.js
Normal file
9
v2/internal/runtime/js/runtime/src/log.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
export function log(message) {
|
||||||
|
// eslint-disable-next-line
|
||||||
|
console.log(
|
||||||
|
'%c wails bridge %c ' + message + ' ',
|
||||||
|
'background: #aa0000; color: #fff; border-radius: 3px 0px 0px 3px; padding: 1px; font-size: 0.7rem',
|
||||||
|
'background: #009900; color: #fff; border-radius: 0px 3px 3px 0px; padding: 1px; font-size: 0.7rem'
|
||||||
|
);
|
||||||
|
}
|
||||||
45
v2/internal/runtime/js/runtime/src/main.js
Normal file
45
v2/internal/runtime/js/runtime/src/main.js
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
_ __ _ __
|
||||||
|
| | / /___ _(_) /____
|
||||||
|
| | /| / / __ `/ / / ___/
|
||||||
|
| |/ |/ / /_/ / / (__ )
|
||||||
|
|__/|__/\__,_/_/_/____/
|
||||||
|
The lightweight framework for web-like apps
|
||||||
|
(c) Lea Anthony 2019-present
|
||||||
|
*/
|
||||||
|
/* jshint esversion: 6 */
|
||||||
|
|
||||||
|
import Overlay from './Overlay.svelte';
|
||||||
|
import MenuBar from './Menubar.svelte';
|
||||||
|
import {showOverlay} from "./store";
|
||||||
|
import {StartWebsocket} from "./websocket";
|
||||||
|
|
||||||
|
let components = {};
|
||||||
|
|
||||||
|
function setupMenuBar() {
|
||||||
|
components.menubar = new MenuBar({
|
||||||
|
target: document.body,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets up the overlay
|
||||||
|
function setupOverlay() {
|
||||||
|
components.overlay = new Overlay({
|
||||||
|
target: document.body,
|
||||||
|
anchor: document.querySelector('#wails-bridge'),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function InitBridge(callback) {
|
||||||
|
|
||||||
|
setupMenuBar()
|
||||||
|
|
||||||
|
// Setup the overlay
|
||||||
|
setupOverlay();
|
||||||
|
|
||||||
|
// Start by showing the overlay...
|
||||||
|
showOverlay();
|
||||||
|
|
||||||
|
// ...and attempt to connect
|
||||||
|
StartWebsocket(callback);
|
||||||
|
}
|
||||||
525
v2/internal/runtime/js/runtime/src/package-lock.json
generated
Normal file
525
v2/internal/runtime/js/runtime/src/package-lock.json
generated
Normal file
@@ -0,0 +1,525 @@
|
|||||||
|
{
|
||||||
|
"name": "bridge",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"requires": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@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,
|
||||||
|
"requires": {
|
||||||
|
"@babel/highlight": "^7.12.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@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
|
||||||
|
},
|
||||||
|
"@babel/highlight": {
|
||||||
|
"version": "7.12.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz",
|
||||||
|
"integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/helper-validator-identifier": "^7.12.11",
|
||||||
|
"chalk": "^2.0.0",
|
||||||
|
"js-tokens": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@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,
|
||||||
|
"requires": {
|
||||||
|
"@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"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@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,
|
||||||
|
"requires": {
|
||||||
|
"@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"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@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,
|
||||||
|
"requires": {
|
||||||
|
"@types/estree": "0.0.39",
|
||||||
|
"estree-walker": "^1.0.1",
|
||||||
|
"picomatch": "^2.2.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@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
|
||||||
|
},
|
||||||
|
"@types/node": {
|
||||||
|
"version": "14.14.25",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.25.tgz",
|
||||||
|
"integrity": "sha512-EPpXLOVqDvisVxtlbvzfyqSsFeQxltFbluZNRndIb8tr9KiBnYNLzrc1N3pyKUCww2RNrfHDViqDWWE1LCJQtQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/resolve": {
|
||||||
|
"version": "1.17.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
|
||||||
|
"integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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,
|
||||||
|
"requires": {
|
||||||
|
"color-convert": "^1.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"balanced-match": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"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,
|
||||||
|
"requires": {
|
||||||
|
"balanced-match": "^1.0.0",
|
||||||
|
"concat-map": "0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"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,
|
||||||
|
"requires": {
|
||||||
|
"ansi-styles": "^3.2.1",
|
||||||
|
"escape-string-regexp": "^1.0.5",
|
||||||
|
"supports-color": "^5.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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,
|
||||||
|
"requires": {
|
||||||
|
"color-name": "1.1.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"color-name": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||||
|
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"commondir": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"fs.realpath": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"function-bind": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"glob": {
|
||||||
|
"version": "7.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
||||||
|
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"has": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"function-bind": "^1.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"has-flag": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"inflight": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||||
|
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"once": "^1.3.0",
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inherits": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"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,
|
||||||
|
"requires": {
|
||||||
|
"has": "^1.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"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,
|
||||||
|
"requires": {
|
||||||
|
"@types/estree": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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,
|
||||||
|
"requires": {
|
||||||
|
"@types/node": "*",
|
||||||
|
"merge-stream": "^2.0.0",
|
||||||
|
"supports-color": "^7.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"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,
|
||||||
|
"requires": {
|
||||||
|
"has-flag": "^4.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"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,
|
||||||
|
"requires": {
|
||||||
|
"sourcemap-codec": "^1.4.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"minimatch": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"brace-expansion": "^1.1.7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"once": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
|
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"picomatch": {
|
||||||
|
"version": "2.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
|
||||||
|
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"randombytes": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"safe-buffer": "^5.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"require-relative": {
|
||||||
|
"version": "0.8.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz",
|
||||||
|
"integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"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,
|
||||||
|
"requires": {
|
||||||
|
"is-core-module": "^2.1.0",
|
||||||
|
"path-parse": "^1.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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,
|
||||||
|
"requires": {
|
||||||
|
"fsevents": "~2.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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,
|
||||||
|
"requires": {
|
||||||
|
"require-relative": "^0.8.7",
|
||||||
|
"rollup-pluginutils": "^2.8.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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,
|
||||||
|
"requires": {
|
||||||
|
"@babel/code-frame": "^7.10.4",
|
||||||
|
"jest-worker": "^26.2.1",
|
||||||
|
"serialize-javascript": "^4.0.0",
|
||||||
|
"terser": "^5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rollup-pluginutils": {
|
||||||
|
"version": "2.8.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz",
|
||||||
|
"integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"estree-walker": "^0.6.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"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,
|
||||||
|
"requires": {
|
||||||
|
"randombytes": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"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,
|
||||||
|
"requires": {
|
||||||
|
"buffer-from": "^1.0.0",
|
||||||
|
"source-map": "^0.6.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"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,
|
||||||
|
"requires": {
|
||||||
|
"has-flag": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"terser": {
|
||||||
|
"version": "5.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/terser/-/terser-5.5.1.tgz",
|
||||||
|
"integrity": "sha512-6VGWZNVP2KTUcltUQJ25TtNjx/XgdDsBDKGt8nN0MpydU36LmbPPcMBd2kmtZNNGVVDLg44k7GKeHHj+4zPIBQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"commander": "^2.20.0",
|
||||||
|
"source-map": "~0.7.2",
|
||||||
|
"source-map-support": "~0.5.19"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"wrappy": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
v2/internal/runtime/js/runtime/src/package.json
Normal file
21
v2/internal/runtime/js/runtime/src/package.json
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"name": "bridge",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Wails bridge",
|
||||||
|
"main": "main.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"build": "npx rollup -c",
|
||||||
|
"watch": "npx rollup -c -w"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
37
v2/internal/runtime/js/runtime/src/rollup.config.js
Normal file
37
v2/internal/runtime/js/runtime/src/rollup.config.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import resolve from '@rollup/plugin-node-resolve';
|
||||||
|
// import commonjs from '@rollup/plugin-commonjs';
|
||||||
|
import svelte from 'rollup-plugin-svelte';
|
||||||
|
import { terser } from "rollup-plugin-terser";
|
||||||
|
|
||||||
|
export default [
|
||||||
|
// browser-friendly UMD build
|
||||||
|
{
|
||||||
|
input: 'main.js',
|
||||||
|
output: {
|
||||||
|
name: 'bridge',
|
||||||
|
file: '../bridge.js',
|
||||||
|
format: 'umd',
|
||||||
|
exports: "named"
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
svelte({
|
||||||
|
// Optionally, preprocess components with svelte.preprocess:
|
||||||
|
// https://svelte.dev/docs#svelte_preprocess
|
||||||
|
// preprocess: {
|
||||||
|
// style: ({content}) => {
|
||||||
|
// return transformStyles(content);
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
|
||||||
|
// Emit CSS as "files" for other plugins to process. default is true
|
||||||
|
emitCss: false,
|
||||||
|
|
||||||
|
}),
|
||||||
|
resolve({browser: true}), // so Rollup can find `ms`
|
||||||
|
// commonjs() // so Rollup can convert `ms` to an ES module
|
||||||
|
// terser(),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
];
|
||||||
52
v2/internal/runtime/js/runtime/src/store.js
Normal file
52
v2/internal/runtime/js/runtime/src/store.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
|
||||||
|
import { writable } from 'svelte/store';
|
||||||
|
import {log} from "./log";
|
||||||
|
|
||||||
|
/** Overlay */
|
||||||
|
export const overlayVisible = writable(false);
|
||||||
|
|
||||||
|
export function showOverlay() {
|
||||||
|
overlayVisible.set(true);
|
||||||
|
}
|
||||||
|
export function hideOverlay() {
|
||||||
|
overlayVisible.set(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Menubar **/
|
||||||
|
export const menuVisible = writable(true);
|
||||||
|
|
||||||
|
export function showMenuBar() {
|
||||||
|
menuVisible.set(true);
|
||||||
|
}
|
||||||
|
export function hideMenuBar() {
|
||||||
|
menuVisible.set(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Trays **/
|
||||||
|
|
||||||
|
export const trays = writable([]);
|
||||||
|
export function setTray(tray) {
|
||||||
|
trays.update((current) => {
|
||||||
|
// Remove existing if it exists, else add
|
||||||
|
const index = current.findIndex(item => item.ID === tray.ID);
|
||||||
|
if ( index === -1 ) {
|
||||||
|
current.push(tray);
|
||||||
|
} else {
|
||||||
|
current[index] = tray;
|
||||||
|
}
|
||||||
|
return current;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export function updateTrayLabel(tray) {
|
||||||
|
trays.update((current) => {
|
||||||
|
// Remove existing if it exists, else add
|
||||||
|
const index = current.findIndex(item => item.ID === tray.ID);
|
||||||
|
if ( index === -1 ) {
|
||||||
|
return log("ERROR: Attempted to update tray index ", tray.ID, "but it doesn't exist")
|
||||||
|
}
|
||||||
|
current[index].Label = tray.Label;
|
||||||
|
return current;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export let selectedMenu = writable(null);
|
||||||
165
v2/internal/runtime/js/runtime/src/websocket.js
Normal file
165
v2/internal/runtime/js/runtime/src/websocket.js
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
_ __ _ __
|
||||||
|
| | / /___ _(_) /____
|
||||||
|
| | /| / / __ `/ / / ___/
|
||||||
|
| |/ |/ / /_/ / / (__ )
|
||||||
|
|__/|__/\__,_/_/_/____/
|
||||||
|
The lightweight framework for web-like apps
|
||||||
|
(c) Lea Anthony 2019-present
|
||||||
|
*/
|
||||||
|
/* jshint esversion: 6 */
|
||||||
|
|
||||||
|
|
||||||
|
import {setTray, hideOverlay, showOverlay, updateTrayLabel} from "./store";
|
||||||
|
import {log} from "./log";
|
||||||
|
|
||||||
|
let websocket = null;
|
||||||
|
let callback = null;
|
||||||
|
let connectTimer;
|
||||||
|
|
||||||
|
export function StartWebsocket(userCallback) {
|
||||||
|
|
||||||
|
callback = userCallback;
|
||||||
|
|
||||||
|
window.onbeforeunload = function() {
|
||||||
|
if( websocket ) {
|
||||||
|
websocket.onclose = function () { };
|
||||||
|
websocket.close();
|
||||||
|
websocket = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...and attempt to connect
|
||||||
|
connect();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupIPCBridge() {
|
||||||
|
// darwin
|
||||||
|
window.webkit = {
|
||||||
|
messageHandlers: {
|
||||||
|
external: {
|
||||||
|
postMessage: (message) => {
|
||||||
|
websocket.send(message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
windowDrag: {
|
||||||
|
postMessage: () => {
|
||||||
|
// Ignore window drag events
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handles incoming websocket connections
|
||||||
|
function handleConnect() {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// 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');
|
||||||
|
|
||||||
|
// We need to now send a message to the backend telling it
|
||||||
|
// we have loaded (System Start)
|
||||||
|
window.webkit.messageHandlers.external.postMessage("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':
|
||||||
|
// addScript(message.data.slice(1), true);
|
||||||
|
// 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
|
||||||
|
default:
|
||||||
|
log('Unknown tray message: ' + message.data);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
log('Unknown message: ' + message.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,7 +13,7 @@ const Events = require('./events');
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers an event listener that will be invoked when the user changes the
|
* Registers an event listener that will be invoked when the user changes the
|
||||||
* desktop theme (light mode / dark mode). The callback receives a boolean which
|
* desktop theme (light mode / dark mode). The callback receives a booleanean which
|
||||||
* indicates if dark mode is enabled.
|
* indicates if dark mode is enabled.
|
||||||
*
|
*
|
||||||
* @export
|
* @export
|
||||||
@@ -43,12 +43,12 @@ function DarkModeEnabled() {
|
|||||||
* Mac Title Bar Config
|
* Mac Title Bar Config
|
||||||
* Check out https://github.com/lukakerr/NSWindowStyles for some examples of these settings
|
* Check out https://github.com/lukakerr/NSWindowStyles for some examples of these settings
|
||||||
* @typedef {Object} MacTitleBar
|
* @typedef {Object} MacTitleBar
|
||||||
* @param {bool} TitleBarAppearsTransparent - NSWindow.titleBarAppearsTransparent
|
* @param {boolean} TitleBarAppearsTransparent - NSWindow.titleBarAppearsTransparent
|
||||||
* @param {bool} HideTitle - NSWindow.hideTitle
|
* @param {boolean} HideTitle - NSWindow.hideTitle
|
||||||
* @param {bool} HideTitleBar - NSWindow.hideTitleBar
|
* @param {boolean} HideTitleBar - NSWindow.hideTitleBar
|
||||||
* @param {bool} FullSizeContent - Makes the webview portion of the window the full size of the window, even over the titlebar
|
* @param {boolean} FullSizeContent - Makes the webview portion of the window the full size of the window, even over the titlebar
|
||||||
* @param {bool} UseToolbar - Set true to add a blank toolbar to the window (makes the title bar larger)
|
* @param {boolean} UseToolbar - Set true to add a blank toolbar to the window (makes the title bar larger)
|
||||||
* @param {bool} HideToolbarSeparator - Set true to remove the separator between the toolbar and the main content area
|
* @param {boolean} HideToolbarSeparator - Set true to remove the separator between the toolbar and the main content area
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -65,8 +65,8 @@ function DarkModeEnabled() {
|
|||||||
* @param {number} MinHeight - Window Minimum Height
|
* @param {number} MinHeight - Window Minimum Height
|
||||||
* @param {number} MaxWidth - Window Maximum Width
|
* @param {number} MaxWidth - Window Maximum Width
|
||||||
* @param {number} MaxHeight - Window Maximum Height
|
* @param {number} MaxHeight - Window Maximum Height
|
||||||
* @param {bool} StartHidden - Start with window hidden
|
* @param {boolean} StartHidden - Start with window hidden
|
||||||
* @param {bool} DevTools - Enables the window devtools
|
* @param {boolean} DevTools - Enables the window devtools
|
||||||
* @param {number} RBGA - The initial window colour. Convert to hex then it'll mean 0xRRGGBBAA
|
* @param {number} RBGA - The initial window colour. Convert to hex then it'll mean 0xRRGGBBAA
|
||||||
* @param {MacAppConfig} [Mac] - Configuration when running on Mac
|
* @param {MacAppConfig} [Mac] - Configuration when running on Mac
|
||||||
* @param {LinuxAppConfig} [Linux] - Configuration when running on Linux
|
* @param {LinuxAppConfig} [Linux] - Configuration when running on Linux
|
||||||
@@ -88,11 +88,23 @@ function AppConfig() {
|
|||||||
return window.wails.System.AppConfig.get();
|
return window.wails.System.AppConfig.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function LogLevel() {
|
||||||
|
return window.wails.System.LogLevel();
|
||||||
|
}
|
||||||
|
|
||||||
|
function Platform() {
|
||||||
|
return window.wails.System.Platform();
|
||||||
|
}
|
||||||
|
|
||||||
|
function AppType() {
|
||||||
|
return window.wails.System.AppType();
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
OnThemeChange: OnThemeChange,
|
OnThemeChange: OnThemeChange,
|
||||||
DarkModeEnabled: DarkModeEnabled,
|
DarkModeEnabled: DarkModeEnabled,
|
||||||
LogLevel: window.wails.System.LogLevel,
|
LogLevel: LogLevel,
|
||||||
Platform: window.wails.System.Platform,
|
Platform: Platform,
|
||||||
AppType: window.wails.System.AppType,
|
AppType: AppType,
|
||||||
AppConfig: AppConfig,
|
AppConfig: AppConfig,
|
||||||
};
|
};
|
||||||
@@ -50,12 +50,20 @@ func main() {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
wailsJS := fs.RelativePath("../../../internal/runtime/assets/desktop_" + platform + ".js")
|
wailsJS := fs.RelativePath("../assets/desktop_" + platform + ".js")
|
||||||
runtimeData, err := ioutil.ReadFile(wailsJS)
|
runtimeData, err := ioutil.ReadFile(wailsJS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy this file to bridge directory for embedding
|
||||||
|
bridgeDir := fs.RelativePath("../../bridge/" + platform + ".js")
|
||||||
|
println("Copying", wailsJS, "to", bridgeDir)
|
||||||
|
err = fs.CopyFile(wailsJS, bridgeDir)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
// Convert to C structure
|
// Convert to C structure
|
||||||
runtimeC := `
|
runtimeC := `
|
||||||
// runtime.c (c) 2019-Present Lea Anthony.
|
// runtime.c (c) 2019-Present Lea Anthony.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/internal/logger"
|
"github.com/wailsapp/wails/v2/internal/logger"
|
||||||
"github.com/wailsapp/wails/v2/internal/runtime"
|
"github.com/wailsapp/wails/v2/internal/runtime"
|
||||||
@@ -30,6 +31,9 @@ type Runtime struct {
|
|||||||
|
|
||||||
//ctx
|
//ctx
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
|
|
||||||
|
// Startup Hook
|
||||||
|
startupOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRuntime creates a new runtime subsystem
|
// NewRuntime creates a new runtime subsystem
|
||||||
@@ -75,7 +79,9 @@ func (r *Runtime) Start() error {
|
|||||||
switch hook {
|
switch hook {
|
||||||
case "startup":
|
case "startup":
|
||||||
if r.startupCallback != nil {
|
if r.startupCallback != nil {
|
||||||
go r.startupCallback(r.runtime)
|
r.startupOnce.Do(func() {
|
||||||
|
go r.startupCallback(r.runtime)
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
r.logger.Warning("no startup callback registered!")
|
r.logger.Warning("no startup callback registered!")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/internal/colour"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CLILogger is used by the cli
|
// CLILogger is used by the cli
|
||||||
@@ -51,9 +53,9 @@ func (c *CLILogger) Println(message string, args ...interface{}) {
|
|||||||
// Fatal prints the given message then aborts
|
// Fatal prints the given message then aborts
|
||||||
func (c *CLILogger) Fatal(message string, args ...interface{}) {
|
func (c *CLILogger) Fatal(message string, args ...interface{}) {
|
||||||
temp := fmt.Sprintf(message, args...)
|
temp := fmt.Sprintf(message, args...)
|
||||||
_, err := fmt.Fprintln(c.Writer, "FATAL: "+temp)
|
_, err := fmt.Fprintln(c.Writer, colour.Red("FATAL: "+temp))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
println("FATAL: ", err)
|
println(colour.Red("FATAL: " + err.Error()))
|
||||||
}
|
}
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ func Build(options *Options) (string, error) {
|
|||||||
builder = newHybridBuilder(options)
|
builder = newHybridBuilder(options)
|
||||||
case "server":
|
case "server":
|
||||||
builder = newServerBuilder(options)
|
builder = newServerBuilder(options)
|
||||||
|
case "dev":
|
||||||
|
builder = newDesktopBuilder(options)
|
||||||
default:
|
default:
|
||||||
return "", fmt.Errorf("cannot build assets for output type %s", projectData.OutputType)
|
return "", fmt.Errorf("cannot build assets for output type %s", projectData.OutputType)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
package keys
|
package keys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
// Modifier is actually a string
|
// Modifier is actually a string
|
||||||
type Modifier string
|
type Modifier string
|
||||||
|
|
||||||
@@ -16,6 +21,23 @@ const (
|
|||||||
ControlKey Modifier = "Control"
|
ControlKey Modifier = "Control"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var modifierMap = map[string]Modifier{
|
||||||
|
"cmdorctrl": CmdOrCtrlKey,
|
||||||
|
"optionoralt": OptionOrAltKey,
|
||||||
|
"shift": ShiftKey,
|
||||||
|
"super": SuperKey,
|
||||||
|
"ctrl": ControlKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseModifier(text string) (*Modifier, error) {
|
||||||
|
result, valid := modifierMap[text]
|
||||||
|
if !valid {
|
||||||
|
return nil, fmt.Errorf("'%s' is not a valid modifier", text)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &result, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Accelerator holds the keyboard shortcut for a menu item
|
// Accelerator holds the keyboard shortcut for a menu item
|
||||||
type Accelerator struct {
|
type Accelerator struct {
|
||||||
Key string
|
Key string
|
||||||
@@ -25,14 +47,14 @@ type Accelerator struct {
|
|||||||
// Key creates a standard key Accelerator
|
// Key creates a standard key Accelerator
|
||||||
func Key(key string) *Accelerator {
|
func Key(key string) *Accelerator {
|
||||||
return &Accelerator{
|
return &Accelerator{
|
||||||
Key: key,
|
Key: strings.ToLower(key),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CmdOrCtrl creates a 'CmdOrCtrl' Accelerator
|
// CmdOrCtrl creates a 'CmdOrCtrl' Accelerator
|
||||||
func CmdOrCtrl(key string) *Accelerator {
|
func CmdOrCtrl(key string) *Accelerator {
|
||||||
return &Accelerator{
|
return &Accelerator{
|
||||||
Key: key,
|
Key: strings.ToLower(key),
|
||||||
Modifiers: []Modifier{CmdOrCtrlKey},
|
Modifiers: []Modifier{CmdOrCtrlKey},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,7 +62,7 @@ func CmdOrCtrl(key string) *Accelerator {
|
|||||||
// OptionOrAlt creates a 'OptionOrAlt' Accelerator
|
// OptionOrAlt creates a 'OptionOrAlt' Accelerator
|
||||||
func OptionOrAlt(key string) *Accelerator {
|
func OptionOrAlt(key string) *Accelerator {
|
||||||
return &Accelerator{
|
return &Accelerator{
|
||||||
Key: key,
|
Key: strings.ToLower(key),
|
||||||
Modifiers: []Modifier{OptionOrAltKey},
|
Modifiers: []Modifier{OptionOrAltKey},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -48,7 +70,7 @@ func OptionOrAlt(key string) *Accelerator {
|
|||||||
// Shift creates a 'Shift' Accelerator
|
// Shift creates a 'Shift' Accelerator
|
||||||
func Shift(key string) *Accelerator {
|
func Shift(key string) *Accelerator {
|
||||||
return &Accelerator{
|
return &Accelerator{
|
||||||
Key: key,
|
Key: strings.ToLower(key),
|
||||||
Modifiers: []Modifier{ShiftKey},
|
Modifiers: []Modifier{ShiftKey},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -56,7 +78,7 @@ func Shift(key string) *Accelerator {
|
|||||||
// Control creates a 'Control' Accelerator
|
// Control creates a 'Control' Accelerator
|
||||||
func Control(key string) *Accelerator {
|
func Control(key string) *Accelerator {
|
||||||
return &Accelerator{
|
return &Accelerator{
|
||||||
Key: key,
|
Key: strings.ToLower(key),
|
||||||
Modifiers: []Modifier{ControlKey},
|
Modifiers: []Modifier{ControlKey},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,7 +86,7 @@ func Control(key string) *Accelerator {
|
|||||||
// Super creates a 'Super' Accelerator
|
// Super creates a 'Super' Accelerator
|
||||||
func Super(key string) *Accelerator {
|
func Super(key string) *Accelerator {
|
||||||
return &Accelerator{
|
return &Accelerator{
|
||||||
Key: key,
|
Key: strings.ToLower(key),
|
||||||
Modifiers: []Modifier{SuperKey},
|
Modifiers: []Modifier{SuperKey},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
90
v2/pkg/menu/keys/parser.go
Normal file
90
v2/pkg/menu/keys/parser.go
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
package keys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/leaanthony/slicer"
|
||||||
|
)
|
||||||
|
|
||||||
|
var namedKeys = slicer.String([]string{"backspace", "tab", "return", "escape", "left", "right", "up", "down", "space", "delete", "home", "end", "page up", "page down", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "f32", "f33", "f34", "f35", "numlock"})
|
||||||
|
|
||||||
|
func parseKey(key string) (string, bool) {
|
||||||
|
|
||||||
|
// Lowercase!
|
||||||
|
key = strings.ToLower(key)
|
||||||
|
|
||||||
|
// Check special case
|
||||||
|
if key == "plus" {
|
||||||
|
return "+", true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle named keys
|
||||||
|
if namedKeys.Contains(key) {
|
||||||
|
return key, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check we only have a single character
|
||||||
|
if len(key) != 1 {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
runeKey := rune(key[0])
|
||||||
|
|
||||||
|
// This may be too inclusive
|
||||||
|
if strconv.IsPrint(runeKey) {
|
||||||
|
return key, true
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func Parse(shortcut string) (*Accelerator, error) {
|
||||||
|
|
||||||
|
var result Accelerator
|
||||||
|
|
||||||
|
// Split the shortcut by +
|
||||||
|
components := strings.Split(shortcut, "+")
|
||||||
|
|
||||||
|
// If we only have one it should be a key
|
||||||
|
// We require components
|
||||||
|
if len(components) == 0 {
|
||||||
|
return nil, fmt.Errorf("no components given to validateComponents")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep track of modifiers we have processed
|
||||||
|
var modifiersProcessed slicer.StringSlicer
|
||||||
|
|
||||||
|
// Check components
|
||||||
|
for index, component := range components {
|
||||||
|
|
||||||
|
// If last component
|
||||||
|
if index == len(components)-1 {
|
||||||
|
processedkey, validKey := parseKey(component)
|
||||||
|
if !validKey {
|
||||||
|
return nil, fmt.Errorf("'%s' is not a valid key", component)
|
||||||
|
}
|
||||||
|
result.Key = processedkey
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not last component - needs to be modifier
|
||||||
|
lowercaseComponent := strings.ToLower(component)
|
||||||
|
thisModifier, valid := modifierMap[lowercaseComponent]
|
||||||
|
if !valid {
|
||||||
|
return nil, fmt.Errorf("'%s' is not a valid modifier", component)
|
||||||
|
}
|
||||||
|
// Needs to be unique
|
||||||
|
if modifiersProcessed.Contains(lowercaseComponent) {
|
||||||
|
return nil, fmt.Errorf("Modifier '%s' is defined twice for shortcut: %s", component, shortcut)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save this data
|
||||||
|
result.Modifiers = append(result.Modifiers, thisModifier)
|
||||||
|
modifiersProcessed.Add(lowercaseComponent)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &result, nil
|
||||||
|
}
|
||||||
38
v2/pkg/menu/keys/parser_test.go
Normal file
38
v2/pkg/menu/keys/parser_test.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package keys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/matryer/is"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParse(t *testing.T) {
|
||||||
|
|
||||||
|
i := is.New(t)
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
Input string
|
||||||
|
Expected *Accelerator
|
||||||
|
}
|
||||||
|
|
||||||
|
gooddata := []args{
|
||||||
|
{"CmdOrCtrl+A", CmdOrCtrl("A")},
|
||||||
|
{"SHIFT+.", Shift(".")},
|
||||||
|
{"CTRL+plus", Control("+")},
|
||||||
|
{"CTRL+SHIFT+escApe", Combo("escape", ControlKey, ShiftKey)},
|
||||||
|
{";", Key(";")},
|
||||||
|
{"Super+Tab", Super("tab")},
|
||||||
|
{"OptionOrAlt+Page Down", OptionOrAlt("Page Down")},
|
||||||
|
}
|
||||||
|
for _, tt := range gooddata {
|
||||||
|
result, err := Parse(tt.Input)
|
||||||
|
i.NoErr(err)
|
||||||
|
i.Equal(result, tt.Expected)
|
||||||
|
}
|
||||||
|
baddata := []string{"CmdOrCrl+A", "SHIT+.", "CTL+plus", "CTRL+SHIF+esApe", "escap", "Sper+Tab", "OptionOrAlt"}
|
||||||
|
for _, d := range baddata {
|
||||||
|
result, err := Parse(d)
|
||||||
|
i.True(err != nil)
|
||||||
|
i.Equal(result, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
package menu
|
package menu
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/wailsapp/wails/v2/pkg/menu/keys"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/pkg/menu/keys"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MenuItem represents a menuitem contained in a menu
|
// MenuItem represents a menuitem contained in a menu
|
||||||
@@ -38,6 +39,9 @@ type MenuItem struct {
|
|||||||
// Image - base64 image data
|
// Image - base64 image data
|
||||||
Image string
|
Image string
|
||||||
|
|
||||||
|
// MacTemplateImage indicates that on a mac, this image is a template image
|
||||||
|
MacTemplateImage bool
|
||||||
|
|
||||||
// Tooltip
|
// Tooltip
|
||||||
Tooltip string
|
Tooltip string
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user