mirror of
https://github.com/taigrr/wails.git
synced 2026-04-05 14:42:40 -07:00
Compare commits
1 Commits
develop
...
feature/v2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
29715b2d57 |
@@ -1,6 +1,7 @@
|
|||||||
package dev
|
package dev
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
@@ -10,14 +11,18 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/wailsapp/wails/v2/pkg/commands/build"
|
||||||
|
|
||||||
|
"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"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddSubcommand adds the `dev` command for the Wails application
|
// AddSubcommand adds the `dev` command for the Wails application
|
||||||
@@ -44,212 +49,262 @@ 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 buildFrontend bool = false
|
|
||||||
var extensionsThatTriggerARebuild = strings.Split(extensions, ",")
|
var extensionsThatTriggerARebuild = strings.Split(extensions, ",")
|
||||||
|
|
||||||
// Setup signal handler
|
reloader, err := NewReloader(logger, extensionsThatTriggerARebuild, ldflags, compilerCommand)
|
||||||
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...")
|
|
||||||
debugBinaryProcess, err = restartApp(logger, "dev", ldflags, compilerCommand, debugBinaryProcess)
|
|
||||||
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())
|
|
||||||
}
|
|
||||||
logger.Println("Watching directory: %s", event.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for file writes
|
|
||||||
if event.Op&fsnotify.Write == fsnotify.Write {
|
|
||||||
|
|
||||||
logger.Println("modified file: %s", event.Name)
|
|
||||||
var rebuild bool = false
|
|
||||||
|
|
||||||
// Iterate all file patterns
|
|
||||||
for _, pattern := range extensionsThatTriggerARebuild {
|
|
||||||
rebuild = strings.HasSuffix(event.Name, pattern)
|
|
||||||
if err != nil {
|
|
||||||
logger.Fatal(err.Error())
|
|
||||||
}
|
|
||||||
if rebuild {
|
|
||||||
// Only build frontend when the file isn't a Go file
|
|
||||||
buildFrontend = !strings.HasSuffix(event.Name, "go")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !rebuild {
|
|
||||||
logger.Println("Filename change: %s did not match extension list (%s)", event.Name, extensions)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Println("Partial build triggered: %s updated", event.Name)
|
|
||||||
|
|
||||||
// Do a rebuild
|
|
||||||
|
|
||||||
// Try and build the app
|
|
||||||
newBinaryProcess, err := restartApp(logger, "dev", ldflags, compilerCommand, debugBinaryProcess)
|
|
||||||
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
|
|
||||||
dir, err := os.Getwd()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all subdirectories
|
// Start
|
||||||
dirs, err := fs.GetSubdirectories(dir)
|
err = reloader.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
println("ERRRRRRRRRR: %+v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup a watcher for non-node_modules directories
|
logger.Println("\nDevelopment mode exited")
|
||||||
dirs.Each(func(dir string) {
|
|
||||||
if strings.Contains(dir, "node_modules") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
logger.Println("Watching directory: %s", dir)
|
|
||||||
err = watcher.Add(dir)
|
|
||||||
if err != nil {
|
|
||||||
logger.Fatal(err.Error())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Wait until we get a quit signal
|
return err
|
||||||
quit := false
|
|
||||||
for quit == false {
|
|
||||||
select {
|
|
||||||
case <-quitChannel:
|
|
||||||
println("Caught 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Println("Development mode exited")
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Credit: https://drailing.net/2018/01/debounce-function-for-golang/
|
type Reloader struct {
|
||||||
func debounce(interval time.Duration, input chan fsnotify.Event, quitChannel chan bool, cb func(arg fsnotify.Event)) {
|
|
||||||
var item fsnotify.Event
|
// Main context
|
||||||
timer := time.NewTimer(interval)
|
ctx context.Context
|
||||||
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 item = <-input:
|
case <-r.signalContext.Done():
|
||||||
timer.Reset(interval)
|
if r.binary != nil {
|
||||||
case <-timer.C:
|
println("Binary is not nil - kill")
|
||||||
if item.Name != "" {
|
return r.binary.Kill()
|
||||||
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 restartApp(logger *clilogger.CLILogger, outputType string, ldflags string, compilerCommand string, debugBinaryProcess *process.Process) (*process.Process, error) {
|
func (r *Reloader) processWatcherEvent(event fsnotify.Event) error {
|
||||||
|
|
||||||
appBinary, err := buildApp(logger, outputType, ldflags, compilerCommand)
|
// Check for new directories
|
||||||
println()
|
if event.Op&fsnotify.Create == fsnotify.Create {
|
||||||
if err != nil {
|
// If this is a folder, add it to our watch list
|
||||||
logger.Fatal(err.Error())
|
if fs.DirExists(event.Name) {
|
||||||
return nil, errors.Wrap(err, "Build Failed:")
|
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
|
||||||
}
|
}
|
||||||
logger.Println("Build new binary: %s", appBinary)
|
|
||||||
|
|
||||||
// Kill existing binary if need be
|
// Check for file writes
|
||||||
if debugBinaryProcess != nil {
|
if event.Op&fsnotify.Write == fsnotify.Write {
|
||||||
killError := debugBinaryProcess.Kill()
|
|
||||||
|
|
||||||
if killError != nil {
|
var rebuild bool
|
||||||
logger.Fatal("Unable to kill debug binary (PID: %d)!", debugBinaryProcess.PID())
|
|
||||||
|
// Iterate all file patterns
|
||||||
|
for _, pattern := range r.extensionsThatTriggerARebuild {
|
||||||
|
if strings.HasSuffix(event.Name, pattern) {
|
||||||
|
rebuild = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debugBinaryProcess = nil
|
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 {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Generate `backend.js`
|
// Kill current binary if running
|
||||||
|
if r.binary != nil {
|
||||||
|
err = r.binary.Kill()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Start up new binary
|
newProcess := process.NewProcess(r.ctx, r.logger, binary)
|
||||||
newProcess := process.NewProcess(logger, appBinary)
|
|
||||||
err = newProcess.Start()
|
err = newProcess.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Remove binary
|
return err
|
||||||
deleteError := fs.DeleteFile(appBinary)
|
|
||||||
if deleteError != nil {
|
|
||||||
logger.Fatal("Unable to delete app binary: " + appBinary)
|
|
||||||
}
|
|
||||||
logger.Fatal("Unable to start application: %s", err.Error())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return newProcess, nil
|
// Ensure process runs correctly
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildApp(logger *clilogger.CLILogger, outputType string, ldflags string, compilerCommand string) (string, error) {
|
//func restartApp(logger *clilogger.CLILogger, outputType string, ldflags string, compilerCommand string, debugBinaryProcess *process.Process) (*process.Process, 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("debug-%d", time.Now().Unix())
|
||||||
|
|
||||||
// Create BuildOptions
|
// Create BuildOptions
|
||||||
buildOptions := &build.Options{
|
buildOptions := &build.Options{
|
||||||
Logger: logger,
|
Logger: r.logger,
|
||||||
OutputType: outputType,
|
OutputType: "dev",
|
||||||
Mode: build.Debug,
|
Mode: build.Debug,
|
||||||
Pack: false,
|
Pack: false,
|
||||||
Platform: runtime.GOOS,
|
Platform: runtime.GOOS,
|
||||||
LDFlags: ldflags,
|
LDFlags: r.ldflags,
|
||||||
Compiler: compilerCommand,
|
Compiler: r.compiler,
|
||||||
OutputFile: outputFile,
|
OutputFile: outputFile,
|
||||||
IgnoreFrontend: true,
|
IgnoreFrontend: true,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/wzshiming/ctc"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/cmd/wails/internal/commands/update"
|
"github.com/wailsapp/wails/v2/cmd/wails/internal/commands/update"
|
||||||
|
|
||||||
"github.com/leaanthony/clir"
|
"github.com/leaanthony/clir"
|
||||||
@@ -19,12 +22,30 @@ func fatal(message string) {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func col(colour ctc.Color, text string) string {
|
||||||
|
return fmt.Sprintf("%s%s%s", colour, text, ctc.Reset)
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
app := clir.NewCli("Wails", "Go/HTML Application Framework", version)
|
app := clir.NewCli("Wails", "Go/HTML Application Framework", version)
|
||||||
|
|
||||||
|
app.SetBannerFunction(banner)
|
||||||
|
|
||||||
build.AddBuildSubcommand(app, os.Stdout)
|
build.AddBuildSubcommand(app, os.Stdout)
|
||||||
err = initialise.AddSubcommand(app, os.Stdout)
|
err = initialise.AddSubcommand(app, os.Stdout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ 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/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/sync v0.0.0-20201207232520-09787c993a3a
|
||||||
|
|||||||
@@ -78,6 +78,10 @@ github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
|||||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||||
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
||||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||||
|
github.com/wzshiming/ctc v1.2.3 h1:q+hW3IQNsjIlOFBTGZZZeIXTElFM4grF4spW/errh/c=
|
||||||
|
github.com/wzshiming/ctc v1.2.3/go.mod h1:2tVAtIY7SUyraSk0JxvwmONNPFL4ARavPuEsg5+KA28=
|
||||||
|
github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae h1:tpXvBXC3hpQBDCc9OojJZCQMVRAbT3TTdUMP8WguXkY=
|
||||||
|
github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae/go.mod h1:VTAq37rkGeV+WOybvZwjXiJOicICdpLCN8ifpISjK20=
|
||||||
github.com/xyproto/xpm v1.2.1 h1:trdvGjjWBsOOKzBBUPT6JvaIQM3acJEEYfbxN7M96wg=
|
github.com/xyproto/xpm v1.2.1 h1:trdvGjjWBsOOKzBBUPT6JvaIQM3acJEEYfbxN7M96wg=
|
||||||
github.com/xyproto/xpm v1.2.1/go.mod h1:cMnesLsD0PBXLgjDfTDEaKr8XyTFsnP1QycSqRw7BiY=
|
github.com/xyproto/xpm v1.2.1/go.mod h1:cMnesLsD0PBXLgjDfTDEaKr8XyTFsnP1QycSqRw7BiY=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
@@ -97,6 +101,7 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
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=
|
||||||
|
golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c h1:UIcGWL6/wpCfyGuJnRFJRurA+yj8RrW7Q6x2YMCXt6c=
|
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c h1:UIcGWL6/wpCfyGuJnRFJRurA+yj8RrW7Q6x2YMCXt6c=
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"github.com/wailsapp/wails/v2/pkg/logger"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Init initialises the application for a debug environment
|
// Init initialises the application for a debug environment
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package process
|
package process
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
@@ -9,18 +10,16 @@ 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
|
||||||
exitChannel chan bool
|
running bool
|
||||||
Running bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewProcess creates a new process struct
|
// NewProcess creates a new process struct
|
||||||
func NewProcess(logger *clilogger.CLILogger, cmd string, args ...string) *Process {
|
func NewProcess(ctx context.Context, logger *clilogger.CLILogger, cmd string, args ...string) *Process {
|
||||||
result := &Process{
|
result := &Process{
|
||||||
logger: logger,
|
logger: logger,
|
||||||
cmd: exec.Command(cmd, args...),
|
cmd: exec.CommandContext(ctx, 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
|
||||||
@@ -35,30 +34,30 @@ func (p *Process) Start() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
p.Running = true
|
p.running = true
|
||||||
|
|
||||||
go func(cmd *exec.Cmd, running *bool, logger *clilogger.CLILogger, exitChannel chan bool) {
|
go func(p *Process) {
|
||||||
logger.Println("Starting process (PID: %d)", cmd.Process.Pid)
|
p.logger.Println("Starting process (PID: %d)", p.cmd.Process.Pid)
|
||||||
cmd.Wait()
|
err := p.cmd.Wait()
|
||||||
logger.Println("Exiting process (PID: %d)", cmd.Process.Pid)
|
if err != nil {
|
||||||
*running = false
|
p.running = false
|
||||||
exitChannel <- true
|
p.logger.Println("Process failed to run: %s", err.Error())
|
||||||
}(p.cmd, &p.Running, p.logger, p.exitChannel)
|
return
|
||||||
|
}
|
||||||
|
p.logger.Println("Exiting process (PID: %d)", p.cmd.Process.Pid)
|
||||||
|
}(p)
|
||||||
|
|
||||||
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 {
|
||||||
return nil
|
println("Calling kill")
|
||||||
|
p.running = false
|
||||||
|
return p.cmd.Process.Kill()
|
||||||
}
|
}
|
||||||
err := p.cmd.Process.Kill()
|
return nil
|
||||||
|
|
||||||
// Wait for command to exit properly
|
|
||||||
<-p.exitChannel
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PID returns the process PID
|
// PID returns the process PID
|
||||||
|
|||||||
@@ -779,18 +779,18 @@
|
|||||||
|
|
||||||
function add_css$1() {
|
function add_css$1() {
|
||||||
var style = element("style");
|
var style = element("style");
|
||||||
style.id = "svelte-1oysp7o-style";
|
style.id = "svelte-1ucacnf-style";
|
||||||
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}";
|
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}";
|
||||||
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[2] = list[i];
|
child_ctx[3] = list[i];
|
||||||
return child_ctx;
|
return child_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
// (8:0) {#if !hidden}
|
// (14:0) {#if visible}
|
||||||
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-1oysp7o");
|
attr(div, "class", "menu svelte-1ucacnf");
|
||||||
},
|
},
|
||||||
m(target, anchor) {
|
m(target, anchor) {
|
||||||
insert(target, div, anchor);
|
insert(target, div, anchor);
|
||||||
@@ -826,7 +826,7 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// (10:4) {#if menu.Menu }
|
// (16: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 & /*menu*/ 1) {
|
if (dirty & /*click, menu*/ 1) {
|
||||||
each_value = /*menu*/ ctx[0].Menu.Items;
|
each_value = /*menu*/ ctx[0].Menu.Items;
|
||||||
let i;
|
let i;
|
||||||
|
|
||||||
@@ -882,44 +882,41 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// (13:12) {#if menuItem.Image }
|
// (25:52)
|
||||||
function create_if_block_2(ctx) {
|
function create_if_block_4(ctx) {
|
||||||
let div;
|
let div;
|
||||||
let img;
|
|
||||||
let img_src_value;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
c() {
|
c() {
|
||||||
div = element("div");
|
div = element("div");
|
||||||
img = element("img");
|
div.innerHTML = `<hr/>`;
|
||||||
attr(img, "alt", "");
|
attr(div, "class", "separator svelte-1ucacnf");
|
||||||
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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// (11:8) {#each menu.Menu.Items as menuItem}
|
// (18:12) {#if menuItem.Type === "Text" }
|
||||||
function create_each_block(ctx) {
|
function create_if_block_2(ctx) {
|
||||||
let div1;
|
let div1;
|
||||||
let t0;
|
let t0;
|
||||||
let div0;
|
let div0;
|
||||||
let t1_value = /*menuItem*/ ctx[2].Label + "";
|
let t1_value = /*menuItem*/ ctx[3].Label + "";
|
||||||
let t1;
|
let t1;
|
||||||
let t2;
|
let t2;
|
||||||
let if_block = /*menuItem*/ ctx[2].Image && create_if_block_2(ctx);
|
let mounted;
|
||||||
|
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() {
|
||||||
@@ -930,7 +927,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-1oysp7o");
|
attr(div1, "class", "menuitem svelte-1ucacnf");
|
||||||
},
|
},
|
||||||
m(target, anchor) {
|
m(target, anchor) {
|
||||||
insert(target, div1, anchor);
|
insert(target, div1, anchor);
|
||||||
@@ -939,13 +936,20 @@
|
|||||||
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(ctx, dirty) {
|
p(new_ctx, dirty) {
|
||||||
if (/*menuItem*/ ctx[2].Image) {
|
ctx = new_ctx;
|
||||||
|
|
||||||
|
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_2(ctx);
|
if_block = create_if_block_3(ctx);
|
||||||
if_block.c();
|
if_block.c();
|
||||||
if_block.m(div1, t0);
|
if_block.m(div1, t0);
|
||||||
}
|
}
|
||||||
@@ -954,18 +958,93 @@
|
|||||||
if_block = null;
|
if_block = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dirty & /*menu*/ 1 && t1_value !== (t1_value = /*menuItem*/ ctx[2].Label + "")) set_data(t1, t1_value);
|
if (dirty & /*menu*/ 1 && t1_value !== (t1_value = /*menuItem*/ ctx[3].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 = !/*hidden*/ ctx[1] && create_if_block$1(ctx);
|
let if_block = /*visible*/ ctx[1] && create_if_block$1(ctx);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
c() {
|
c() {
|
||||||
@@ -977,7 +1056,7 @@
|
|||||||
insert(target, if_block_anchor, anchor);
|
insert(target, if_block_anchor, anchor);
|
||||||
},
|
},
|
||||||
p(ctx, [dirty]) {
|
p(ctx, [dirty]) {
|
||||||
if (!/*hidden*/ ctx[1]) {
|
if (/*visible*/ ctx[1]) {
|
||||||
if (if_block) {
|
if (if_block) {
|
||||||
if_block.p(ctx, dirty);
|
if_block.p(ctx, dirty);
|
||||||
} else {
|
} else {
|
||||||
@@ -999,23 +1078,29 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
let { hidden = true } = $$props;
|
console.log({ menu });
|
||||||
|
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 ("hidden" in $$props) $$invalidate(1, hidden = $$props.hidden);
|
if ("visible" in $$props) $$invalidate(1, visible = $$props.visible);
|
||||||
};
|
};
|
||||||
|
|
||||||
return [menu, hidden];
|
return [menu, visible, click_handler];
|
||||||
}
|
}
|
||||||
|
|
||||||
class Menu extends SvelteComponent {
|
class Menu extends SvelteComponent {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
super();
|
super();
|
||||||
if (!document.getElementById("svelte-1oysp7o-style")) add_css$1();
|
if (!document.getElementById("svelte-1ucacnf-style")) add_css$1();
|
||||||
init(this, options, instance$1, create_fragment$1, safe_not_equal, { menu: 0, hidden: 1 });
|
init(this, options, instance$1, create_fragment$1, safe_not_equal, { menu: 0, visible: 1 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1030,7 +1115,7 @@
|
|||||||
append(document_1.head, style);
|
append(document_1.head, style);
|
||||||
}
|
}
|
||||||
|
|
||||||
// (47:4) {#if tray.ProcessedMenu }
|
// (48:4) {#if tray.ProcessedMenu }
|
||||||
function create_if_block$2(ctx) {
|
function create_if_block$2(ctx) {
|
||||||
let menu;
|
let menu;
|
||||||
let current;
|
let current;
|
||||||
@@ -1038,7 +1123,7 @@
|
|||||||
menu = new Menu({
|
menu = new Menu({
|
||||||
props: {
|
props: {
|
||||||
menu: /*tray*/ ctx[0].ProcessedMenu,
|
menu: /*tray*/ ctx[0].ProcessedMenu,
|
||||||
hidden: /*hidden*/ ctx[1]
|
visible: /*visible*/ ctx[1]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1053,7 +1138,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 & /*hidden*/ 2) menu_changes.hidden = /*hidden*/ ctx[1];
|
if (dirty & /*visible*/ 2) menu_changes.visible = /*visible*/ ctx[1];
|
||||||
menu.$set(menu_changes);
|
menu.$set(menu_changes);
|
||||||
},
|
},
|
||||||
i(local) {
|
i(local) {
|
||||||
@@ -1157,6 +1242,7 @@
|
|||||||
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));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1171,7 +1257,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function instance$2($$self, $$props, $$invalidate) {
|
function instance$2($$self, $$props, $$invalidate) {
|
||||||
let hidden;
|
let visible;
|
||||||
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;
|
||||||
@@ -1194,11 +1280,11 @@
|
|||||||
|
|
||||||
$$self.$$.update = () => {
|
$$self.$$.update = () => {
|
||||||
if ($$self.$$.dirty & /*$selectedMenu, tray*/ 17) {
|
if ($$self.$$.dirty & /*$selectedMenu, tray*/ 17) {
|
||||||
$$invalidate(1, hidden = $selectedMenu !== tray);
|
$$invalidate(1, visible = $selectedMenu === tray);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return [tray, hidden, closeMenu, trayClicked, $selectedMenu];
|
return [tray, visible, closeMenu, trayClicked, $selectedMenu];
|
||||||
}
|
}
|
||||||
|
|
||||||
class TrayMenu extends SvelteComponent {
|
class TrayMenu extends SvelteComponent {
|
||||||
|
|||||||
@@ -2,19 +2,29 @@
|
|||||||
|
|
||||||
export let menu;
|
export let menu;
|
||||||
|
|
||||||
export let hidden = true;
|
console.log({menu})
|
||||||
|
|
||||||
|
export let visible = false;
|
||||||
|
|
||||||
|
function click(id) {
|
||||||
|
console.log("MenuItem", id, "pressed")
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if !hidden}
|
{#if visible}
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
{#if menu.Menu }
|
{#if menu.Menu }
|
||||||
{#each menu.Menu.Items as menuItem}
|
{#each menu.Menu.Items as menuItem}
|
||||||
<div class="menuitem">
|
{#if menuItem.Type === "Text" }
|
||||||
|
<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>
|
||||||
@@ -23,7 +33,7 @@
|
|||||||
<style>
|
<style>
|
||||||
|
|
||||||
.menu {
|
.menu {
|
||||||
padding: 3px;
|
padding: 5px;
|
||||||
background-color: #0008;
|
background-color: #0008;
|
||||||
color: #EEF;
|
color: #EEF;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
@@ -32,7 +42,6 @@
|
|||||||
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 {
|
||||||
@@ -53,4 +62,13 @@
|
|||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.separator {
|
||||||
|
padding-top: 5px;
|
||||||
|
width: 100%;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
}
|
||||||
|
.separator:hover {
|
||||||
|
background-color: #0000;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
export let tray = null;
|
export let tray = null;
|
||||||
|
|
||||||
$: hidden = $selectedMenu !== tray;
|
$: visible = $selectedMenu === tray;
|
||||||
|
|
||||||
function closeMenu() {
|
function closeMenu() {
|
||||||
selectedMenu.set(null);
|
selectedMenu.set(null);
|
||||||
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
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)
|
||||||
)
|
)
|
||||||
@@ -45,7 +46,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}" {hidden}/>
|
<Menu menu="{tray.ProcessedMenu}" visible="{visible}"/>
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
|||||||
@@ -80,4 +80,5 @@ func (m *Manager) Start() {
|
|||||||
m.logger.Trace("Shutdown")
|
m.logger.Trace("Shutdown")
|
||||||
m.wg.Done()
|
m.wg.Done()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user