5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-03 03:40:12 +08:00

[windows-x] Dev mode. Auto rebuild/reload. Auto open browser. Disconnect spinner. Base template update. mimecache

This commit is contained in:
Lea Anthony 2021-08-24 23:48:03 +10:00
parent c3c88f5e27
commit b558246d52
23 changed files with 611 additions and 488 deletions

View File

@ -6,6 +6,7 @@ import (
"github.com/wailsapp/wails/v2/internal/project" "github.com/wailsapp/wails/v2/internal/project"
"io" "io"
"log" "log"
"net/http"
"os" "os"
"os/signal" "os/signal"
"path/filepath" "path/filepath"
@ -40,6 +41,14 @@ func LogDarkYellow(message string, args ...interface{}) {
println(colour.DarkYellow(text)) println(colour.DarkYellow(text))
} }
func sliceToMap(input []string) map[string]struct{} {
result := map[string]struct{}{}
for _, value := range input {
result[value] = struct{}{}
}
return result
}
// 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 {
@ -56,14 +65,24 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
assetDir := "" assetDir := ""
command.StringFlag("assetdir", "Serve assets from the given directory", &assetDir) command.StringFlag("assetdir", "Serve assets from the given directory", &assetDir)
// extensions to trigger rebuilds // extensions to trigger rebuilds of application
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", &extensions)
// extensions to trigger reloads in the application
reloadEnabled := true
command.BoolFlag("r", "Reload on asset changes", &reloadEnabled)
// extensions to trigger rebuilds // extensions to trigger rebuilds
showWarnings := false showWarnings := false
command.BoolFlag("w", "Show warnings", &showWarnings) command.BoolFlag("w", "Show warnings", &showWarnings)
openBrowser := false
command.BoolFlag("browser", "Open application in browser", &openBrowser)
noreload := false
command.BoolFlag("noreload", "Disable reload on asset change", &noreload)
// Verbosity // Verbosity
verbosity := 1 verbosity := 1
command.IntFlag("v", "Verbosity level (0 - silent, 1 - default, 2 - verbose)", &verbosity) command.IntFlag("v", "Verbosity level (0 - silent, 1 - default, 2 - verbose)", &verbosity)
@ -77,7 +96,6 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
logger := clilogger.New(w) logger := clilogger.New(w)
app.PrintBanner() app.PrintBanner()
// TODO: Check you are in a project directory
cwd, err := os.Getwd() cwd, err := os.Getwd()
if err != nil { if err != nil {
return err return err
@ -91,6 +109,11 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
return fmt.Errorf("No asset directory provided. Please use -assetdir to indicate which directory contains your built assets.") return fmt.Errorf("No asset directory provided. Please use -assetdir to indicate which directory contains your built assets.")
} }
assetDir, err = filepath.Abs(assetDir)
if err != nil {
return err
}
if assetDir != "" && assetDir != projectConfig.AssetDirectory { if assetDir != "" && assetDir != projectConfig.AssetDirectory {
projectConfig.AssetDirectory = assetDir projectConfig.AssetDirectory = assetDir
err := projectConfig.Save() err := projectConfig.Save()
@ -115,13 +138,12 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
}(watcher) }(watcher)
var debugBinaryProcess *process.Process = nil var debugBinaryProcess *process.Process = nil
var extensionsThatTriggerARebuild = strings.Split(extensions, ",") var extensionsThatTriggerARebuild = sliceToMap(strings.Split(extensions, ","))
// Setup signal handler // Setup signal handler
quitChannel := make(chan os.Signal, 1) quitChannel := make(chan os.Signal, 1)
signal.Notify(quitChannel, os.Interrupt, os.Kill, syscall.SIGTERM) signal.Notify(quitChannel, os.Interrupt, os.Kill, syscall.SIGTERM)
exitCodeChannel := make(chan int, 1)
debounceQuit := make(chan bool, 1)
var passthruArgs []string var passthruArgs []string
//if len(os.Args) > 2 { //if len(os.Args) > 2 {
@ -130,7 +152,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
// Do initial build // Do initial build
logger.Println("Building application for development...") logger.Println("Building application for development...")
newProcess, appBinary, err := restartApp(logger, ldflags, compilerCommand, debugBinaryProcess, loglevel, passthruArgs, verbosity, assetDir, true) newProcess, appBinary, err := restartApp(logger, ldflags, compilerCommand, debugBinaryProcess, loglevel, passthruArgs, verbosity, assetDir, true, exitCodeChannel)
if err != nil { if err != nil {
return err return err
} }
@ -139,70 +161,17 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
} }
// open browser // open browser
if openBrowser {
err = browser.OpenURL("http://localhost:34115") err = browser.OpenURL("http://localhost:34115")
if err != nil { if err != nil {
return err return err
} }
}
if err != nil { if err != nil {
return err return err
} }
var newBinaryProcess *process.Process var newBinaryProcess *process.Process
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, ldflags, compilerCommand, debugBinaryProcess, loglevel, passthruArgs, verbosity, assetDir, false)
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 // Get project dir
projectDir, err := os.Getwd() projectDir, err := os.Getwd()
@ -227,20 +196,88 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
if strings.HasPrefix(dir, filepath.Join(projectDir, "build")) { if strings.HasPrefix(dir, filepath.Join(projectDir, "build")) {
return return
} }
//println("Watching", dir)
err = watcher.Add(dir) err = watcher.Add(dir)
if err != nil { if err != nil {
logger.Fatal(err.Error()) logger.Fatal(err.Error())
} }
}) })
// Wait until we get a quit signal // Main Loop
quit := false quit := false
// Use 100ms debounce
interval := 100 * time.Millisecond
timer := time.NewTimer(interval)
rebuild := false
reload := false
for quit == false { for quit == false {
//reload := false
select { select {
case exitCode := <-exitCodeChannel:
if exitCode == 0 {
quit = true
}
case item := <-watcher.Events:
// Check for file writes
if item.Op&fsnotify.Write == fsnotify.Write {
// Ignore directories
if fs.DirExists(item.Name) {
continue
}
// Iterate all file patterns
ext := filepath.Ext(item.Name)
if ext != "" {
ext = ext[1:]
if _, exists := extensionsThatTriggerARebuild[ext]; exists {
rebuild = true
continue
}
}
if strings.HasPrefix(item.Name, assetDir) {
reload = true
}
timer.Reset(interval)
}
// Check for new directories
if item.Op&fsnotify.Create == fsnotify.Create {
// If this is a folder, add it to our watch list
if fs.DirExists(item.Name) {
//node_modules is BANNED!
if !strings.Contains(item.Name, "node_modules") {
err := watcher.Add(item.Name)
if err != nil {
logger.Fatal("%s", err.Error())
}
LogGreen("Added new directory to watcher: %s", item.Name)
}
}
}
case <-timer.C:
if rebuild {
rebuild = false
LogGreen("[Rebuild triggered] files updated")
// Try and build the app
newBinaryProcess, _, err = restartApp(logger, ldflags, compilerCommand, debugBinaryProcess, loglevel, passthruArgs, verbosity, assetDir, false, exitCodeChannel)
if err != nil {
LogRed("Error during build: %s", err.Error())
continue
}
// If we have a new process, save it
if newBinaryProcess != nil {
debugBinaryProcess = newBinaryProcess
}
}
if reload {
reload = false
_, err = http.Get("http://localhost:34115/wails/reload")
if err != nil {
LogRed("Error during refresh: %s", err.Error())
}
}
case <-quitChannel: case <-quitChannel:
LogGreen("\nCaught quit") LogGreen("\nCaught quit")
// Notify debouncer to quit
debounceQuit <- true
quit = true quit = true
} }
} }
@ -267,26 +304,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
return nil return nil
} }
// Credit: https://drailing.net/2018/01/debounce-function-for-golang/ func restartApp(logger *clilogger.CLILogger, ldflags string, compilerCommand string, debugBinaryProcess *process.Process, loglevel string, passthruArgs []string, verbosity int, assetDir string, firstRun bool, exitCodeChannel chan int) (*process.Process, string, error) {
func debounce(interval time.Duration, input chan fsnotify.Event, quitChannel chan bool, cb func(arg fsnotify.Event)) {
var item fsnotify.Event
timer := time.NewTimer(interval)
exit:
for {
select {
case item = <-input:
timer.Reset(interval)
case <-timer.C:
if item.Name != "" {
cb(item)
}
case <-quitChannel:
break exit
}
}
}
func restartApp(logger *clilogger.CLILogger, ldflags string, compilerCommand string, debugBinaryProcess *process.Process, loglevel string, passthruArgs []string, verbosity int, assetDir string, firstRun bool) (*process.Process, string, error) {
appBinary, err := buildApp(logger, ldflags, compilerCommand, verbosity) appBinary, err := buildApp(logger, ldflags, compilerCommand, verbosity)
println() println()
@ -322,8 +340,8 @@ func restartApp(logger *clilogger.CLILogger, ldflags string, compilerCommand str
if len(passthruArgs) > 0 { if len(passthruArgs) > 0 {
args.AddSlice(passthruArgs) args.AddSlice(passthruArgs)
} }
newProcess := process.NewProcess(logger, appBinary, args.AsSlice()...) newProcess := process.NewProcess(appBinary, args.AsSlice()...)
err = newProcess.Start() err = newProcess.Start(exitCodeChannel)
if err != nil { if err != nil {
// Remove binary // Remove binary
deleteError := fs.DeleteFile(appBinary) deleteError := fs.DeleteFile(appBinary)

View File

@ -6,6 +6,7 @@ require (
github.com/Masterminds/semver v1.5.0 github.com/Masterminds/semver v1.5.0
github.com/fatih/structtag v1.2.0 github.com/fatih/structtag v1.2.0
github.com/fsnotify/fsnotify v1.4.9 github.com/fsnotify/fsnotify v1.4.9
github.com/gabriel-vasile/mimetype v1.3.1
github.com/go-git/go-billy/v5 v5.2.0 // indirect github.com/go-git/go-billy/v5 v5.2.0 // indirect
github.com/go-git/go-git/v5 v5.3.0 github.com/go-git/go-git/v5 v5.3.0
github.com/gofiber/fiber/v2 v2.17.0 github.com/gofiber/fiber/v2 v2.17.0
@ -43,7 +44,7 @@ require (
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect
golang.org/x/mod v0.4.1 // indirect golang.org/x/mod v0.4.1 // indirect
golang.org/x/net v0.0.0-20210510120150-4163338589ed golang.org/x/net v0.0.0-20210510120150-4163338589ed
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71 golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf
golang.org/x/tools v0.1.0 golang.org/x/tools v0.1.0
nhooyr.io/websocket v1.8.6 nhooyr.io/websocket v1.8.6
) )

View File

@ -11,7 +11,6 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@ -22,10 +21,11 @@ github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab h1:9e2joQGp642w
github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab/go.mod h1:smsv/h4PBEBaU0XDTY5UwJTpZv69fQ0FfcLJr21mA6Y= github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab/go.mod h1:smsv/h4PBEBaU0XDTY5UwJTpZv69fQ0FfcLJr21mA6Y=
github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/gabriel-vasile/mimetype v1.3.1 h1:qevA6c2MtE1RorlScnixeG0VA1H4xrXyhyX3oWBynNQ=
github.com/gabriel-vasile/mimetype v1.3.1/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
@ -45,7 +45,6 @@ github.com/go-git/go-git/v5 v5.3.0/go.mod h1:xdX4bWJ48aOrdhnl2XqHYstHbbp6+LFS4r4
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
@ -68,13 +67,11 @@ github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgj
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
@ -89,7 +86,6 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jchv/go-winloader v0.0.0-20200815041850-dec1ee9a7fd5 h1:pdFFlHXY9tZXmJz+tRSm1DzYEH4ebha7cffmm607bMU= github.com/jchv/go-winloader v0.0.0-20200815041850-dec1ee9a7fd5 h1:pdFFlHXY9tZXmJz+tRSm1DzYEH4ebha7cffmm607bMU=
github.com/jchv/go-winloader v0.0.0-20200815041850-dec1ee9a7fd5/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= github.com/jchv/go-winloader v0.0.0-20200815041850-dec1ee9a7fd5/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc=
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@ -99,14 +95,11 @@ github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.12.2 h1:2KCfW3I9M7nSc5wOqXAlW2v2U6v+w6cbjvbfp+OykW8= github.com/klauspost/compress v1.12.2 h1:2KCfW3I9M7nSc5wOqXAlW2v2U6v+w6cbjvbfp+OykW8=
github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w=
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@ -148,7 +141,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLD
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8= github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
@ -163,10 +155,8 @@ github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f h1:PgA+Olipyj258EIE
github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f/go.mod h1:lHhJedqxCoHN+zMtwGNTXWmF0u9Jt363FYRhV6g0CdY= github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f/go.mod h1:lHhJedqxCoHN+zMtwGNTXWmF0u9Jt363FYRhV6g0CdY=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@ -210,7 +200,6 @@ github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
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 h1:ruQGxdhGHe7FWOJPT0mKs5+pD2Xs1Bm/kdGlHO04FmM=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/ztrue/tracerr v0.3.0 h1:lDi6EgEYhPYPnKcjsYzmWw4EkFEoA/gfe+I9Y5f+h6Y= github.com/ztrue/tracerr v0.3.0 h1:lDi6EgEYhPYPnKcjsYzmWw4EkFEoA/gfe+I9Y5f+h6Y=
github.com/ztrue/tracerr v0.3.0/go.mod h1:qEalzze4VN9O8tnhBXScfCrmoJo10o8TN5ciKjm6Mww= github.com/ztrue/tracerr v0.3.0/go.mod h1:qEalzze4VN9O8tnhBXScfCrmoJo10o8TN5ciKjm6Mww=
@ -233,10 +222,10 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I= golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I=
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
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-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -257,8 +246,9 @@ golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210611083646-a4fc73990273/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210611083646-a4fc73990273/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71 h1:X/2sJAybVknnUnV7AD2HdT6rm2p5BP6eH2j+igduWgk=
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf h1:2ucpDCmfkl8Bd/FsLtiD653Wf96cW37s+iGx93zsu4k=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -266,7 +256,6 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=

View File

@ -10,7 +10,6 @@ import (
"github.com/wailsapp/wails/v2/internal/frontend/runtime" "github.com/wailsapp/wails/v2/internal/frontend/runtime"
"github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/internal/logger"
"io/fs" "io/fs"
"net/http"
"path/filepath" "path/filepath"
"strings" "strings"
) )
@ -103,11 +102,11 @@ func (a *DesktopAssetServer) init(assets embed.FS) error {
if err != nil { if err != nil {
return err return err
} }
a.indexFile, err = injectScript(string(indexHTML), `<script src="/wails/runtime.js"></script>`) a.indexFile, err = injectHTML(string(indexHTML), `<script src="/wails/runtime.js"></script>`)
if err != nil { if err != nil {
return err return err
} }
a.indexFile, err = injectScript(string(a.indexFile), `<script src="/wails/ipc.js"></script>`) a.indexFile, err = injectHTML(string(a.indexFile), `<script src="/wails/ipc.js"></script>`)
if err != nil { if err != nil {
return err return err
} }
@ -130,6 +129,6 @@ func (a *DesktopAssetServer) Load(filename string) ([]byte, string, error) {
if err != nil { if err != nil {
return nil, "", err return nil, "", err
} }
mimeType := http.DetectContentType(content) mimeType := GetMimetype(filename, content)
return content, mimeType, nil return content, mimeType, nil
} }

View File

@ -18,7 +18,6 @@ It injects a websocket based IPC script into `index.html`.
*/ */
import ( import (
"net/http"
"os" "os"
) )
@ -53,15 +52,20 @@ func (a *AssetServer) loadFileFromDisk(filename string) ([]byte, error) {
} }
func (a *AssetServer) init() error { func (a *AssetServer) init() error {
indexHTML, err := a.loadFileFromDisk("index.html") var err error
a.indexFile, err = a.loadFileFromDisk("index.html")
if err != nil { if err != nil {
return err return err
} }
a.indexFile, err = injectScript(string(indexHTML), `<script src="/wails/runtime.js"></script>`) a.indexFile, err = injectHTML(string(a.indexFile), `<div id="wails-spinner"></div>`)
if err != nil { if err != nil {
return err return err
} }
a.indexFile, err = injectScript(string(a.indexFile), `<script src="/wails/ipc.js"></script>`) a.indexFile, err = injectHTML(string(a.indexFile), `<script src="/wails/ipc.js"></script>`)
if err != nil {
return err
}
a.indexFile, err = injectHTML(string(a.indexFile), `<script src="/wails/runtime.js"></script>`)
if err != nil { if err != nil {
return err return err
} }
@ -84,6 +88,6 @@ func (a *AssetServer) Load(filename string) ([]byte, string, error) {
if err != nil { if err != nil {
return nil, "", err return nil, "", err
} }
mimeType := http.DetectContentType(content) mimeType := GetMimetype(filename, content)
return content, mimeType, nil return content, mimeType, nil
} }

View File

@ -6,16 +6,16 @@ import (
"strings" "strings"
) )
func injectScript(input string, script string) ([]byte, error) { func injectHTML(input string, html string) ([]byte, error) {
splits := strings.Split(input, "<head>") splits := strings.Split(input, "</body>")
if len(splits) != 2 { if len(splits) != 2 {
return nil, fmt.Errorf("unable to locate a </head> tag in your html") return nil, fmt.Errorf("unable to locate a </body> tag in your html")
} }
var result bytes.Buffer var result bytes.Buffer
result.WriteString(splits[0]) result.WriteString(splits[0])
result.WriteString("<head>") result.WriteString(html)
result.WriteString(script) result.WriteString("</body>")
result.WriteString(splits[1]) result.WriteString(splits[1])
return result.Bytes(), nil return result.Bytes(), nil
} }

View File

@ -0,0 +1,36 @@
package assetserver
import (
"net/http"
"sync"
)
import "github.com/gabriel-vasile/mimetype"
var (
cache = map[string]string{}
mutex sync.Mutex
)
func GetMimetype(filename string, data []byte) string {
mutex.Lock()
defer mutex.Unlock()
result := cache[filename]
if result != "" {
return result
}
detect := mimetype.Detect(data)
if detect == nil {
result = http.DetectContentType(data)
} else {
result = detect.String()
}
if result == "" {
result = "application/octet-stream"
}
cache[filename] = result
return result
}

View File

@ -41,6 +41,10 @@ type Frontend struct {
servingFromDisk bool servingFromDisk bool
} }
func (f *Frontend) WindowReload() {
f.ExecJS("runtime.WindowReload();")
}
func (f *Frontend) Run(ctx context.Context) error { func (f *Frontend) Run(ctx context.Context) error {
mainWindow := NewWindow(nil, f.frontendOptions) mainWindow := NewWindow(nil, f.frontendOptions)
@ -211,9 +215,7 @@ func (f *Frontend) Notify(name string, data ...interface{}) {
f.logger.Error(err.Error()) f.logger.Error(err.Error())
return return
} }
f.mainWindow.Dispatch(func() { f.ExecJS(`window.wails.EventsNotify('` + string(payload) + `');`)
f.chromium.Eval(`window.wails.EventsNotify('` + string(payload) + `');`)
})
} }
func (f *Frontend) processRequest(req *edge.ICoreWebView2WebResourceRequest, args *edge.ICoreWebView2WebResourceRequestedEventArgs) { func (f *Frontend) processRequest(req *edge.ICoreWebView2WebResourceRequest, args *edge.ICoreWebView2WebResourceRequestedEventArgs) {
@ -288,6 +290,12 @@ func (f *Frontend) startDrag() error {
return nil return nil
} }
func (f *Frontend) ExecJS(js string) {
f.mainWindow.Dispatch(func() {
f.chromium.Eval(js)
})
}
func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher) *Frontend { func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher) *Frontend {
result := &Frontend{ result := &Frontend{

View File

@ -39,9 +39,19 @@ type DevServer struct {
desktopFrontend frontend.Frontend desktopFrontend frontend.Frontend
} }
func (d *DevServer) WindowReload() {
d.broadcast("reload")
}
func (d *DevServer) Run(ctx context.Context) error { func (d *DevServer) Run(ctx context.Context) error {
d.ctx = ctx d.ctx = ctx
d.server.Get("/wails/reload", func(fctx *fiber.Ctx) error {
d.WindowReload()
d.desktopFrontend.WindowReload()
return nil
})
d.server.Get("/wails/ipc", websocket.New(func(c *websocket.Conn) { d.server.Get("/wails/ipc", websocket.New(func(c *websocket.Conn) {
d.newWebsocketSession(c) d.newWebsocketSession(c)
// websocket.Conn bindings https://pkg.go.dev/github.com/fasthttp/websocket?tab=doc#pkg-index // websocket.Conn bindings https://pkg.go.dev/github.com/fasthttp/websocket?tab=doc#pkg-index
@ -55,14 +65,13 @@ func (d *DevServer) Run(ctx context.Context) error {
if mt, msg, err = c.ReadMessage(); err != nil { if mt, msg, err = c.ReadMessage(); err != nil {
break break
} }
d.logger.Info("[%p] %s", c, msg) //d.logger.Info("[%p] %s", c, msg)
if string(msg) == "drag" { if string(msg) == "drag" {
continue continue
} }
if len(msg) > 2 && strings.HasPrefix(string(msg), "EE") { if len(msg) > 2 && strings.HasPrefix(string(msg), "EE") {
d.broadcast(string(msg)[2:]) d.notifyExcludingSender(msg, c)
//d.broadcastExcludingSender(string(msg)[2:], c)
continue continue
} }
@ -272,8 +281,6 @@ func (d *DevServer) newWebsocketSession(c *websocket.Conn) {
}) })
d.websocketClients[c] = struct{}{} d.websocketClients[c] = struct{}{}
d.LogInfo(fmt.Sprintf("Websocket client %p connected", c)) d.LogInfo(fmt.Sprintf("Websocket client %p connected", c))
// Send the starttime to see if the client needs to reload
c.WriteMessage(websocket.TextMessage, []byte("T"+d.starttime))
} }
type EventNotify struct { type EventNotify struct {
@ -322,6 +329,19 @@ func (d *DevServer) broadcastExcludingSender(message string, sender *websocket.C
} }
} }
func (d *DevServer) notifyExcludingSender(eventMessage []byte, sender *websocket.Conn) {
message := "n" + string(eventMessage[2:])
d.broadcastExcludingSender(message, sender)
var notifyMessage EventNotify
err := json.Unmarshal(eventMessage[2:], &notifyMessage)
if err != nil {
d.logger.Error(err.Error())
return
}
d.desktopFrontend.Notify(notifyMessage.Name, notifyMessage.Data...)
}
func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher, menuManager *menumanager.Manager) *DevServer { func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher, menuManager *menumanager.Manager) *DevServer {
result := &DevServer{ result := &DevServer{
ctx: ctx, ctx: ctx,
@ -336,7 +356,6 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
}), }),
menuManager: menuManager, menuManager: menuManager,
websocketClients: make(map[*websocket.Conn]struct{}), websocketClients: make(map[*websocket.Conn]struct{}),
starttime: time.Now().String(),
} }
return result return result
} }

