mirror of
https://github.com/taigrr/wails.git
synced 2026-04-14 10:50:53 -07:00
Compare commits
27 Commits
feature/v2
...
v2.0.0-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13939d3d6b | ||
|
|
552c6b8711 | ||
|
|
feee2b3db2 | ||
|
|
9889c2bdbb | ||
|
|
2432fccf71 | ||
|
|
70510fd180 | ||
|
|
17c6201469 | ||
|
|
0f209c8900 | ||
|
|
cbf043585c | ||
|
|
5ae621ceaa | ||
|
|
1231b59443 | ||
|
|
b18d4fbf41 | ||
|
|
9ec5605e63 | ||
|
|
98a4de8878 | ||
|
|
5fe709f558 | ||
|
|
5231a6893b | ||
|
|
74f3ce990f | ||
|
|
998a913853 | ||
|
|
964844835c | ||
|
|
4e152bb849 | ||
|
|
51133d098c | ||
|
|
d4191e7d1b | ||
|
|
9c273bc745 | ||
|
|
c6f6ad6beb | ||
|
|
4362a14459 | ||
|
|
0080e9e311 | ||
|
|
83d9297cac |
@@ -1,30 +1,41 @@
|
|||||||
package dev
|
package dev
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/pkg/commands/build"
|
"github.com/wailsapp/wails/v2/internal/colour"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/internal/process"
|
|
||||||
|
|
||||||
"github.com/wzshiming/ctc"
|
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/internal/fs"
|
|
||||||
|
|
||||||
"github.com/fsnotify/fsnotify"
|
"github.com/fsnotify/fsnotify"
|
||||||
|
|
||||||
"github.com/leaanthony/clir"
|
"github.com/leaanthony/clir"
|
||||||
|
"github.com/wailsapp/wails/v2/internal/fs"
|
||||||
|
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
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 {
|
||||||
|
|
||||||
@@ -42,6 +53,13 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
|||||||
extensions := "go"
|
extensions := "go"
|
||||||
command.StringFlag("e", "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 {
|
||||||
|
|
||||||
// Create logger
|
// Create logger
|
||||||
@@ -49,262 +67,215 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
|||||||
app.PrintBanner()
|
app.PrintBanner()
|
||||||
|
|
||||||
// TODO: Check you are in a project directory
|
// TODO: Check you are in a project directory
|
||||||
|
|
||||||
|
watcher, err := fsnotify.NewWatcher()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer watcher.Close()
|
||||||
|
|
||||||
|
var debugBinaryProcess *process.Process = nil
|
||||||
var extensionsThatTriggerARebuild = strings.Split(extensions, ",")
|
var extensionsThatTriggerARebuild = strings.Split(extensions, ",")
|
||||||
|
|
||||||
reloader, err := NewReloader(logger, extensionsThatTriggerARebuild, ldflags, compilerCommand)
|
// Setup signal handler
|
||||||
|
quitChannel := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(quitChannel, os.Interrupt, os.Kill, syscall.SIGTERM)
|
||||||
|
|
||||||
|
debounceQuit := make(chan bool, 1)
|
||||||
|
|
||||||
|
// Do initial build
|
||||||
|
logger.Println("Building application for development...")
|
||||||
|
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) {
|
||||||
|
// logger.Println("event: %+v", event)
|
||||||
|
|
||||||
|
// Check for new directories
|
||||||
|
if event.Op&fsnotify.Create == fsnotify.Create {
|
||||||
|
// If this is a folder, add it to our watch list
|
||||||
|
if fs.DirExists(event.Name) {
|
||||||
|
if !strings.Contains(event.Name, "node_modules") {
|
||||||
|
err := watcher.Add(event.Name)
|
||||||
|
if err != nil {
|
||||||
|
logger.Fatal("%s", err.Error())
|
||||||
|
}
|
||||||
|
LogGreen("[New Directory] Watching new directory: %s", event.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for file writes
|
||||||
|
if event.Op&fsnotify.Write == fsnotify.Write {
|
||||||
|
|
||||||
|
var rebuild bool = false
|
||||||
|
|
||||||
|
// Iterate all file patterns
|
||||||
|
for _, pattern := range extensionsThatTriggerARebuild {
|
||||||
|
if strings.HasSuffix(event.Name, pattern) {
|
||||||
|
rebuild = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !rebuild {
|
||||||
|
if showWarnings {
|
||||||
|
LogDarkYellow("[File change] %s did not match extension list (%s)", event.Name, extensions)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
LogGreen("[Attempting rebuild] %s updated", event.Name)
|
||||||
|
|
||||||
|
// Do a rebuild
|
||||||
|
|
||||||
|
// Try and build the app
|
||||||
|
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 newBinaryProcess != nil {
|
||||||
|
debugBinaryProcess = newBinaryProcess
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Get project dir
|
||||||
|
projectDir, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start
|
// Get all subdirectories
|
||||||
err = reloader.Start()
|
dirs, err := fs.GetSubdirectories(projectDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
println("ERRRRRRRRRR: %+v", err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Println("\nDevelopment mode exited")
|
LogGreen("Watching (sub)/directory: %s", projectDir)
|
||||||
|
|
||||||
return err
|
// Setup a watcher for non-node_modules directories
|
||||||
|
dirs.Each(func(dir string) {
|
||||||
|
if strings.Contains(dir, "node_modules") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Ignore build directory
|
||||||
|
if strings.HasPrefix(dir, filepath.Join(projectDir, "build")) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = watcher.Add(dir)
|
||||||
|
if err != nil {
|
||||||
|
logger.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Wait until we get a quit signal
|
||||||
|
quit := false
|
||||||
|
for quit == false {
|
||||||
|
select {
|
||||||
|
case <-quitChannel:
|
||||||
|
LogGreen("\nCaught quit")
|
||||||
|
// Notify debouncer to quit
|
||||||
|
debounceQuit <- true
|
||||||
|
quit = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kill the current program if running
|
||||||
|
if debugBinaryProcess != nil {
|
||||||
|
err := debugBinaryProcess.Kill()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LogGreen("Development mode exited")
|
||||||
|
|
||||||
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type Reloader struct {
|
// Credit: https://drailing.net/2018/01/debounce-function-for-golang/
|
||||||
|
func debounce(interval time.Duration, input chan fsnotify.Event, quitChannel chan bool, cb func(arg fsnotify.Event)) {
|
||||||
// Main context
|
var item fsnotify.Event
|
||||||
ctx context.Context
|
timer := time.NewTimer(interval)
|
||||||
|
exit:
|
||||||
// Signal context
|
|
||||||
signalContext context.Context
|
|
||||||
|
|
||||||
// notify
|
|
||||||
watcher *fsnotify.Watcher
|
|
||||||
|
|
||||||
// Logger
|
|
||||||
logger *clilogger.CLILogger
|
|
||||||
|
|
||||||
// Extensions to listen for
|
|
||||||
extensionsThatTriggerARebuild []string
|
|
||||||
|
|
||||||
// The binary we are running
|
|
||||||
binary *process.Process
|
|
||||||
|
|
||||||
// options
|
|
||||||
ldflags string
|
|
||||||
compiler string
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewReloader(logger *clilogger.CLILogger, extensionsThatTriggerARebuild []string, ldFlags string, compiler string) (*Reloader, error) {
|
|
||||||
var result Reloader
|
|
||||||
|
|
||||||
// Create context
|
|
||||||
result.ctx = context.Background()
|
|
||||||
|
|
||||||
// Signal context (we don't need cancel)
|
|
||||||
signalContext, _ := signal.NotifyContext(result.ctx, os.Interrupt, os.Kill, syscall.SIGTERM)
|
|
||||||
result.signalContext = signalContext
|
|
||||||
|
|
||||||
// Create watcher
|
|
||||||
watcher, err := fsnotify.NewWatcher()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
result.watcher = watcher
|
|
||||||
|
|
||||||
// Logger
|
|
||||||
result.logger = logger
|
|
||||||
|
|
||||||
// Extensions
|
|
||||||
result.extensionsThatTriggerARebuild = extensionsThatTriggerARebuild
|
|
||||||
|
|
||||||
// Options
|
|
||||||
result.ldflags = ldFlags
|
|
||||||
result.compiler = compiler
|
|
||||||
|
|
||||||
return &result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Reloader) Start() error {
|
|
||||||
|
|
||||||
err := r.rebuildBinary()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get project dir
|
|
||||||
dir, err := os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get all subdirectories
|
|
||||||
dirs, err := fs.GetSubdirectories(dir)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup a watcher for non-node_modules directories
|
|
||||||
r.logger.Println("Watching (sub)directories: %s", dir)
|
|
||||||
|
|
||||||
dirs.Each(func(dir string) {
|
|
||||||
if strings.Contains(dir, "node_modules") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = r.watcher.Add(dir)
|
|
||||||
if err != nil {
|
|
||||||
r.logger.Fatal(err.Error())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Main loop
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-r.signalContext.Done():
|
case item = <-input:
|
||||||
if r.binary != nil {
|
timer.Reset(interval)
|
||||||
println("Binary is not nil - kill")
|
case <-timer.C:
|
||||||
return r.binary.Kill()
|
if item.Name != "" {
|
||||||
}
|
cb(item)
|
||||||
return nil
|
|
||||||
case event := <-r.watcher.Events:
|
|
||||||
err := r.processWatcherEvent(event)
|
|
||||||
if err != nil {
|
|
||||||
println("error from processWatcherEvent. Calling cancel()")
|
|
||||||
println("Calling kill")
|
|
||||||
return r.binary.Kill()
|
|
||||||
}
|
}
|
||||||
|
case <-quitChannel:
|
||||||
|
break exit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Reloader) processWatcherEvent(event fsnotify.Event) error {
|
func restartApp(logger *clilogger.CLILogger, outputType string, ldflags string, compilerCommand string, debugBinaryProcess *process.Process, loglevel string) (*process.Process, error) {
|
||||||
|
|
||||||
// Check for new directories
|
appBinary, err := buildApp(logger, outputType, ldflags, compilerCommand)
|
||||||
if event.Op&fsnotify.Create == fsnotify.Create {
|
println()
|
||||||
// If this is a folder, add it to our watch list
|
|
||||||
if fs.DirExists(event.Name) {
|
|
||||||
if !strings.Contains(event.Name, "node_modules") {
|
|
||||||
err := r.watcher.Add(event.Name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
r.logger.Println("Watching directory: %s", event.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for file writes
|
|
||||||
if event.Op&fsnotify.Write == fsnotify.Write {
|
|
||||||
|
|
||||||
var rebuild bool
|
|
||||||
|
|
||||||
// Iterate all file patterns
|
|
||||||
for _, pattern := range r.extensionsThatTriggerARebuild {
|
|
||||||
if strings.HasSuffix(event.Name, pattern) {
|
|
||||||
rebuild = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !rebuild {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
r.logger.Println("\n%s[Build triggered] %s %s", ctc.ForegroundGreen|ctc.ForegroundBright, event.Name, ctc.Reset)
|
|
||||||
|
|
||||||
return r.rebuildBinary()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Reloader) rebuildBinary() error {
|
|
||||||
|
|
||||||
// rebuild binary
|
|
||||||
binary, err := r.buildApp()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
LogRed("Build error - continuing to run current version")
|
||||||
|
LogDarkYellow(err.Error())
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kill current binary if running
|
// Kill existing binary if need be
|
||||||
if r.binary != nil {
|
if debugBinaryProcess != nil {
|
||||||
err = r.binary.Kill()
|
killError := debugBinaryProcess.Kill()
|
||||||
if err != nil {
|
|
||||||
return err
|
if killError != nil {
|
||||||
|
logger.Fatal("Unable to kill debug binary (PID: %d)!", debugBinaryProcess.PID())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debugBinaryProcess = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
newProcess := process.NewProcess(r.ctx, r.logger, binary)
|
// TODO: Generate `backend.js`
|
||||||
|
|
||||||
|
// Start up new binary
|
||||||
|
newProcess := process.NewProcess(logger, appBinary, "-loglevel", loglevel)
|
||||||
err = newProcess.Start()
|
err = newProcess.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
// Remove binary
|
||||||
|
deleteError := fs.DeleteFile(appBinary)
|
||||||
|
if deleteError != nil {
|
||||||
|
logger.Fatal("Unable to delete app binary: " + appBinary)
|
||||||
|
}
|
||||||
|
logger.Fatal("Unable to start application: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure process runs correctly
|
return newProcess, nil
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//func restartApp(logger *clilogger.CLILogger, outputType string, ldflags string, compilerCommand string, debugBinaryProcess *process.Process) (*process.Process, error) {
|
func buildApp(logger *clilogger.CLILogger, outputType string, ldflags string, compilerCommand string) (string, error) {
|
||||||
//
|
|
||||||
// appBinary, err := buildApp(logger, outputType, ldflags, compilerCommand)
|
|
||||||
// println()
|
|
||||||
// if err != nil {
|
|
||||||
// logger.Fatal(err.Error())
|
|
||||||
// return nil, errors.Wrap(err, "Build Failed:")
|
|
||||||
// }
|
|
||||||
// logger.Println("Build new binary: %s", appBinary)
|
|
||||||
//
|
|
||||||
// // Kill existing binary if need be
|
|
||||||
// if debugBinaryProcess != nil {
|
|
||||||
// killError := debugBinaryProcess.Kill()
|
|
||||||
//
|
|
||||||
// if killError != nil {
|
|
||||||
// logger.Fatal("Unable to kill debug binary (PID: %d)!", debugBinaryProcess.PID())
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// debugBinaryProcess = nil
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // TODO: Generate `backend.js`
|
|
||||||
//
|
|
||||||
// // Start up new binary
|
|
||||||
// newProcess := process.NewProcess(logger, appBinary)
|
|
||||||
// err = newProcess.Start()
|
|
||||||
// if err != nil {
|
|
||||||
// // Remove binary
|
|
||||||
// deleteError := fs.DeleteFile(appBinary)
|
|
||||||
// if deleteError != nil {
|
|
||||||
// logger.Fatal("Unable to delete app binary: " + appBinary)
|
|
||||||
// }
|
|
||||||
// logger.Fatal("Unable to start application: %s", err.Error())
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Check if port is open
|
|
||||||
// timeout := time.Second
|
|
||||||
// conn, err := net.DialTimeout("tcp", net.JoinHostPort("host", port), timeout)
|
|
||||||
// if err != nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// newProcess.Running
|
|
||||||
// return newProcess, nil
|
|
||||||
//}
|
|
||||||
|
|
||||||
// buildapp attempts to compile the application
|
|
||||||
// It returns the path to the new binary or an error
|
|
||||||
func (r *Reloader) buildApp() (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{
|
||||||
Logger: r.logger,
|
Logger: logger,
|
||||||
OutputType: "dev",
|
OutputType: outputType,
|
||||||
Mode: build.Debug,
|
Mode: build.Debug,
|
||||||
Pack: false,
|
Pack: false,
|
||||||
Platform: runtime.GOOS,
|
Platform: runtime.GOOS,
|
||||||
LDFlags: r.ldflags,
|
LDFlags: ldflags,
|
||||||
Compiler: r.compiler,
|
Compiler: compilerCommand,
|
||||||
OutputFile: outputFile,
|
OutputFile: outputFile,
|
||||||
IgnoreFrontend: true,
|
IgnoreFrontend: true,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/wzshiming/ctc"
|
"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"
|
||||||
|
|
||||||
@@ -22,20 +22,8 @@ func fatal(message string) {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func col(colour ctc.Color, text string) string {
|
func banner(_ *clir.Cli) string {
|
||||||
return fmt.Sprintf("%s%s%s", colour, text, ctc.Reset)
|
return fmt.Sprintf("%s %s - Go/HTML Application Framework", colour.Yellow("Wails"), colour.DarkRed(version))
|
||||||
}
|
|
||||||
|
|
||||||
func Yellow(str string) string {
|
|
||||||
return col(ctc.ForegroundBrightYellow, str)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Red(str string) string {
|
|
||||||
return col(ctc.ForegroundBrightRed, str)
|
|
||||||
}
|
|
||||||
|
|
||||||
func banner(cli *clir.Cli) string {
|
|
||||||
return fmt.Sprintf("%s %s - Go/HTML Application Framework", Yellow("Wails"), Red(version))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
var version = "v2.0.0-alpha.26"
|
var version = "v2.0.0-alpha.37"
|
||||||
|
|||||||
@@ -20,10 +20,9 @@ require (
|
|||||||
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 // 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/sync v0.0.0-20201207232520-09787c993a3a
|
|
||||||
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
|
||||||
nhooyr.io/websocket v1.8.6
|
nhooyr.io/websocket v1.8.6
|
||||||
|
|||||||
@@ -96,8 +96,6 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up
|
|||||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
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/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs=
|
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/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/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
|||||||
@@ -20,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":
|
||||||
|
|||||||
@@ -117,14 +117,6 @@ func (a *App) Run() error {
|
|||||||
parentContext := context.WithValue(context.Background(), "waitgroup", &subsystemWaitGroup)
|
parentContext := context.WithValue(context.Background(), "waitgroup", &subsystemWaitGroup)
|
||||||
ctx, cancel := context.WithCancel(parentContext)
|
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
|
// Start the service bus
|
||||||
a.servicebus.Debug()
|
a.servicebus.Debug()
|
||||||
err = a.servicebus.Start()
|
err = a.servicebus.Start()
|
||||||
@@ -132,7 +124,7 @@ func (a *App) Run() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
runtimesubsystem, err := subsystem.NewRuntime(ctx, a.servicebus, a.logger, a.startupCallback, a.shutdownCallback)
|
runtimesubsystem, err := subsystem.NewRuntime(ctx, a.servicebus, a.logger, a.startupCallback)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -207,6 +199,14 @@ func (a *App) Run() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup signal handler
|
||||||
|
signalsubsystem, err := signal.NewManager(ctx, cancel, a.servicebus, a.logger)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
a.signal = signalsubsystem
|
||||||
|
a.signal.Start()
|
||||||
|
|
||||||
err = a.window.Run(dispatcher, bindingDump, a.debug)
|
err = a.window.Run(dispatcher, bindingDump, a.debug)
|
||||||
a.logger.Trace("Ffenestri.Run() exited")
|
a.logger.Trace("Ffenestri.Run() exited")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -231,5 +231,10 @@ func (a *App) Run() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shutdown callback
|
||||||
|
if a.shutdownCallback != nil {
|
||||||
|
a.shutdownCallback()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,6 @@ func CreateApp(appoptions *options.App) (*App, error) {
|
|||||||
|
|
||||||
// Set up logger
|
// Set up logger
|
||||||
myLogger := logger.New(appoptions.Logger)
|
myLogger := logger.New(appoptions.Logger)
|
||||||
myLogger.SetLogLevel(appoptions.LogLevel)
|
|
||||||
|
|
||||||
// Create the menu manager
|
// Create the menu manager
|
||||||
menuManager := menumanager.NewManager()
|
menuManager := menumanager.NewManager()
|
||||||
@@ -119,14 +118,6 @@ func (a *App) Run() error {
|
|||||||
parentContext := context.WithValue(context.Background(), "waitgroup", &subsystemWaitGroup)
|
parentContext := context.WithValue(context.Background(), "waitgroup", &subsystemWaitGroup)
|
||||||
ctx, cancel := context.WithCancel(parentContext)
|
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
|
// Start the service bus
|
||||||
a.servicebus.Debug()
|
a.servicebus.Debug()
|
||||||
err = a.servicebus.Start()
|
err = a.servicebus.Start()
|
||||||
@@ -134,7 +125,7 @@ func (a *App) Run() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
runtimesubsystem, err := subsystem.NewRuntime(ctx, a.servicebus, a.logger, a.startupCallback, a.shutdownCallback)
|
runtimesubsystem, err := subsystem.NewRuntime(ctx, a.servicebus, a.logger, a.startupCallback)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -212,6 +203,14 @@ func (a *App) Run() error {
|
|||||||
// Generate backend.js
|
// Generate backend.js
|
||||||
a.bindings.GenerateBackendJS()
|
a.bindings.GenerateBackendJS()
|
||||||
|
|
||||||
|
// Setup signal handler
|
||||||
|
signalsubsystem, err := signal.NewManager(ctx, cancel, a.servicebus, a.logger)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
a.signal = signalsubsystem
|
||||||
|
a.signal.Start()
|
||||||
|
|
||||||
err = a.bridge.Run(dispatcher, a.menuManager, bindingDump, a.debug)
|
err = a.bridge.Run(dispatcher, a.menuManager, bindingDump, a.debug)
|
||||||
a.logger.Trace("Bridge.Run() exited")
|
a.logger.Trace("Bridge.Run() exited")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -236,6 +235,10 @@ func (a *App) Run() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shutdown callback
|
||||||
|
if a.shutdownCallback != nil {
|
||||||
|
a.shutdownCallback()
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ const backend = {`)
|
|||||||
sortedPackageNames.Add(packageName)
|
sortedPackageNames.Add(packageName)
|
||||||
}
|
}
|
||||||
sortedPackageNames.Sort()
|
sortedPackageNames.Sort()
|
||||||
for _, packageName := range sortedPackageNames.AsSlice() {
|
sortedPackageNames.Each(func(packageName string) {
|
||||||
packages := store[packageName]
|
packages := store[packageName]
|
||||||
output.WriteString(fmt.Sprintf(" \"%s\": {", packageName))
|
output.WriteString(fmt.Sprintf(" \"%s\": {", packageName))
|
||||||
output.WriteString("\n")
|
output.WriteString("\n")
|
||||||
@@ -67,7 +67,8 @@ const backend = {`)
|
|||||||
sortedStructNames.Add(structName)
|
sortedStructNames.Add(structName)
|
||||||
}
|
}
|
||||||
sortedStructNames.Sort()
|
sortedStructNames.Sort()
|
||||||
for _, structName := range sortedStructNames.AsSlice() {
|
|
||||||
|
sortedStructNames.Each(func(structName string) {
|
||||||
structs := packages[structName]
|
structs := packages[structName]
|
||||||
output.WriteString(fmt.Sprintf(" \"%s\": {", structName))
|
output.WriteString(fmt.Sprintf(" \"%s\": {", structName))
|
||||||
output.WriteString("\n")
|
output.WriteString("\n")
|
||||||
@@ -78,7 +79,7 @@ const backend = {`)
|
|||||||
}
|
}
|
||||||
sortedMethodNames.Sort()
|
sortedMethodNames.Sort()
|
||||||
|
|
||||||
for _, methodName := range sortedMethodNames.AsSlice() {
|
sortedMethodNames.Each(func(methodName string) {
|
||||||
methodDetails := structs[methodName]
|
methodDetails := structs[methodName]
|
||||||
output.WriteString(" /**\n")
|
output.WriteString(" /**\n")
|
||||||
output.WriteString(" * " + methodName + "\n")
|
output.WriteString(" * " + methodName + "\n")
|
||||||
@@ -109,13 +110,16 @@ const backend = {`)
|
|||||||
output.WriteString("\n")
|
output.WriteString("\n")
|
||||||
output.WriteString(fmt.Sprintf(" },"))
|
output.WriteString(fmt.Sprintf(" },"))
|
||||||
output.WriteString("\n")
|
output.WriteString("\n")
|
||||||
}
|
|
||||||
|
})
|
||||||
|
|
||||||
output.WriteString(fmt.Sprintf(" }"))
|
output.WriteString(fmt.Sprintf(" }"))
|
||||||
output.WriteString("\n")
|
output.WriteString("\n")
|
||||||
}
|
})
|
||||||
|
|
||||||
output.WriteString(fmt.Sprintf(" }\n"))
|
output.WriteString(fmt.Sprintf(" }\n"))
|
||||||
output.WriteString("\n")
|
output.WriteString("\n")
|
||||||
}
|
})
|
||||||
|
|
||||||
output.WriteString(`};
|
output.WriteString(`};
|
||||||
export default backend;`)
|
export default backend;`)
|
||||||
|
|||||||
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()
|
||||||
|
}
|
||||||
@@ -79,6 +79,7 @@ struct Application {
|
|||||||
id mouseEvent;
|
id mouseEvent;
|
||||||
id mouseDownMonitor;
|
id mouseDownMonitor;
|
||||||
id mouseUpMonitor;
|
id mouseUpMonitor;
|
||||||
|
int activationPolicy;
|
||||||
|
|
||||||
// Window Data
|
// Window Data
|
||||||
const char *title;
|
const char *title;
|
||||||
@@ -253,7 +254,7 @@ void Hide(struct Application *app) {
|
|||||||
if( app->shuttingDown ) return;
|
if( app->shuttingDown ) return;
|
||||||
|
|
||||||
ON_MAIN_THREAD(
|
ON_MAIN_THREAD(
|
||||||
msg(app->application, s("hide:"))
|
msg(app->application, s("hide:"));
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,31 +499,6 @@ void DestroyApplication(struct Application *app) {
|
|||||||
Debug(app, "Finished Destroying Application");
|
Debug(app, "Finished Destroying Application");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quit will stop the cocoa application and free up all the memory
|
|
||||||
// used by the application
|
|
||||||
void Quit(struct Application *app) {
|
|
||||||
Debug(app, "Quit Called");
|
|
||||||
ON_MAIN_THREAD (
|
|
||||||
// Terminate app
|
|
||||||
msg(app->application, s("stop:"), NULL);
|
|
||||||
id fakeevent = msg(c("NSEvent"),
|
|
||||||
s("otherEventWithType:location:modifierFlags:timestamp:windowNumber:context:subtype:data1:data2:"),
|
|
||||||
15, // Type
|
|
||||||
msg(c("CGPoint"), s("init:x:y:"), 0, 0), // location
|
|
||||||
0, // flags
|
|
||||||
0, // timestamp
|
|
||||||
0, // window
|
|
||||||
NULL, // context
|
|
||||||
0, // subtype
|
|
||||||
0, // data1
|
|
||||||
0 // data2
|
|
||||||
);
|
|
||||||
msg(c("NSApp"), s("postEvent:atStart:"), fakeevent, true);
|
|
||||||
// msg(c(app->mainWindow), s("performClose:"))
|
|
||||||
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetTitle sets the main window title to the given string
|
// SetTitle sets the main window title to the given string
|
||||||
void SetTitle(struct Application *app, const char *title) {
|
void SetTitle(struct Application *app, const char *title) {
|
||||||
// Guard against calling during shutdown
|
// Guard against calling during shutdown
|
||||||
@@ -1137,7 +1113,7 @@ void processDecorations(struct Application *app) {
|
|||||||
void createApplication(struct Application *app) {
|
void createApplication(struct Application *app) {
|
||||||
id application = msg(c("NSApplication"), s("sharedApplication"));
|
id application = msg(c("NSApplication"), s("sharedApplication"));
|
||||||
app->application = application;
|
app->application = application;
|
||||||
msg(application, s("setActivationPolicy:"), 0);
|
msg(application, s("setActivationPolicy:"), app->activationPolicy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DarkModeEnabled(struct Application *app, const char *callbackID) {
|
void DarkModeEnabled(struct Application *app, const char *callbackID) {
|
||||||
@@ -1837,6 +1813,19 @@ void Run(struct Application *app, int argc, char **argv) {
|
|||||||
MEMFREE(internalCode);
|
MEMFREE(internalCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetActivationPolicy(struct Application* app, int policy) {
|
||||||
|
app->activationPolicy = policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quit will stop the cocoa application and free up all the memory
|
||||||
|
// used by the application
|
||||||
|
void Quit(struct Application *app) {
|
||||||
|
Debug(app, "Quit Called");
|
||||||
|
msg(app->application, s("stop:"), NULL);
|
||||||
|
SetSize(app, 0, 0);
|
||||||
|
Show(app);
|
||||||
|
Hide(app);
|
||||||
|
}
|
||||||
|
|
||||||
void* NewApplication(const char *title, int width, int height, int resizable, int devtools, int fullscreen, int startHidden, int logLevel, int hideWindowOnClose) {
|
void* NewApplication(const char *title, int width, int height, int resizable, int devtools, int fullscreen, int startHidden, int logLevel, int hideWindowOnClose) {
|
||||||
|
|
||||||
@@ -1899,6 +1888,8 @@ void* NewApplication(const char *title, int width, int height, int resizable, in
|
|||||||
|
|
||||||
result->shuttingDown = false;
|
result->shuttingDown = false;
|
||||||
|
|
||||||
|
result->activationPolicy = NSApplicationActivationPolicyRegular;
|
||||||
|
|
||||||
return (void*) result;
|
return (void*) result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ func (a *Application) processPlatformSettings() error {
|
|||||||
C.SetAppearance(a.app, a.string2CString(string(mac.Appearance)))
|
C.SetAppearance(a.app, a.string2CString(string(mac.Appearance)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set activation policy
|
||||||
|
C.SetActivationPolicy(a.app, C.int(mac.ActivationPolicy))
|
||||||
|
|
||||||
// Check if the webview should be transparent
|
// Check if the webview should be transparent
|
||||||
if mac.WebviewIsTransparent {
|
if mac.WebviewIsTransparent {
|
||||||
C.WebviewIsTransparent(a.app)
|
C.WebviewIsTransparent(a.app)
|
||||||
|
|||||||
@@ -66,6 +66,10 @@
|
|||||||
#define NSControlStateValueOff 0
|
#define NSControlStateValueOff 0
|
||||||
#define NSControlStateValueOn 1
|
#define NSControlStateValueOn 1
|
||||||
|
|
||||||
|
#define NSApplicationActivationPolicyRegular 0
|
||||||
|
#define NSApplicationActivationPolicyAccessory 1
|
||||||
|
#define NSApplicationActivationPolicyProhibited 2
|
||||||
|
|
||||||
// Unbelievably, if the user swaps their button preference
|
// Unbelievably, if the user swaps their button preference
|
||||||
// then right buttons are reported as left buttons
|
// then right buttons are reported as left buttons
|
||||||
#define NSEventMaskLeftMouseDown 1 << 1
|
#define NSEventMaskLeftMouseDown 1 << 1
|
||||||
@@ -110,6 +114,8 @@ void SetTray(struct Application* app, const char *, const char *, const char *);
|
|||||||
//void SetContextMenus(struct Application* app, const char *);
|
//void SetContextMenus(struct Application* app, const char *);
|
||||||
void AddTrayMenu(struct Application* app, const char *);
|
void AddTrayMenu(struct Application* app, const char *);
|
||||||
|
|
||||||
|
void SetActivationPolicy(struct Application* app, int policy);
|
||||||
|
|
||||||
void* lookupStringConstant(id constantName);
|
void* lookupStringConstant(id constantName);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,20 +508,21 @@ unsigned long parseModifiers(const char **modifiers) {
|
|||||||
const char *thisModifier = modifiers[0];
|
const char *thisModifier = modifiers[0];
|
||||||
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, "ctrl") ) {
|
||||||
result |= NSEventModifierFlagControl;
|
result |= NSEventModifierFlagControl;
|
||||||
}
|
}
|
||||||
count++;
|
count++;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package process
|
package process
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
@@ -10,16 +9,18 @@ import (
|
|||||||
|
|
||||||
// Process defines a process that can be executed
|
// Process defines a process that can be executed
|
||||||
type Process struct {
|
type Process struct {
|
||||||
logger *clilogger.CLILogger
|
logger *clilogger.CLILogger
|
||||||
cmd *exec.Cmd
|
cmd *exec.Cmd
|
||||||
running bool
|
exitChannel chan bool
|
||||||
|
Running bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewProcess creates a new process struct
|
// NewProcess creates a new process struct
|
||||||
func NewProcess(ctx context.Context, logger *clilogger.CLILogger, cmd string, args ...string) *Process {
|
func NewProcess(logger *clilogger.CLILogger, cmd string, args ...string) *Process {
|
||||||
result := &Process{
|
result := &Process{
|
||||||
logger: logger,
|
logger: logger,
|
||||||
cmd: exec.CommandContext(ctx, cmd, args...),
|
cmd: exec.Command(cmd, args...),
|
||||||
|
exitChannel: make(chan bool, 1),
|
||||||
}
|
}
|
||||||
result.cmd.Stdout = os.Stdout
|
result.cmd.Stdout = os.Stdout
|
||||||
result.cmd.Stderr = os.Stderr
|
result.cmd.Stderr = os.Stderr
|
||||||
@@ -34,30 +35,35 @@ func (p *Process) Start() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
p.running = true
|
p.Running = true
|
||||||
|
|
||||||
go func(p *Process) {
|
go func(cmd *exec.Cmd, running *bool, logger *clilogger.CLILogger, exitChannel chan bool) {
|
||||||
p.logger.Println("Starting process (PID: %d)", p.cmd.Process.Pid)
|
logger.Println("Starting process (PID: %d)", cmd.Process.Pid)
|
||||||
err := p.cmd.Wait()
|
err := cmd.Wait()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.running = false
|
if err.Error() != "signal: killed" {
|
||||||
p.logger.Println("Process failed to run: %s", err.Error())
|
logger.Fatal("Fatal error from app: " + err.Error())
|
||||||
return
|
}
|
||||||
}
|
}
|
||||||
p.logger.Println("Exiting process (PID: %d)", p.cmd.Process.Pid)
|
logger.Println("Exiting process (PID: %d)", cmd.Process.Pid)
|
||||||
}(p)
|
*running = false
|
||||||
|
exitChannel <- true
|
||||||
|
}(p.cmd, &p.Running, p.logger, p.exitChannel)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kill the process
|
// Kill the process
|
||||||
func (p *Process) Kill() error {
|
func (p *Process) Kill() error {
|
||||||
if p.running {
|
if !p.Running {
|
||||||
println("Calling kill")
|
return nil
|
||||||
p.running = false
|
|
||||||
return p.cmd.Process.Kill()
|
|
||||||
}
|
}
|
||||||
return nil
|
err := p.cmd.Process.Kill()
|
||||||
|
|
||||||
|
// Wait for command to exit properly
|
||||||
|
<-p.exitChannel
|
||||||
|
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// PID returns the process PID
|
// PID returns the process PID
|
||||||
|
|||||||
@@ -620,7 +620,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Menubar **/
|
/** Menubar **/
|
||||||
const menuVisible = writable(true);
|
const menuVisible = writable(false);
|
||||||
|
|
||||||
/** Trays **/
|
/** Trays **/
|
||||||
|
|
||||||
@@ -779,18 +779,18 @@
|
|||||||
|
|
||||||
function add_css$1() {
|
function add_css$1() {
|
||||||
var style = element("style");
|
var style = element("style");
|
||||||
style.id = "svelte-1ucacnf-style";
|
style.id = "svelte-1oysp7o-style";
|
||||||
style.textContent = ".menu.svelte-1ucacnf.svelte-1ucacnf{padding:5px;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.svelte-1ucacnf.svelte-1ucacnf{display:flex;align-items:center;padding:1px 5px}.menuitem.svelte-1ucacnf.svelte-1ucacnf:hover{display:flex;align-items:center;background-color:rgb(57,131,223);padding:1px 5px;border-radius:5px}.menuitem.svelte-1ucacnf img.svelte-1ucacnf{padding-right:5px}.separator.svelte-1ucacnf.svelte-1ucacnf{padding-top:5px;width:100%;padding-bottom:5px}.separator.svelte-1ucacnf.svelte-1ucacnf:hover{background-color:#0000}";
|
style.textContent = ".menu.svelte-1oysp7o.svelte-1oysp7o{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.svelte-1oysp7o.svelte-1oysp7o{display:flex;align-items:center;padding:1px 5px}.menuitem.svelte-1oysp7o.svelte-1oysp7o:hover{display:flex;align-items:center;background-color:rgb(57,131,223);padding:1px 5px;border-radius:5px}.menuitem.svelte-1oysp7o img.svelte-1oysp7o{padding-right:5px}";
|
||||||
append(document.head, style);
|
append(document.head, style);
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_each_context(ctx, list, i) {
|
function get_each_context(ctx, list, i) {
|
||||||
const child_ctx = ctx.slice();
|
const child_ctx = ctx.slice();
|
||||||
child_ctx[3] = list[i];
|
child_ctx[2] = list[i];
|
||||||
return child_ctx;
|
return child_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
// (14:0) {#if visible}
|
// (8:0) {#if !hidden}
|
||||||
function create_if_block$1(ctx) {
|
function create_if_block$1(ctx) {
|
||||||
let div;
|
let div;
|
||||||
let if_block = /*menu*/ ctx[0].Menu && create_if_block_1(ctx);
|
let if_block = /*menu*/ ctx[0].Menu && create_if_block_1(ctx);
|
||||||
@@ -799,7 +799,7 @@
|
|||||||
c() {
|
c() {
|
||||||
div = element("div");
|
div = element("div");
|
||||||
if (if_block) if_block.c();
|
if (if_block) if_block.c();
|
||||||
attr(div, "class", "menu svelte-1ucacnf");
|
attr(div, "class", "menu svelte-1oysp7o");
|
||||||
},
|
},
|
||||||
m(target, anchor) {
|
m(target, anchor) {
|
||||||
insert(target, div, anchor);
|
insert(target, div, anchor);
|
||||||
@@ -826,7 +826,7 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// (16:4) {#if menu.Menu }
|
// (10:4) {#if menu.Menu }
|
||||||
function create_if_block_1(ctx) {
|
function create_if_block_1(ctx) {
|
||||||
let each_1_anchor;
|
let each_1_anchor;
|
||||||
let each_value = /*menu*/ ctx[0].Menu.Items;
|
let each_value = /*menu*/ ctx[0].Menu.Items;
|
||||||
@@ -852,7 +852,7 @@
|
|||||||
insert(target, each_1_anchor, anchor);
|
insert(target, each_1_anchor, anchor);
|
||||||
},
|
},
|
||||||
p(ctx, dirty) {
|
p(ctx, dirty) {
|
||||||
if (dirty & /*click, menu*/ 1) {
|
if (dirty & /*menu*/ 1) {
|
||||||
each_value = /*menu*/ ctx[0].Menu.Items;
|
each_value = /*menu*/ ctx[0].Menu.Items;
|
||||||
let i;
|
let i;
|
||||||
|
|
||||||
@@ -882,41 +882,44 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// (25:52)
|
// (13:12) {#if menuItem.Image }
|
||||||
function create_if_block_4(ctx) {
|
function create_if_block_2(ctx) {
|
||||||
let div;
|
let div;
|
||||||
|
let img;
|
||||||
|
let img_src_value;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
c() {
|
c() {
|
||||||
div = element("div");
|
div = element("div");
|
||||||
div.innerHTML = `<hr/>`;
|
img = element("img");
|
||||||
attr(div, "class", "separator svelte-1ucacnf");
|
attr(img, "alt", "");
|
||||||
|
if (img.src !== (img_src_value = "data:image/png;base64," + /*menuItem*/ ctx[2].Image)) attr(img, "src", img_src_value);
|
||||||
|
attr(img, "class", "svelte-1oysp7o");
|
||||||
},
|
},
|
||||||
m(target, anchor) {
|
m(target, anchor) {
|
||||||
insert(target, div, anchor);
|
insert(target, div, anchor);
|
||||||
|
append(div, img);
|
||||||
|
},
|
||||||
|
p(ctx, dirty) {
|
||||||
|
if (dirty & /*menu*/ 1 && img.src !== (img_src_value = "data:image/png;base64," + /*menuItem*/ ctx[2].Image)) {
|
||||||
|
attr(img, "src", img_src_value);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
p: noop,
|
|
||||||
d(detaching) {
|
d(detaching) {
|
||||||
if (detaching) detach(div);
|
if (detaching) detach(div);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// (18:12) {#if menuItem.Type === "Text" }
|
// (11:8) {#each menu.Menu.Items as menuItem}
|
||||||
function create_if_block_2(ctx) {
|
function create_each_block(ctx) {
|
||||||
let div1;
|
let div1;
|
||||||
let t0;
|
let t0;
|
||||||
let div0;
|
let div0;
|
||||||
let t1_value = /*menuItem*/ ctx[3].Label + "";
|
let t1_value = /*menuItem*/ ctx[2].Label + "";
|
||||||
let t1;
|
let t1;
|
||||||
let t2;
|
let t2;
|
||||||
let mounted;
|
let if_block = /*menuItem*/ ctx[2].Image && create_if_block_2(ctx);
|
||||||
let dispose;
|
|
||||||
let if_block = /*menuItem*/ ctx[3].Image && create_if_block_3(ctx);
|
|
||||||
|
|
||||||
function click_handler() {
|
|
||||||
return /*click_handler*/ ctx[2](/*menuItem*/ ctx[3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
c() {
|
c() {
|
||||||
@@ -927,7 +930,7 @@
|
|||||||
t1 = text(t1_value);
|
t1 = text(t1_value);
|
||||||
t2 = space();
|
t2 = space();
|
||||||
attr(div0, "class", "menulabel");
|
attr(div0, "class", "menulabel");
|
||||||
attr(div1, "class", "menuitem svelte-1ucacnf");
|
attr(div1, "class", "menuitem svelte-1oysp7o");
|
||||||
},
|
},
|
||||||
m(target, anchor) {
|
m(target, anchor) {
|
||||||
insert(target, div1, anchor);
|
insert(target, div1, anchor);
|
||||||
@@ -936,20 +939,13 @@
|
|||||||
append(div1, div0);
|
append(div1, div0);
|
||||||
append(div0, t1);
|
append(div0, t1);
|
||||||
append(div1, t2);
|
append(div1, t2);
|
||||||
|
|
||||||
if (!mounted) {
|
|
||||||
dispose = listen(div1, "click", click_handler);
|
|
||||||
mounted = true;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
p(new_ctx, dirty) {
|
p(ctx, dirty) {
|
||||||
ctx = new_ctx;
|
if (/*menuItem*/ ctx[2].Image) {
|
||||||
|
|
||||||
if (/*menuItem*/ ctx[3].Image) {
|
|
||||||
if (if_block) {
|
if (if_block) {
|
||||||
if_block.p(ctx, dirty);
|
if_block.p(ctx, dirty);
|
||||||
} else {
|
} else {
|
||||||
if_block = create_if_block_3(ctx);
|
if_block = create_if_block_2(ctx);
|
||||||
if_block.c();
|
if_block.c();
|
||||||
if_block.m(div1, t0);
|
if_block.m(div1, t0);
|
||||||
}
|
}
|
||||||
@@ -958,93 +954,18 @@
|
|||||||
if_block = null;
|
if_block = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dirty & /*menu*/ 1 && t1_value !== (t1_value = /*menuItem*/ ctx[3].Label + "")) set_data(t1, t1_value);
|
if (dirty & /*menu*/ 1 && t1_value !== (t1_value = /*menuItem*/ ctx[2].Label + "")) set_data(t1, t1_value);
|
||||||
},
|
},
|
||||||
d(detaching) {
|
d(detaching) {
|
||||||
if (detaching) detach(div1);
|
if (detaching) detach(div1);
|
||||||
if (if_block) if_block.d();
|
if (if_block) if_block.d();
|
||||||
mounted = false;
|
|
||||||
dispose();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// (20:12) {#if menuItem.Image }
|
|
||||||
function create_if_block_3(ctx) {
|
|
||||||
let div;
|
|
||||||
let img;
|
|
||||||
let img_src_value;
|
|
||||||
|
|
||||||
return {
|
|
||||||
c() {
|
|
||||||
div = element("div");
|
|
||||||
img = element("img");
|
|
||||||
attr(img, "alt", "");
|
|
||||||
if (img.src !== (img_src_value = "data:image/png;base64," + /*menuItem*/ ctx[3].Image)) attr(img, "src", img_src_value);
|
|
||||||
attr(img, "class", "svelte-1ucacnf");
|
|
||||||
},
|
|
||||||
m(target, anchor) {
|
|
||||||
insert(target, div, anchor);
|
|
||||||
append(div, img);
|
|
||||||
},
|
|
||||||
p(ctx, dirty) {
|
|
||||||
if (dirty & /*menu*/ 1 && img.src !== (img_src_value = "data:image/png;base64," + /*menuItem*/ ctx[3].Image)) {
|
|
||||||
attr(img, "src", img_src_value);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
d(detaching) {
|
|
||||||
if (detaching) detach(div);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// (17:8) {#each menu.Menu.Items as menuItem}
|
|
||||||
function create_each_block(ctx) {
|
|
||||||
let if_block_anchor;
|
|
||||||
|
|
||||||
function select_block_type(ctx, dirty) {
|
|
||||||
if (/*menuItem*/ ctx[3].Type === "Text") return create_if_block_2;
|
|
||||||
if (/*menuItem*/ ctx[3].Type === "Separator") return create_if_block_4;
|
|
||||||
}
|
|
||||||
|
|
||||||
let current_block_type = select_block_type(ctx);
|
|
||||||
let if_block = current_block_type && current_block_type(ctx);
|
|
||||||
|
|
||||||
return {
|
|
||||||
c() {
|
|
||||||
if (if_block) if_block.c();
|
|
||||||
if_block_anchor = empty();
|
|
||||||
},
|
|
||||||
m(target, anchor) {
|
|
||||||
if (if_block) if_block.m(target, anchor);
|
|
||||||
insert(target, if_block_anchor, anchor);
|
|
||||||
},
|
|
||||||
p(ctx, dirty) {
|
|
||||||
if (current_block_type === (current_block_type = select_block_type(ctx)) && if_block) {
|
|
||||||
if_block.p(ctx, dirty);
|
|
||||||
} else {
|
|
||||||
if (if_block) if_block.d(1);
|
|
||||||
if_block = current_block_type && current_block_type(ctx);
|
|
||||||
|
|
||||||
if (if_block) {
|
|
||||||
if_block.c();
|
|
||||||
if_block.m(if_block_anchor.parentNode, if_block_anchor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
d(detaching) {
|
|
||||||
if (if_block) {
|
|
||||||
if_block.d(detaching);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (detaching) detach(if_block_anchor);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function create_fragment$1(ctx) {
|
function create_fragment$1(ctx) {
|
||||||
let if_block_anchor;
|
let if_block_anchor;
|
||||||
let if_block = /*visible*/ ctx[1] && create_if_block$1(ctx);
|
let if_block = !/*hidden*/ ctx[1] && create_if_block$1(ctx);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
c() {
|
c() {
|
||||||
@@ -1056,7 +977,7 @@
|
|||||||
insert(target, if_block_anchor, anchor);
|
insert(target, if_block_anchor, anchor);
|
||||||
},
|
},
|
||||||
p(ctx, [dirty]) {
|
p(ctx, [dirty]) {
|
||||||
if (/*visible*/ ctx[1]) {
|
if (!/*hidden*/ ctx[1]) {
|
||||||
if (if_block) {
|
if (if_block) {
|
||||||
if_block.p(ctx, dirty);
|
if_block.p(ctx, dirty);
|
||||||
} else {
|
} else {
|
||||||
@@ -1078,29 +999,23 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function click(id) {
|
|
||||||
console.log("MenuItem", id, "pressed");
|
|
||||||
}
|
|
||||||
|
|
||||||
function instance$1($$self, $$props, $$invalidate) {
|
function instance$1($$self, $$props, $$invalidate) {
|
||||||
let { menu } = $$props;
|
let { menu } = $$props;
|
||||||
console.log({ menu });
|
let { hidden = true } = $$props;
|
||||||
let { visible = false } = $$props;
|
|
||||||
const click_handler = menuItem => click(menuItem.ID);
|
|
||||||
|
|
||||||
$$self.$$set = $$props => {
|
$$self.$$set = $$props => {
|
||||||
if ("menu" in $$props) $$invalidate(0, menu = $$props.menu);
|
if ("menu" in $$props) $$invalidate(0, menu = $$props.menu);
|
||||||
if ("visible" in $$props) $$invalidate(1, visible = $$props.visible);
|
if ("hidden" in $$props) $$invalidate(1, hidden = $$props.hidden);
|
||||||
};
|
};
|
||||||
|
|
||||||
return [menu, visible, click_handler];
|
return [menu, hidden];
|
||||||
}
|
}
|
||||||
|
|
||||||
class Menu extends SvelteComponent {
|
class Menu extends SvelteComponent {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
super();
|
super();
|
||||||
if (!document.getElementById("svelte-1ucacnf-style")) add_css$1();
|
if (!document.getElementById("svelte-1oysp7o-style")) add_css$1();
|
||||||
init(this, options, instance$1, create_fragment$1, safe_not_equal, { menu: 0, visible: 1 });
|
init(this, options, instance$1, create_fragment$1, safe_not_equal, { menu: 0, hidden: 1 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1115,7 +1030,7 @@
|
|||||||
append(document_1.head, style);
|
append(document_1.head, style);
|
||||||
}
|
}
|
||||||
|
|
||||||
// (48:4) {#if tray.ProcessedMenu }
|
// (47:4) {#if tray.ProcessedMenu }
|
||||||
function create_if_block$2(ctx) {
|
function create_if_block$2(ctx) {
|
||||||
let menu;
|
let menu;
|
||||||
let current;
|
let current;
|
||||||
@@ -1123,7 +1038,7 @@
|
|||||||
menu = new Menu({
|
menu = new Menu({
|
||||||
props: {
|
props: {
|
||||||
menu: /*tray*/ ctx[0].ProcessedMenu,
|
menu: /*tray*/ ctx[0].ProcessedMenu,
|
||||||
visible: /*visible*/ ctx[1]
|
hidden: /*hidden*/ ctx[1]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1138,7 +1053,7 @@
|
|||||||
p(ctx, dirty) {
|
p(ctx, dirty) {
|
||||||
const menu_changes = {};
|
const menu_changes = {};
|
||||||
if (dirty & /*tray*/ 1) menu_changes.menu = /*tray*/ ctx[0].ProcessedMenu;
|
if (dirty & /*tray*/ 1) menu_changes.menu = /*tray*/ ctx[0].ProcessedMenu;
|
||||||
if (dirty & /*visible*/ 2) menu_changes.visible = /*visible*/ ctx[1];
|
if (dirty & /*hidden*/ 2) menu_changes.hidden = /*hidden*/ ctx[1];
|
||||||
menu.$set(menu_changes);
|
menu.$set(menu_changes);
|
||||||
},
|
},
|
||||||
i(local) {
|
i(local) {
|
||||||
@@ -1242,7 +1157,6 @@
|
|||||||
function clickOutside(node) {
|
function clickOutside(node) {
|
||||||
const handleClick = event => {
|
const handleClick = event => {
|
||||||
if (node && !node.contains(event.target) && !event.defaultPrevented) {
|
if (node && !node.contains(event.target) && !event.defaultPrevented) {
|
||||||
console.log("click outside of node");
|
|
||||||
node.dispatchEvent(new CustomEvent("click_outside", node));
|
node.dispatchEvent(new CustomEvent("click_outside", node));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1257,7 +1171,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function instance$2($$self, $$props, $$invalidate) {
|
function instance$2($$self, $$props, $$invalidate) {
|
||||||
let visible;
|
let hidden;
|
||||||
let $selectedMenu;
|
let $selectedMenu;
|
||||||
component_subscribe($$self, selectedMenu, $$value => $$invalidate(4, $selectedMenu = $$value));
|
component_subscribe($$self, selectedMenu, $$value => $$invalidate(4, $selectedMenu = $$value));
|
||||||
let { tray = null } = $$props;
|
let { tray = null } = $$props;
|
||||||
@@ -1280,11 +1194,11 @@
|
|||||||
|
|
||||||
$$self.$$.update = () => {
|
$$self.$$.update = () => {
|
||||||
if ($$self.$$.dirty & /*$selectedMenu, tray*/ 17) {
|
if ($$self.$$.dirty & /*$selectedMenu, tray*/ 17) {
|
||||||
$$invalidate(1, visible = $selectedMenu === tray);
|
$$invalidate(1, hidden = $selectedMenu !== tray);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return [tray, visible, closeMenu, trayClicked, $selectedMenu];
|
return [tray, hidden, closeMenu, trayClicked, $selectedMenu];
|
||||||
}
|
}
|
||||||
|
|
||||||
class TrayMenu extends SvelteComponent {
|
class TrayMenu extends SvelteComponent {
|
||||||
@@ -1306,11 +1220,11 @@
|
|||||||
|
|
||||||
function get_each_context$1(ctx, list, i) {
|
function get_each_context$1(ctx, list, i) {
|
||||||
const child_ctx = ctx.slice();
|
const child_ctx = ctx.slice();
|
||||||
child_ctx[8] = list[i];
|
child_ctx[9] = list[i];
|
||||||
return child_ctx;
|
return child_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
// (29:0) {#if $menuVisible }
|
// (38:0) {#if $menuVisible }
|
||||||
function create_if_block$3(ctx) {
|
function create_if_block$3(ctx) {
|
||||||
let div;
|
let div;
|
||||||
let span1;
|
let span1;
|
||||||
@@ -1422,11 +1336,11 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// (32:4) {#each $trays as tray}
|
// (41:4) {#each $trays as tray}
|
||||||
function create_each_block$1(ctx) {
|
function create_each_block$1(ctx) {
|
||||||
let traymenu;
|
let traymenu;
|
||||||
let current;
|
let current;
|
||||||
traymenu = new TrayMenu({ props: { tray: /*tray*/ ctx[8] } });
|
traymenu = new TrayMenu({ props: { tray: /*tray*/ ctx[9] } });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
c() {
|
c() {
|
||||||
@@ -1438,7 +1352,7 @@
|
|||||||
},
|
},
|
||||||
p(ctx, dirty) {
|
p(ctx, dirty) {
|
||||||
const traymenu_changes = {};
|
const traymenu_changes = {};
|
||||||
if (dirty & /*$trays*/ 4) traymenu_changes.tray = /*tray*/ ctx[8];
|
if (dirty & /*$trays*/ 4) traymenu_changes.tray = /*tray*/ ctx[9];
|
||||||
traymenu.$set(traymenu_changes);
|
traymenu.$set(traymenu_changes);
|
||||||
},
|
},
|
||||||
i(local) {
|
i(local) {
|
||||||
@@ -1459,6 +1373,8 @@
|
|||||||
function create_fragment$3(ctx) {
|
function create_fragment$3(ctx) {
|
||||||
let if_block_anchor;
|
let if_block_anchor;
|
||||||
let current;
|
let current;
|
||||||
|
let mounted;
|
||||||
|
let dispose;
|
||||||
let if_block = /*$menuVisible*/ ctx[1] && create_if_block$3(ctx);
|
let if_block = /*$menuVisible*/ ctx[1] && create_if_block$3(ctx);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -1470,6 +1386,11 @@
|
|||||||
if (if_block) if_block.m(target, anchor);
|
if (if_block) if_block.m(target, anchor);
|
||||||
insert(target, if_block_anchor, anchor);
|
insert(target, if_block_anchor, anchor);
|
||||||
current = true;
|
current = true;
|
||||||
|
|
||||||
|
if (!mounted) {
|
||||||
|
dispose = listen(window, "keydown", /*handleKeydown*/ ctx[3]);
|
||||||
|
mounted = true;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
p(ctx, [dirty]) {
|
p(ctx, [dirty]) {
|
||||||
if (/*$menuVisible*/ ctx[1]) {
|
if (/*$menuVisible*/ ctx[1]) {
|
||||||
@@ -1507,6 +1428,8 @@
|
|||||||
d(detaching) {
|
d(detaching) {
|
||||||
if (if_block) if_block.d(detaching);
|
if (if_block) if_block.d(detaching);
|
||||||
if (detaching) detach(if_block_anchor);
|
if (detaching) detach(if_block_anchor);
|
||||||
|
mounted = false;
|
||||||
|
dispose();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1526,7 +1449,7 @@
|
|||||||
onMount(() => {
|
onMount(() => {
|
||||||
const interval = setInterval(
|
const interval = setInterval(
|
||||||
() => {
|
() => {
|
||||||
$$invalidate(3, time = new Date());
|
$$invalidate(4, time = new Date());
|
||||||
},
|
},
|
||||||
1000
|
1000
|
||||||
);
|
);
|
||||||
@@ -1536,33 +1459,52 @@
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function handleKeydown(e) {
|
||||||
|
// Backtick toggle
|
||||||
|
if (e.keyCode == 192) {
|
||||||
|
menuVisible.update(current => {
|
||||||
|
return !current;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$$self.$$.update = () => {
|
$$self.$$.update = () => {
|
||||||
if ($$self.$$.dirty & /*time*/ 8) {
|
if ($$self.$$.dirty & /*time*/ 16) {
|
||||||
$$invalidate(4, day = time.toLocaleString("default", { weekday: "short" }));
|
$$invalidate(5, day = time.toLocaleString("default", { weekday: "short" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($$self.$$.dirty & /*time*/ 8) {
|
if ($$self.$$.dirty & /*time*/ 16) {
|
||||||
$$invalidate(5, dom = time.getDate());
|
$$invalidate(6, dom = time.getDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($$self.$$.dirty & /*time*/ 8) {
|
if ($$self.$$.dirty & /*time*/ 16) {
|
||||||
$$invalidate(6, mon = time.toLocaleString("default", { month: "short" }));
|
$$invalidate(7, mon = time.toLocaleString("default", { month: "short" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($$self.$$.dirty & /*time*/ 8) {
|
if ($$self.$$.dirty & /*time*/ 16) {
|
||||||
$$invalidate(7, currentTime = time.toLocaleString("en-US", {
|
$$invalidate(8, currentTime = time.toLocaleString("en-US", {
|
||||||
hour: "numeric",
|
hour: "numeric",
|
||||||
minute: "numeric",
|
minute: "numeric",
|
||||||
hour12: true
|
hour12: true
|
||||||
}).toLowerCase());
|
}).toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($$self.$$.dirty & /*day, dom, mon, currentTime*/ 240) {
|
if ($$self.$$.dirty & /*day, dom, mon, currentTime*/ 480) {
|
||||||
$$invalidate(0, dateTimeString = `${day} ${dom} ${mon} ${currentTime}`);
|
$$invalidate(0, dateTimeString = `${day} ${dom} ${mon} ${currentTime}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return [dateTimeString, $menuVisible, $trays, time, day, dom, mon, currentTime];
|
return [
|
||||||
|
dateTimeString,
|
||||||
|
$menuVisible,
|
||||||
|
$trays,
|
||||||
|
handleKeydown,
|
||||||
|
time,
|
||||||
|
day,
|
||||||
|
dom,
|
||||||
|
mon,
|
||||||
|
currentTime
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
class Menubar extends SvelteComponent {
|
class Menubar extends SvelteComponent {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wails/runtime",
|
"name": "@wails/runtime",
|
||||||
"version": "1.3.9",
|
"version": "1.3.10",
|
||||||
"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",
|
||||||
|
|||||||
@@ -2,29 +2,19 @@
|
|||||||
|
|
||||||
export let menu;
|
export let menu;
|
||||||
|
|
||||||
console.log({menu})
|
export let hidden = true;
|
||||||
|
|
||||||
export let visible = false;
|
|
||||||
|
|
||||||
function click(id) {
|
|
||||||
console.log("MenuItem", id, "pressed")
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if visible}
|
{#if !hidden}
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
{#if menu.Menu }
|
{#if menu.Menu }
|
||||||
{#each menu.Menu.Items as menuItem}
|
{#each menu.Menu.Items as menuItem}
|
||||||
{#if menuItem.Type === "Text" }
|
<div class="menuitem">
|
||||||
<div class="menuitem" on:click={() => click(menuItem.ID)}>
|
|
||||||
{#if menuItem.Image }
|
{#if menuItem.Image }
|
||||||
<div><img alt="" src="data:image/png;base64,{menuItem.Image}"/></div>
|
<div><img alt="" src="data:image/png;base64,{menuItem.Image}"/></div>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="menulabel">{menuItem.Label}</div>
|
<div class="menulabel">{menuItem.Label}</div>
|
||||||
</div>
|
</div>
|
||||||
{:else if menuItem.Type === "Separator"}
|
|
||||||
<div class="separator"><hr/></div>
|
|
||||||
{/if}
|
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
@@ -33,7 +23,7 @@
|
|||||||
<style>
|
<style>
|
||||||
|
|
||||||
.menu {
|
.menu {
|
||||||
padding: 5px;
|
padding: 3px;
|
||||||
background-color: #0008;
|
background-color: #0008;
|
||||||
color: #EEF;
|
color: #EEF;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
@@ -42,6 +32,7 @@
|
|||||||
backdrop-filter: blur(3px) saturate(160%) contrast(45%) brightness(140%);
|
backdrop-filter: blur(3px) saturate(160%) contrast(45%) brightness(140%);
|
||||||
border: 1px solid rgb(88,88,88);
|
border: 1px solid rgb(88,88,88);
|
||||||
box-shadow: 0 0 1px rgb(146,146,148) inset;
|
box-shadow: 0 0 1px rgb(146,146,148) inset;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.menuitem {
|
.menuitem {
|
||||||
@@ -62,13 +53,4 @@
|
|||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.separator {
|
|
||||||
padding-top: 5px;
|
|
||||||
width: 100%;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
}
|
|
||||||
.separator:hover {
|
|
||||||
background-color: #0000;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
@@ -24,6 +24,15 @@
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function handleKeydown(e) {
|
||||||
|
// Backtick toggle
|
||||||
|
if( e.keyCode == 192 ) {
|
||||||
|
menuVisible.update( (current) => {
|
||||||
|
return !current;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $menuVisible }
|
{#if $menuVisible }
|
||||||
@@ -37,6 +46,8 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
<svelte:window on:keydown={handleKeydown}/>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
.tray-menus {
|
.tray-menus {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
export let tray = null;
|
export let tray = null;
|
||||||
|
|
||||||
$: visible = $selectedMenu === tray;
|
$: hidden = $selectedMenu !== tray;
|
||||||
|
|
||||||
function closeMenu() {
|
function closeMenu() {
|
||||||
selectedMenu.set(null);
|
selectedMenu.set(null);
|
||||||
@@ -23,7 +23,6 @@
|
|||||||
|
|
||||||
const handleClick = event => {
|
const handleClick = event => {
|
||||||
if (node && !node.contains(event.target) && !event.defaultPrevented) {
|
if (node && !node.contains(event.target) && !event.defaultPrevented) {
|
||||||
console.log("click outside of node")
|
|
||||||
node.dispatchEvent(
|
node.dispatchEvent(
|
||||||
new CustomEvent('click_outside', node)
|
new CustomEvent('click_outside', node)
|
||||||
)
|
)
|
||||||
@@ -46,7 +45,7 @@
|
|||||||
<!--{/if}-->
|
<!--{/if}-->
|
||||||
<span class="label" on:click={trayClicked}>{tray.Label}</span>
|
<span class="label" on:click={trayClicked}>{tray.Label}</span>
|
||||||
{#if tray.ProcessedMenu }
|
{#if tray.ProcessedMenu }
|
||||||
<Menu menu="{tray.ProcessedMenu}" visible="{visible}"/>
|
<Menu menu="{tray.ProcessedMenu}" {hidden}/>
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export function hideOverlay() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Menubar **/
|
/** Menubar **/
|
||||||
export const menuVisible = writable(true);
|
export const menuVisible = writable(false);
|
||||||
|
|
||||||
export function showMenuBar() {
|
export function showMenuBar() {
|
||||||
menuVisible.set(true);
|
menuVisible.set(true);
|
||||||
|
|||||||
@@ -6,20 +6,19 @@ import (
|
|||||||
|
|
||||||
// Runtime is a means for the user to interact with the application at runtime
|
// Runtime is a means for the user to interact with the application at runtime
|
||||||
type Runtime struct {
|
type Runtime struct {
|
||||||
Browser Browser
|
Browser Browser
|
||||||
Events Events
|
Events Events
|
||||||
Window Window
|
Window Window
|
||||||
Dialog Dialog
|
Dialog Dialog
|
||||||
System System
|
System System
|
||||||
Menu Menu
|
Menu Menu
|
||||||
Store *StoreProvider
|
Store *StoreProvider
|
||||||
Log Log
|
Log Log
|
||||||
bus *servicebus.ServiceBus
|
bus *servicebus.ServiceBus
|
||||||
shutdownCallback func()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new runtime
|
// New creates a new runtime
|
||||||
func New(serviceBus *servicebus.ServiceBus, shutdownCallback func()) *Runtime {
|
func New(serviceBus *servicebus.ServiceBus) *Runtime {
|
||||||
result := &Runtime{
|
result := &Runtime{
|
||||||
Browser: newBrowser(),
|
Browser: newBrowser(),
|
||||||
Events: newEvents(serviceBus),
|
Events: newEvents(serviceBus),
|
||||||
@@ -36,11 +35,6 @@ func New(serviceBus *servicebus.ServiceBus, shutdownCallback func()) *Runtime {
|
|||||||
|
|
||||||
// Quit the application
|
// Quit the application
|
||||||
func (r *Runtime) Quit() {
|
func (r *Runtime) Quit() {
|
||||||
// Call back to user's shutdown method if defined
|
|
||||||
if r.shutdownCallback != nil {
|
|
||||||
r.shutdownCallback()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start shutdown of Wails
|
// Start shutdown of Wails
|
||||||
r.bus.Publish("quit", "runtime.Quit()")
|
r.bus.Publish("quit", "runtime.Quit()")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,25 +26,20 @@ type Manager struct {
|
|||||||
ctx context.Context
|
ctx context.Context
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
|
|
||||||
// The shutdown callback to notify the user's app that a shutdown
|
|
||||||
// has started
|
|
||||||
shutdownCallback func()
|
|
||||||
|
|
||||||
// Parent waitgroup
|
// Parent waitgroup
|
||||||
wg *sync.WaitGroup
|
wg *sync.WaitGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewManager creates a new signal manager
|
// NewManager creates a new signal manager
|
||||||
func NewManager(ctx context.Context, cancel context.CancelFunc, bus *servicebus.ServiceBus, logger *logger.Logger, shutdownCallback func()) (*Manager, error) {
|
func NewManager(ctx context.Context, cancel context.CancelFunc, bus *servicebus.ServiceBus, logger *logger.Logger) (*Manager, error) {
|
||||||
|
|
||||||
result := &Manager{
|
result := &Manager{
|
||||||
bus: bus,
|
bus: bus,
|
||||||
logger: logger.CustomLogger("Event Manager"),
|
logger: logger.CustomLogger("Event Manager"),
|
||||||
signalchannel: make(chan os.Signal, 2),
|
signalchannel: make(chan os.Signal, 2),
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
shutdownCallback: shutdownCallback,
|
wg: ctx.Value("waitgroup").(*sync.WaitGroup),
|
||||||
wg: ctx.Value("waitgroup").(*sync.WaitGroup),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
@@ -67,11 +62,6 @@ func (m *Manager) Start() {
|
|||||||
m.logger.Trace("Ctrl+C detected. Shutting down...")
|
m.logger.Trace("Ctrl+C detected. Shutting down...")
|
||||||
m.bus.Publish("quit", "ctrl-c pressed")
|
m.bus.Publish("quit", "ctrl-c pressed")
|
||||||
|
|
||||||
// Shutdown app first
|
|
||||||
if m.shutdownCallback != nil {
|
|
||||||
m.shutdownCallback()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start shutdown of Wails
|
// Start shutdown of Wails
|
||||||
m.cancel()
|
m.cancel()
|
||||||
|
|
||||||
@@ -80,5 +70,4 @@ func (m *Manager) Start() {
|
|||||||
m.logger.Trace("Shutdown")
|
m.logger.Trace("Shutdown")
|
||||||
m.wg.Done()
|
m.wg.Done()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ type Runtime struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewRuntime creates a new runtime subsystem
|
// NewRuntime creates a new runtime subsystem
|
||||||
func NewRuntime(ctx context.Context, bus *servicebus.ServiceBus, logger *logger.Logger, startupCallback func(*runtime.Runtime), shutdownCallback func()) (*Runtime, error) {
|
func NewRuntime(ctx context.Context, bus *servicebus.ServiceBus, logger *logger.Logger, startupCallback func(*runtime.Runtime)) (*Runtime, error) {
|
||||||
|
|
||||||
// Subscribe to log messages
|
// Subscribe to log messages
|
||||||
runtimeChannel, err := bus.Subscribe("runtime:")
|
runtimeChannel, err := bus.Subscribe("runtime:")
|
||||||
@@ -52,13 +52,12 @@ func NewRuntime(ctx context.Context, bus *servicebus.ServiceBus, logger *logger.
|
|||||||
}
|
}
|
||||||
|
|
||||||
result := &Runtime{
|
result := &Runtime{
|
||||||
runtimeChannel: runtimeChannel,
|
runtimeChannel: runtimeChannel,
|
||||||
hooksChannel: hooksChannel,
|
hooksChannel: hooksChannel,
|
||||||
logger: logger.CustomLogger("Runtime Subsystem"),
|
logger: logger.CustomLogger("Runtime Subsystem"),
|
||||||
runtime: runtime.New(bus, shutdownCallback),
|
runtime: runtime.New(bus),
|
||||||
startupCallback: startupCallback,
|
startupCallback: startupCallback,
|
||||||
shutdownCallback: shutdownCallback,
|
ctx: ctx,
|
||||||
ctx: ctx,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,43 @@
|
|||||||
package keys
|
package keys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
// Modifier is actually a string
|
// Modifier is actually a string
|
||||||
type Modifier string
|
type Modifier string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// CmdOrCtrlKey represents Command on Mac and Control on other platforms
|
// CmdOrCtrlKey represents Command on Mac and Control on other platforms
|
||||||
CmdOrCtrlKey Modifier = "CmdOrCtrl"
|
CmdOrCtrlKey Modifier = "cmdorctrl"
|
||||||
// OptionOrAltKey represents Option on Mac and Alt on other platforms
|
// OptionOrAltKey represents Option on Mac and Alt on other platforms
|
||||||
OptionOrAltKey Modifier = "OptionOrAlt"
|
OptionOrAltKey Modifier = "optionoralt"
|
||||||
// ShiftKey represents the shift key on all systems
|
// ShiftKey represents the shift key on all systems
|
||||||
ShiftKey Modifier = "Shift"
|
ShiftKey Modifier = "shift"
|
||||||
// SuperKey represents Command on Mac and the Windows key on the other platforms
|
// SuperKey represents Command on Mac and the Windows key on the other platforms
|
||||||
SuperKey Modifier = "Super"
|
SuperKey Modifier = "super"
|
||||||
// ControlKey represents the control key on all systems
|
// ControlKey represents the control key on all systems
|
||||||
ControlKey Modifier = "Control"
|
ControlKey Modifier = "ctrl"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
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, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,14 @@ package mac
|
|||||||
|
|
||||||
import "github.com/wailsapp/wails/v2/pkg/menu"
|
import "github.com/wailsapp/wails/v2/pkg/menu"
|
||||||
|
|
||||||
|
type ActivationPolicy int
|
||||||
|
|
||||||
|
const (
|
||||||
|
NSApplicationActivationPolicyRegular ActivationPolicy = 0
|
||||||
|
NSApplicationActivationPolicyAccessory ActivationPolicy = 1
|
||||||
|
NSApplicationActivationPolicyProhibited ActivationPolicy = 2
|
||||||
|
)
|
||||||
|
|
||||||
// Options are options specific to Mac
|
// Options are options specific to Mac
|
||||||
type Options struct {
|
type Options struct {
|
||||||
TitleBar *TitleBar
|
TitleBar *TitleBar
|
||||||
@@ -11,4 +19,5 @@ type Options struct {
|
|||||||
Menu *menu.Menu
|
Menu *menu.Menu
|
||||||
TrayMenus []*menu.TrayMenu
|
TrayMenus []*menu.TrayMenu
|
||||||
ContextMenus []*menu.ContextMenu
|
ContextMenus []*menu.ContextMenu
|
||||||
|
ActivationPolicy ActivationPolicy
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user