View File

@ -85,6 +85,7 @@ type Frontend interface {
WindowFullscreen() WindowFullscreen()
WindowUnFullscreen() WindowUnFullscreen()
WindowSetColour(colour int) WindowSetColour(colour int)
WindowReload()
// Menus // Menus
SetApplicationMenu(menu *menu.Menu) SetApplicationMenu(menu *menu.Menu)

View File

@ -12,6 +12,7 @@ import * as Log from './log';
import {eventListeners, EventsEmit, EventsNotify, EventsOff, EventsOn, EventsOnce, EventsOnMultiple} from './events'; import {eventListeners, EventsEmit, EventsNotify, EventsOff, EventsOn, EventsOnce, EventsOnMultiple} from './events';
import {Callback, callbacks} from './calls'; import {Callback, callbacks} from './calls';
import {SetBindings} from "./bindings"; import {SetBindings} from "./bindings";
import {WindowReload} from "./window";
// Backend is where the Go struct wrappers get bound to // Backend is where the Go struct wrappers get bound to
window.backend = {}; window.backend = {};
@ -23,6 +24,7 @@ window.runtime = {
EventsOnMultiple, EventsOnMultiple,
EventsEmit, EventsEmit,
EventsOff, EventsOff,
WindowReload,
}; };
// Initialise global if not already // Initialise global if not already

View File

@ -0,0 +1,15 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The lightweight framework for web-like apps
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
export function WindowReload() {
window.location.reload();
}

View File

@ -0,0 +1,54 @@
<script>
import {overlayVisible} from './store'
import {fade,} from 'svelte/transition';
</script>
{#if $overlayVisible }
<div class="wails-reconnect-overlay" transition:fade="{{ duration: 300 }}">
<div class="wails-reconnect-overlay-content">
<div class="wails-reconnect-overlay-loadingspinner"></div>
</div>
</div>
{/if}
<style>
.wails-reconnect-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
backdrop-filter: blur(2px) saturate(0%) contrast(50%) brightness(25%);
z-index: 999999
}
.wails-reconnect-overlay-content {
position: relative;
top: 50%;
transform: translateY(-50%);
margin: 0;
background-image: url(data:image/png;base64,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);
background-repeat: no-repeat;
background-position: center
}
.wails-reconnect-overlay-loadingspinner {
pointer-events: none;
width: 2.5em;
height: 2.5em;
border: .4em solid transparent;
border-color: #f00 #eee0 #f00 #eee0;
border-radius: 50%;
animation: loadingspin 1s linear infinite;
margin: auto;
padding: 2.5em
}
@keyframes loadingspin {
100% {
transform: rotate(360deg);
}
}
</style>

View File

@ -10,7 +10,7 @@ let sveltePlugin = {
build.onLoad({filter: /\.svelte$/}, async (args) => { build.onLoad({filter: /\.svelte$/}, async (args) => {
// This converts a message in Svelte's format to esbuild's format // This converts a message in Svelte's format to esbuild's format
let convertMessage = ({message, start, end}) => { let convertMessage = ({message, start, end}) => {
let location let location;
if (start && end) { if (start && end) {
let lineText = source.split(/\r\n|\r|\n/g)[start.line - 1]; let lineText = source.split(/\r\n|\r|\n/g)[start.line - 1];
let lineEnd = start.line === end.line ? end.column : lineText.length; let lineEnd = start.line === end.line ? end.column : lineText.length;

View File

@ -10,6 +10,16 @@ The lightweight framework for web-like apps
/* jshint esversion: 6 */ /* jshint esversion: 6 */
import {log} from "./log"; import {log} from "./log";
import Overlay from "./Overlay.svelte";
import {hideOverlay, showOverlay} from "./store";
let components = {};
// Sets up the overlay
components.overlay = new Overlay({
target: document.body,
anchor: document.querySelector('#wails-spinner'),
});
let websocket = null; let websocket = null;
let connectTimer; let connectTimer;
@ -26,7 +36,6 @@ window.onbeforeunload = function () {
// ...and attempt to connect // ...and attempt to connect
connect(); connect();
function setupIPCBridge() { function setupIPCBridge() {
window.WailsInvoke = (message) => { window.WailsInvoke = (message) => {
websocket.send(message); websocket.send(message);
@ -36,6 +45,7 @@ function setupIPCBridge() {
// Handles incoming websocket connections // Handles incoming websocket connections
function handleConnect() { function handleConnect() {
log('Connected to backend'); log('Connected to backend');
hideOverlay();
setupIPCBridge(); setupIPCBridge();
clearInterval(connectTimer); clearInterval(connectTimer);
websocket.onclose = handleDisconnect; websocket.onclose = handleDisconnect;
@ -46,6 +56,7 @@ function handleConnect() {
function handleDisconnect() { function handleDisconnect() {
log('Disconnected from backend'); log('Disconnected from backend');
websocket = null; websocket = null;
showOverlay();
connect(); connect();
} }
@ -63,100 +74,26 @@ function connect() {
return false; return false;
}; };
} }
}, 1000); }, 250);
} }
function handleMessage(message) { function handleMessage(message) {
// ignore if (message.data === "reload") {
if (message === "drag") { window.runtime.WindowReload();
return; return;
} }
// As a bridge we ignore js and css injections // As a bridge we ignore js and css injections
switch (message.data[0]) { switch (message.data[0]) {
// Wails library - inject!
// case 'b':
// message = message.data.slice(1);
// addScript(message);
// log('Loaded Wails Runtime');
//
// // We need to now send a message to the backend telling it
// // we have loaded (System Start)
// window.wailsInvoke('SS');
//
// // Now wails runtime is loaded, wails for the ready event
// // and callback to the main app
// // window.wails.Events.On('wails:loaded', function () {
// if (callback) {
// log('Notifying application');
// callback(window.wails);
// }
// // });
// break;
// Notifications // Notifications
case 'n': case 'n':
window.wails.EventsNotify(message.data.slice(1)); window.wails.EventsNotify(message.data.slice(1));
break; break;
// // // Binding
// // case 'b':
// // const binding = message.data.slice(1);
// // //log("Binding: " + binding)
// // window.wails._.NewBinding(binding);
// // break;
// // // Call back
case 'c': case 'c':
const callbackData = message.data.slice(1); const callbackData = message.data.slice(1);
window.wails.Callback(callbackData); window.wails.Callback(callbackData);
break; break;
// Application menu
/*
case 'M':
const menuData = message.data.slice(1);
window.appmenu = JSON.parse(menuData);
ApplicationMenu.set(window.appmenu);
console.log("Set application menu");
break;
*/
case 'T':
const serverStartTime = message.data.slice(1);
const lastServerStartTime = localStorage.getItem('wails:lastServerStartTime');
if (lastServerStartTime === null) {
localStorage.setItem('wails:lastServerStartTime', serverStartTime);
}
if (serverStartTime !== lastServerStartTime) {
localStorage.setItem('wails:lastServerStartTime', serverStartTime);
location.reload(true);
console.log("Reloaded");
}
break;
// // Tray
// case 'T':
// const trayMessage = message.data.slice(1);
// switch (trayMessage[0]) {
// case 'S':
// // Set tray
// const trayJSON = trayMessage.slice(1);
// let tray = JSON.parse(trayJSON);
// setTray(tray);
// break;
// case 'U':
// // Update label
// const updateTrayLabelJSON = trayMessage.slice(1);
// let trayLabelData = JSON.parse(updateTrayLabelJSON);
// updateTrayLabel(trayLabelData);
// break;
// case 'D':
// // Delete Tray Menu
// const id = trayMessage.slice(1);
// deleteTrayMenu(id);
// break;
// default:
// log('Unknown tray message: ' + message.data);
// }
// break;
default: default:
log('Unknown message: ' + message.data); log('Unknown message: ' + message.data);
} }

View File

@ -10,7 +10,6 @@
"author": "Lea Anthony <lea.anthony@gmail.com>", "author": "Lea Anthony <lea.anthony@gmail.com>",
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"@zerodevx/svelte-toast": "^0.5.1",
"esbuild": "^0.12.17", "esbuild": "^0.12.17",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"svelte": "^3.42.2" "svelte": "^3.42.2"

View File

@ -0,0 +1,12 @@
import {writable} from 'svelte/store';
/** Overlay */
export const overlayVisible = writable(false);
export function showOverlay() {
overlayVisible.set(true);
}
export function hideOverlay() {
overlayVisible.set(false);
}

File diff suppressed because one or more lines are too long

View File

@ -6,7 +6,7 @@
"scripts": { "scripts": {
"build": "run-p build:*", "build": "run-p build:*",
"build:ipc-windows": "esbuild desktop/ipc.js --bundle --minify --outfile=ipc_windows.js --define:PLATFORM='windows'", "build:ipc-windows": "esbuild desktop/ipc.js --bundle --minify --outfile=ipc_windows.js --define:PLATFORM='windows'",
"build:ipc-dev": "esbuild dev/main.js --bundle --minify --outfile=ipc_websocket.js", "build:ipc-dev": "cd dev && npm run build",
"build:runtime-desktop-prod": "esbuild desktop/main.js --bundle --minify --outfile=runtime_prod_desktop.js", "build:runtime-desktop-prod": "esbuild desktop/main.js --bundle --minify --outfile=runtime_prod_desktop.js",
"build:runtime-desktop-dev": "esbuild desktop/main.js --bundle --sourcemap=inline --outfile=runtime_dev_desktop.js", "build:runtime-desktop-dev": "esbuild desktop/main.js --bundle --sourcemap=inline --outfile=runtime_dev_desktop.js",
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
(()=>{var p=Object.defineProperty;var m=n=>p(n,"__esModule",{value:!0});var I=(n,e)=>{m(n);for(var t in e)p(n,t,{get:e[t],enumerable:!0})};var u={};I(u,{LogDebug:()=>W,LogError:()=>T,LogFatal:()=>C,LogInfo:()=>D,LogLevel:()=>A,LogPrint:()=>R,LogTrace:()=>S,LogWarning:()=>J,SetLogLevel:()=>j});function l(n,e){window.WailsInvoke("L"+n+e)}function S(n){l("T",n)}function R(n){l("P",n)}function W(n){l("D",n)}function D(n){l("I",n)}function J(n){l("W",n)}function T(n){l("E",n)}function C(n){l("F",n)}function j(n){l("S",n)}var A={TRACE:1,DEBUG:2,INFO:3,WARNING:4,ERROR:5};var E=class{constructor(e,t){t=t||-1,this.Callback=o=>(e.apply(null,o),t===-1?!1:(t-=1,t===0))}},s={};function d(n,e,t){s[n]=s[n]||[];let o=new E(e,t);s[n].push(o)}function v(n,e){d(n,e,-1)}function g(n,e){d(n,e,1)}function b(n){let e=n.name;if(s[e]){let t=s[e].slice();for(let o=0;o<s[e].length;o+=1){let i=s[e][o],r=n.data;i.Callback(r)&&t.splice(o,1)}s[e]=t}}function y(n){let e;try{e=JSON.parse(n)}catch(t){let o="Invalid JSON passed to Notify: "+n;throw new Error(o)}b(e)}function L(n){let e={name:n,data:[].slice.apply(arguments).slice(1)};b(e),window.WailsInvoke("EE"+JSON.stringify(e))}function k(n){s.delete(n),window.WailsInvoke("EX"+n)}var a={};function B(){var n=new Uint32Array(1);return window.crypto.getRandomValues(n)[0]}function F(){return Math.random()*9007199254740991}var f;window.crypto?f=B:f=F;function O(n,e,t){return t==null&&(t=0),new Promise(function(o,i){var r;do r=n+"-"+f();while(a[r]);var c;t>0&&(c=setTimeout(function(){i(Error("Call to "+n+" timed out. Request ID: "+r))},t)),a[r]={timeoutHandle:c,reject:i,resolve:o};try{let w={name:n,args:e,callbackID:r};window.WailsInvoke("C"+JSON.stringify(w))}catch(w){console.error(w)}})}function h(n){var e;try{e=JSON.parse(n)}catch(i){let r=`Invalid JSON passed to callback: ${i.message}. Message: ${n}`;throw wails.LogDebug(r),new Error(r)}var t=e.callbackid,o=a[t];if(!o){let i=`Callback '${t}' not registered!!!`;throw console.error(i),new Error(i)}clearTimeout(o.timeoutHandle),delete a[t],e.error?o.reject(e.error):o.resolve(e.result)}window.backend={};function x(n){try{n=JSON.parse(n)}catch(e){console.error(e)}window.backend=window.backend||{},Object.keys(n).forEach(e=>{window.backend[e]=window.backend[e]||{},Object.keys(n[e]).forEach(t=>{window.backend[e][t]=window.backend[e][t]||{},Object.keys(n[e][t]).forEach(o=>{window.backend[e][t][o]=function(){let i=0;function r(){let c=[].slice.call(arguments);return O([e,t,o].join("."),c,i)}return r.setTimeout=function(c){i=c},r.getTimeout=function(){return i},r}()})})})}window.backend={};window.runtime={...u,EventsOn:v,EventsOnce:g,EventsOnMultiple:d,EventsEmit:L,EventsOff:k};window.wails={Callback:h,EventsNotify:y,SetBindings:x,eventListeners:s,callbacks:a};window.wails.SetBindings(window.wailsbindings);delete window.wails.SetBindings;delete window.wailsbindings;window.addEventListener("mousedown",n=>{let e=n.target;for(;e!=null&&!e.hasAttribute("data-wails-no-drag");){if(e.hasAttribute("data-wails-drag")){window.WailsInvoke("drag");break}e=e.parentElement}});})(); (()=>{var p=Object.defineProperty;var I=n=>p(n,"__esModule",{value:!0});var S=(n,e)=>{I(n);for(var o in e)p(n,o,{get:e[o],enumerable:!0})};var f={};S(f,{LogDebug:()=>D,LogError:()=>C,LogFatal:()=>j,LogInfo:()=>J,LogLevel:()=>B,LogPrint:()=>W,LogTrace:()=>R,LogWarning:()=>T,SetLogLevel:()=>A});function l(n,e){window.WailsInvoke("L"+n+e)}function R(n){l("T",n)}function W(n){l("P",n)}function D(n){l("D",n)}function J(n){l("I",n)}function T(n){l("W",n)}function C(n){l("E",n)}function j(n){l("F",n)}function A(n){l("S",n)}var B={TRACE:1,DEBUG:2,INFO:3,WARNING:4,ERROR:5};var E=class{constructor(e,o){o=o||-1,this.Callback=t=>(e.apply(null,t),o===-1?!1:(o-=1,o===0))}},s={};function d(n,e,o){s[n]=s[n]||[];let t=new E(e,o);s[n].push(t)}function v(n,e){d(n,e,-1)}function g(n,e){d(n,e,1)}function b(n){let e=n.name;if(s[e]){let o=s[e].slice();for(let t=0;t<s[e].length;t+=1){let i=s[e][t],r=n.data;i.Callback(r)&&o.splice(t,1)}s[e]=o}}function y(n){let e;try{e=JSON.parse(n)}catch(o){let t="Invalid JSON passed to Notify: "+n;throw new Error(t)}b(e)}function L(n){let e={name:n,data:[].slice.apply(arguments).slice(1)};b(e),window.WailsInvoke("EE"+JSON.stringify(e))}function k(n){s.delete(n),window.WailsInvoke("EX"+n)}var a={};function F(){var n=new Uint32Array(1);return window.crypto.getRandomValues(n)[0]}function H(){return Math.random()*9007199254740991}var u;window.crypto?u=F:u=H;function O(n,e,o){return o==null&&(o=0),new Promise(function(t,i){var r;do r=n+"-"+u();while(a[r]);var c;o>0&&(c=setTimeout(function(){i(Error("Call to "+n+" timed out. Request ID: "+r))},o)),a[r]={timeoutHandle:c,reject:i,resolve:t};try{let w={name:n,args:e,callbackID:r};window.WailsInvoke("C"+JSON.stringify(w))}catch(w){console.error(w)}})}function h(n){var e;try{e=JSON.parse(n)}catch(i){let r=`Invalid JSON passed to callback: ${i.message}. Message: ${n}`;throw wails.LogDebug(r),new Error(r)}var o=e.callbackid,t=a[o];if(!t){let i=`Callback '${o}' not registered!!!`;throw console.error(i),new Error(i)}clearTimeout(t.timeoutHandle),delete a[o],e.error?t.reject(e.error):t.resolve(e.result)}window.backend={};function x(n){try{n=JSON.parse(n)}catch(e){console.error(e)}window.backend=window.backend||{},Object.keys(n).forEach(e=>{window.backend[e]=window.backend[e]||{},Object.keys(n[e]).forEach(o=>{window.backend[e][o]=window.backend[e][o]||{},Object.keys(n[e][o]).forEach(t=>{window.backend[e][o][t]=function(){let i=0;function r(){let c=[].slice.call(arguments);return O([e,o,t].join("."),c,i)}return r.setTimeout=function(c){i=c},r.getTimeout=function(){return i},r}()})})})}function m(){window.location.reload()}window.backend={};window.runtime={...f,EventsOn:v,EventsOnce:g,EventsOnMultiple:d,EventsEmit:L,EventsOff:k,WindowReload:m};window.wails={Callback:h,EventsNotify:y,SetBindings:x,eventListeners:s,callbacks:a};window.wails.SetBindings(window.wailsbindings);delete window.wails.SetBindings;delete window.wailsbindings;window.addEventListener("mousedown",n=>{let e=n.target;for(;e!=null&&!e.hasAttribute("data-wails-no-drag");){if(e.hasAttribute("data-wails-drag")){window.WailsInvoke("drag");break}e=e.parentElement}});})();

View File

@ -3,22 +3,18 @@ package process
import ( import (
"os" "os"
"os/exec" "os/exec"
"github.com/wailsapp/wails/v2/pkg/clilogger"
) )
// 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
cmd *exec.Cmd cmd *exec.Cmd
exitChannel chan bool 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(cmd string, args ...string) *Process {
result := &Process{ result := &Process{
logger: logger,
cmd: exec.Command(cmd, args...), cmd: exec.Command(cmd, args...),
exitChannel: make(chan bool, 1), exitChannel: make(chan bool, 1),
} }
@ -28,7 +24,7 @@ func NewProcess(logger *clilogger.CLILogger, cmd string, args ...string) *Proces
} }
// Start the process // Start the process
func (p *Process) Start() error { func (p *Process) Start(exitCodeChannel chan int) error {
err := p.cmd.Start() err := p.cmd.Start()
if err != nil { if err != nil {
@ -37,13 +33,14 @@ func (p *Process) Start() error {
p.Running = true p.Running = true
go func(cmd *exec.Cmd, running *bool, logger *clilogger.CLILogger, exitChannel chan bool) { go func(cmd *exec.Cmd, running *bool, exitChannel chan bool, exitCodeChannel chan int) {
logger.Println("Starting process (PID: %d)", cmd.Process.Pid) err := cmd.Wait()
_ = cmd.Wait() if err == nil {
logger.Println("Exiting process (PID: %d)", cmd.Process.Pid) exitCodeChannel <- 0
}
*running = false *running = false
exitChannel <- true exitChannel <- true
}(p.cmd, &p.Running, p.logger, p.exitChannel) }(p.cmd, &p.Running, p.exitChannel, exitCodeChannel)
return nil return nil
} }

View File

@ -28,6 +28,12 @@ func WindowCenter(ctx context.Context) {
appFrontend.WindowCenter() appFrontend.WindowCenter()
} }
// WindowReload will reload the window contents
func WindowReload(ctx context.Context) {
appFrontend := getFrontend(ctx)
appFrontend.WindowReload()
}
// WindowShow shows the window if hidden // WindowShow shows the window if hidden
func WindowShow(ctx context.Context) { func WindowShow(ctx context.Context) {
appFrontend := getFrontend(ctx) appFrontend := getFrontend(ctx)