diff --git a/v2/cmd/wails/internal/commands/dev/dev.go b/v2/cmd/wails/internal/commands/dev/dev.go
index 56a61492d..0b874072e 100644
--- a/v2/cmd/wails/internal/commands/dev/dev.go
+++ b/v2/cmd/wails/internal/commands/dev/dev.go
@@ -6,6 +6,7 @@ import (
"github.com/wailsapp/wails/v2/internal/project"
"io"
"log"
+ "net/http"
"os"
"os/signal"
"path/filepath"
@@ -40,6 +41,14 @@ func LogDarkYellow(message string, args ...interface{}) {
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
func AddSubcommand(app *clir.Cli, w io.Writer) error {
@@ -56,14 +65,24 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
assetDir := ""
command.StringFlag("assetdir", "Serve assets from the given directory", &assetDir)
- // extensions to trigger rebuilds
+ // extensions to trigger rebuilds of application
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
showWarnings := false
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 := 1
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)
app.PrintBanner()
- // TODO: Check you are in a project directory
cwd, err := os.Getwd()
if err != nil {
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.")
}
+ assetDir, err = filepath.Abs(assetDir)
+ if err != nil {
+ return err
+ }
+
if assetDir != "" && assetDir != projectConfig.AssetDirectory {
projectConfig.AssetDirectory = assetDir
err := projectConfig.Save()
@@ -115,13 +138,12 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
}(watcher)
var debugBinaryProcess *process.Process = nil
- var extensionsThatTriggerARebuild = strings.Split(extensions, ",")
+ var extensionsThatTriggerARebuild = sliceToMap(strings.Split(extensions, ","))
// Setup signal handler
quitChannel := make(chan os.Signal, 1)
signal.Notify(quitChannel, os.Interrupt, os.Kill, syscall.SIGTERM)
-
- debounceQuit := make(chan bool, 1)
+ exitCodeChannel := make(chan int, 1)
var passthruArgs []string
//if len(os.Args) > 2 {
@@ -130,7 +152,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
// Do initial build
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 {
return err
}
@@ -139,70 +161,17 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
}
// open browser
- err = browser.OpenURL("http://localhost:34115")
- if err != nil {
- return err
+ if openBrowser {
+ err = browser.OpenURL("http://localhost:34115")
+ if err != nil {
+ return err
+ }
}
if err != nil {
return err
}
var newBinaryProcess *process.Process
- go debounce(100*time.Millisecond, watcher.Events, debounceQuit, func(event fsnotify.Event) {
- // logger.Println("event: %+v", event)
-
- // 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
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")) {
return
}
+ //println("Watching", dir)
err = watcher.Add(dir)
if err != nil {
logger.Fatal(err.Error())
}
})
- // Wait until we get a quit signal
+ // Main Loop
quit := false
+ // Use 100ms debounce
+ interval := 100 * time.Millisecond
+ timer := time.NewTimer(interval)
+ rebuild := false
+ reload := false
for quit == false {
+ //reload := false
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:
LogGreen("\nCaught quit")
- // Notify debouncer to quit
- debounceQuit <- true
quit = true
}
}
@@ -267,26 +304,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
return nil
}
-// Credit: https://drailing.net/2018/01/debounce-function-for-golang/
-func debounce(interval time.Duration, input chan fsnotify.Event, quitChannel chan bool, cb func(arg fsnotify.Event)) {
- 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) {
+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) {
appBinary, err := buildApp(logger, ldflags, compilerCommand, verbosity)
println()
@@ -322,8 +340,8 @@ func restartApp(logger *clilogger.CLILogger, ldflags string, compilerCommand str
if len(passthruArgs) > 0 {
args.AddSlice(passthruArgs)
}
- newProcess := process.NewProcess(logger, appBinary, args.AsSlice()...)
- err = newProcess.Start()
+ newProcess := process.NewProcess(appBinary, args.AsSlice()...)
+ err = newProcess.Start(exitCodeChannel)
if err != nil {
// Remove binary
deleteError := fs.DeleteFile(appBinary)
diff --git a/v2/go.mod b/v2/go.mod
index 229b70d30..93ef72775 100644
--- a/v2/go.mod
+++ b/v2/go.mod
@@ -6,6 +6,7 @@ require (
github.com/Masterminds/semver v1.5.0
github.com/fatih/structtag v1.2.0
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-git/v5 v5.3.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/mod v0.4.1 // indirect
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
nhooyr.io/websocket v1.8.6
)
diff --git a/v2/go.sum b/v2/go.sum
index 8a11fdb7c..9c29cab1b 100644
--- a/v2/go.sum
+++ b/v2/go.sum
@@ -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/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/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
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.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/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/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/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
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/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
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.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
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/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
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.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
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/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.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
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/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
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/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/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc=
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/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.12.2 h1:2KCfW3I9M7nSc5wOqXAlW2v2U6v+w6cbjvbfp+OykW8=
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/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/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/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/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
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/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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
github.com/olekukonko/tablewriter v0.0.4/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/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/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
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.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
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.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/xyproto/xpm v1.2.1 h1:trdvGjjWBsOOKzBBUPT6JvaIQM3acJEEYfbxN7M96wg=
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/ztrue/tracerr v0.3.0 h1:lDi6EgEYhPYPnKcjsYzmWw4EkFEoA/gfe+I9Y5f+h6Y=
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-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-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/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-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
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-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-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-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-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/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
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.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
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/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=
diff --git a/v2/internal/frontend/assetserver/assetserver_desktop.go b/v2/internal/frontend/assetserver/assetserver_desktop.go
index 962f5f9ff..36d6c77d2 100644
--- a/v2/internal/frontend/assetserver/assetserver_desktop.go
+++ b/v2/internal/frontend/assetserver/assetserver_desktop.go
@@ -10,7 +10,6 @@ import (
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
"github.com/wailsapp/wails/v2/internal/logger"
"io/fs"
- "net/http"
"path/filepath"
"strings"
)
@@ -103,11 +102,11 @@ func (a *DesktopAssetServer) init(assets embed.FS) error {
if err != nil {
return err
}
- a.indexFile, err = injectScript(string(indexHTML), ``)
+ a.indexFile, err = injectHTML(string(indexHTML), ``)
if err != nil {
return err
}
- a.indexFile, err = injectScript(string(a.indexFile), ``)
+ a.indexFile, err = injectHTML(string(a.indexFile), ``)
if err != nil {
return err
}
@@ -130,6 +129,6 @@ func (a *DesktopAssetServer) Load(filename string) ([]byte, string, error) {
if err != nil {
return nil, "", err
}
- mimeType := http.DetectContentType(content)
+ mimeType := GetMimetype(filename, content)
return content, mimeType, nil
}
diff --git a/v2/internal/frontend/assetserver/assetserver_dev.go b/v2/internal/frontend/assetserver/assetserver_dev.go
index a84481869..8ab9ec918 100644
--- a/v2/internal/frontend/assetserver/assetserver_dev.go
+++ b/v2/internal/frontend/assetserver/assetserver_dev.go
@@ -18,7 +18,6 @@ It injects a websocket based IPC script into `index.html`.
*/
import (
- "net/http"
"os"
)
@@ -53,15 +52,20 @@ func (a *AssetServer) loadFileFromDisk(filename string) ([]byte, 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 {
return err
}
- a.indexFile, err = injectScript(string(indexHTML), ``)
+ a.indexFile, err = injectHTML(string(a.indexFile), `
`)
if err != nil {
return err
}
- a.indexFile, err = injectScript(string(a.indexFile), ``)
+ a.indexFile, err = injectHTML(string(a.indexFile), ``)
+ if err != nil {
+ return err
+ }
+ a.indexFile, err = injectHTML(string(a.indexFile), ``)
if err != nil {
return err
}
@@ -84,6 +88,6 @@ func (a *AssetServer) Load(filename string) ([]byte, string, error) {
if err != nil {
return nil, "", err
}
- mimeType := http.DetectContentType(content)
+ mimeType := GetMimetype(filename, content)
return content, mimeType, nil
}
diff --git a/v2/internal/frontend/assetserver/common.go b/v2/internal/frontend/assetserver/common.go
index c66b66e09..826aee4c3 100644
--- a/v2/internal/frontend/assetserver/common.go
+++ b/v2/internal/frontend/assetserver/common.go
@@ -6,16 +6,16 @@ import (
"strings"
)
-func injectScript(input string, script string) ([]byte, error) {
- splits := strings.Split(input, "")
+func injectHTML(input string, html string) ([]byte, error) {
+ splits := strings.Split(input, "")
if len(splits) != 2 {
- return nil, fmt.Errorf("unable to locate a tag in your html")
+ return nil, fmt.Errorf("unable to locate a tag in your html")
}
var result bytes.Buffer
result.WriteString(splits[0])
- result.WriteString("
")
- result.WriteString(script)
+ result.WriteString(html)
+ result.WriteString("")
result.WriteString(splits[1])
return result.Bytes(), nil
}
diff --git a/v2/internal/frontend/assetserver/mimecache.go b/v2/internal/frontend/assetserver/mimecache.go
new file mode 100644
index 000000000..e5dab20ec
--- /dev/null
+++ b/v2/internal/frontend/assetserver/mimecache.go
@@ -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
+}
diff --git a/v2/internal/frontend/desktop/windows/frontend.go b/v2/internal/frontend/desktop/windows/frontend.go
index aed85625e..5d71601ba 100644
--- a/v2/internal/frontend/desktop/windows/frontend.go
+++ b/v2/internal/frontend/desktop/windows/frontend.go
@@ -41,6 +41,10 @@ type Frontend struct {
servingFromDisk bool
}
+func (f *Frontend) WindowReload() {
+ f.ExecJS("runtime.WindowReload();")
+}
+
func (f *Frontend) Run(ctx context.Context) error {
mainWindow := NewWindow(nil, f.frontendOptions)
@@ -211,9 +215,7 @@ func (f *Frontend) Notify(name string, data ...interface{}) {
f.logger.Error(err.Error())
return
}
- f.mainWindow.Dispatch(func() {
- f.chromium.Eval(`window.wails.EventsNotify('` + string(payload) + `');`)
- })
+ f.ExecJS(`window.wails.EventsNotify('` + string(payload) + `');`)
}
func (f *Frontend) processRequest(req *edge.ICoreWebView2WebResourceRequest, args *edge.ICoreWebView2WebResourceRequestedEventArgs) {
@@ -288,6 +290,12 @@ func (f *Frontend) startDrag() error {
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 {
result := &Frontend{
diff --git a/v2/internal/frontend/devserver/devserver.go b/v2/internal/frontend/devserver/devserver.go
index 0616468cb..8ae88e88f 100644
--- a/v2/internal/frontend/devserver/devserver.go
+++ b/v2/internal/frontend/devserver/devserver.go
@@ -39,9 +39,19 @@ type DevServer struct {
desktopFrontend frontend.Frontend
}
+func (d *DevServer) WindowReload() {
+ d.broadcast("reload")
+}
+
func (d *DevServer) Run(ctx context.Context) error {
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.newWebsocketSession(c)
// 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 {
break
}
- d.logger.Info("[%p] %s", c, msg)
+ //d.logger.Info("[%p] %s", c, msg)
if string(msg) == "drag" {
continue
}
if len(msg) > 2 && strings.HasPrefix(string(msg), "EE") {
- d.broadcast(string(msg)[2:])
- //d.broadcastExcludingSender(string(msg)[2:], c)
+ d.notifyExcludingSender(msg, c)
continue
}
@@ -272,8 +281,6 @@ func (d *DevServer) newWebsocketSession(c *websocket.Conn) {
})
d.websocketClients[c] = struct{}{}
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 {
@@ -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:], ¬ifyMessage)
+ 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 {
result := &DevServer{
ctx: ctx,
@@ -336,7 +356,6 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
}),
menuManager: menuManager,
websocketClients: make(map[*websocket.Conn]struct{}),
- starttime: time.Now().String(),
}
return result
}
diff --git a/v2/internal/frontend/frontend.go b/v2/internal/frontend/frontend.go
index 41f908318..8a9433e04 100644
--- a/v2/internal/frontend/frontend.go
+++ b/v2/internal/frontend/frontend.go
@@ -85,6 +85,7 @@ type Frontend interface {
WindowFullscreen()
WindowUnFullscreen()
WindowSetColour(colour int)
+ WindowReload()
// Menus
SetApplicationMenu(menu *menu.Menu)
diff --git a/v2/internal/frontend/runtime/desktop/main.js b/v2/internal/frontend/runtime/desktop/main.js
index 61cc99a0f..0512d7e38 100644
--- a/v2/internal/frontend/runtime/desktop/main.js
+++ b/v2/internal/frontend/runtime/desktop/main.js
@@ -12,6 +12,7 @@ import * as Log from './log';
import {eventListeners, EventsEmit, EventsNotify, EventsOff, EventsOn, EventsOnce, EventsOnMultiple} from './events';
import {Callback, callbacks} from './calls';
import {SetBindings} from "./bindings";
+import {WindowReload} from "./window";
// Backend is where the Go struct wrappers get bound to
window.backend = {};
@@ -23,6 +24,7 @@ window.runtime = {
EventsOnMultiple,
EventsEmit,
EventsOff,
+ WindowReload,
};
// Initialise global if not already
diff --git a/v2/internal/frontend/runtime/desktop/window.js b/v2/internal/frontend/runtime/desktop/window.js
new file mode 100644
index 000000000..c4cdf22c7
--- /dev/null
+++ b/v2/internal/frontend/runtime/desktop/window.js
@@ -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();
+}
diff --git a/v2/internal/frontend/runtime/dev/Overlay.svelte b/v2/internal/frontend/runtime/dev/Overlay.svelte
new file mode 100644
index 000000000..dfe02b21b
--- /dev/null
+++ b/v2/internal/frontend/runtime/dev/Overlay.svelte
@@ -0,0 +1,54 @@
+
+
+{#if $overlayVisible }
+
+{/if}
+
+
\ No newline at end of file
diff --git a/v2/internal/frontend/runtime/dev/build.js b/v2/internal/frontend/runtime/dev/build.js
index 6106b8ce5..3557a6cd7 100644
--- a/v2/internal/frontend/runtime/dev/build.js
+++ b/v2/internal/frontend/runtime/dev/build.js
@@ -10,7 +10,7 @@ let sveltePlugin = {
build.onLoad({filter: /\.svelte$/}, async (args) => {
// This converts a message in Svelte's format to esbuild's format
let convertMessage = ({message, start, end}) => {
- let location
+ let location;
if (start && end) {
let lineText = source.split(/\r\n|\r|\n/g)[start.line - 1];
let lineEnd = start.line === end.line ? end.column : lineText.length;
diff --git a/v2/internal/frontend/runtime/dev/main.js b/v2/internal/frontend/runtime/dev/main.js
index bf65807de..c3a8dd57c 100644
--- a/v2/internal/frontend/runtime/dev/main.js
+++ b/v2/internal/frontend/runtime/dev/main.js
@@ -10,6 +10,16 @@ The lightweight framework for web-like apps
/* jshint esversion: 6 */
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 connectTimer;
@@ -26,7 +36,6 @@ window.onbeforeunload = function () {
// ...and attempt to connect
connect();
-
function setupIPCBridge() {
window.WailsInvoke = (message) => {
websocket.send(message);
@@ -36,6 +45,7 @@ function setupIPCBridge() {
// Handles incoming websocket connections
function handleConnect() {
log('Connected to backend');
+ hideOverlay();
setupIPCBridge();
clearInterval(connectTimer);
websocket.onclose = handleDisconnect;
@@ -46,6 +56,7 @@ function handleConnect() {
function handleDisconnect() {
log('Disconnected from backend');
websocket = null;
+ showOverlay();
connect();
}
@@ -63,100 +74,26 @@ function connect() {
return false;
};
}
- }, 1000);
+ }, 250);
}
function handleMessage(message) {
- // ignore
- if (message === "drag") {
+ if (message.data === "reload") {
+ window.runtime.WindowReload();
return;
}
// As a bridge we ignore js and css injections
switch (message.data[0]) {
- // Wails library - inject!
- // case 'b':
- // message = message.data.slice(1);
- // addScript(message);
- // log('Loaded Wails Runtime');
- //
- // // We need to now send a message to the backend telling it
- // // we have loaded (System Start)
- // window.wailsInvoke('SS');
- //
- // // Now wails runtime is loaded, wails for the ready event
- // // and callback to the main app
- // // window.wails.Events.On('wails:loaded', function () {
- // if (callback) {
- // log('Notifying application');
- // callback(window.wails);
- // }
- // // });
- // break;
// Notifications
case 'n':
window.wails.EventsNotify(message.data.slice(1));
break;
- // // // Binding
- // // case 'b':
- // // const binding = message.data.slice(1);
- // // //log("Binding: " + binding)
- // // window.wails._.NewBinding(binding);
- // // break;
- // // // Call back
case 'c':
const callbackData = message.data.slice(1);
window.wails.Callback(callbackData);
break;
-
- // 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:
log('Unknown message: ' + message.data);
}
diff --git a/v2/internal/frontend/runtime/dev/package.json b/v2/internal/frontend/runtime/dev/package.json
index 843ce7761..a3e719b42 100644
--- a/v2/internal/frontend/runtime/dev/package.json
+++ b/v2/internal/frontend/runtime/dev/package.json
@@ -10,7 +10,6 @@
"author": "Lea Anthony ",
"license": "ISC",
"devDependencies": {
- "@zerodevx/svelte-toast": "^0.5.1",
"esbuild": "^0.12.17",
"npm-run-all": "^4.1.5",
"svelte": "^3.42.2"
diff --git a/v2/internal/frontend/runtime/dev/store.js b/v2/internal/frontend/runtime/dev/store.js
new file mode 100644
index 000000000..fc085570b
--- /dev/null
+++ b/v2/internal/frontend/runtime/dev/store.js
@@ -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);
+}
diff --git a/v2/internal/frontend/runtime/ipc_websocket.js b/v2/internal/frontend/runtime/ipc_websocket.js
index 217f10b49..a00933d45 100644
--- a/v2/internal/frontend/runtime/ipc_websocket.js
+++ b/v2/internal/frontend/runtime/ipc_websocket.js
@@ -1 +1,21 @@
-(()=>{function o(e){console.log("%c wails dev %c "+e+" ","background: #aa0000; color: #fff; border-radius: 3px 0px 0px 3px; padding: 1px; font-size: 0.7rem","background: #009900; color: #fff; border-radius: 0px 3px 3px 0px; padding: 1px; font-size: 0.7rem")}var n=null,l;window.onbeforeunload=function(){n&&(n.onclose=function(){},n.close(),n=null)};c();function i(){window.WailsInvoke=e=>{n.send(e)}}function s(){o("Connected to backend"),i(),clearInterval(l),n.onclose=d,n.onmessage=f}function d(){o("Disconnected from backend"),n=null,c()}function c(){l=setInterval(function(){n==null&&(n=new WebSocket("ws://"+window.location.hostname+":34115/wails/ipc"),n.onopen=s,n.onerror=function(e){return e.stopImmediatePropagation(),e.stopPropagation(),e.preventDefault(),n=null,!1})},1e3)}function f(e){if(e!=="drag")switch(e.data[0]){case"n":window.wails.EventsNotify(e.data.slice(1));break;case"c":let r=e.data.slice(1);window.wails.Callback(r);break;case"T":let t=e.data.slice(1),a=localStorage.getItem("wails:lastServerStartTime");a===null&&localStorage.setItem("wails:lastServerStartTime",t),t!==a&&(localStorage.setItem("wails:lastServerStartTime",t),location.reload(!0),console.log("Reloaded"));break;default:o("Unknown message: "+e.data)}}})();
+(()=>{function E(t){console.log("%c wails dev %c "+t+" ","background: #aa0000; color: #fff; border-radius: 3px 0px 0px 3px; padding: 1px; font-size: 0.7rem","background: #009900; color: #fff; border-radius: 0px 3px 3px 0px; padding: 1px; font-size: 0.7rem")}function p(){}var j=t=>t;function G(t){return t()}function tt(){return Object.create(null)}function b(t){t.forEach(G)}function S(t){return typeof t=="function"}function O(t,e){return t!=t?e==e:t!==e||t&&typeof t=="object"||typeof t=="function"}function et(t){return Object.keys(t).length===0}function nt(t,...e){if(t==null)return p;let n=t.subscribe(...e);return n.unsubscribe?()=>n.unsubscribe():n}function it(t,e,n){t.$$.on_destroy.push(nt(e,n))}var rt=typeof window!="undefined",It=rt?()=>window.performance.now():()=>Date.now(),q=rt?t=>requestAnimationFrame(t):p;var v=new Set;function ot(t){v.forEach(e=>{e.c(t)||(v.delete(e),e.f())}),v.size!==0&&q(ot)}function Et(t){let e;return v.size===0&&q(ot),{promise:new Promise(n=>{v.add(e={c:t,f:n})}),abort(){v.delete(e)}}}var st=!1;function jt(){st=!0}function Ot(){st=!1}function Dt(t,e){t.appendChild(e)}function ct(t,e,n){let i=K(t);if(!i.getElementById(e)){let r=A("style");r.id=e,r.textContent=n,lt(i,r)}}function K(t){if(!t)return document;let e=t.getRootNode?t.getRootNode():t.ownerDocument;return e.host?e:document}function At(t){let e=A("style");return lt(K(t),e),e}function lt(t,e){Dt(t.head||t,e)}function P(t,e,n){t.insertBefore(e,n||null)}function D(t){t.parentNode.removeChild(t)}function A(t){return document.createElement(t)}function Bt(t){return document.createTextNode(t)}function ut(){return Bt("")}function at(t,e,n){n==null?t.removeAttribute(e):t.getAttribute(e)!==n&&t.setAttribute(e,n)}function Lt(t){return Array.from(t.childNodes)}function Jt(t,e,n=!1){let i=document.createEvent("CustomEvent");return i.initCustomEvent(t,n,!1,e),i}var R=new Set,B=0;function zt(t){let e=5381,n=t.length;for(;n--;)e=(e<<5)-e^t.charCodeAt(n);return e>>>0}function ft(t,e,n,i,r,c,s,l=0){let a=16.666/i,o=`{
+`;for(let g=0;g<=1;g+=a){let F=e+(n-e)*c(g);o+=g*100+`%{${s(F,1-F)}}
+`}let y=o+`100% {${s(n,1-n)}}
+}`,f=`__svelte_${zt(y)}_${l}`,u=K(t);R.add(u);let h=u.__svelte_stylesheet||(u.__svelte_stylesheet=At(t).sheet),_=u.__svelte_rules||(u.__svelte_rules={});_[f]||(_[f]=!0,h.insertRule(`@keyframes ${f} ${y}`,h.cssRules.length));let w=t.style.animation||"";return t.style.animation=`${w?`${w}, `:""}${f} ${i}ms linear ${r}ms 1 both`,B+=1,f}function Tt(t,e){let n=(t.style.animation||"").split(", "),i=n.filter(e?c=>c.indexOf(e)<0:c=>c.indexOf("__svelte")===-1),r=n.length-i.length;r&&(t.style.animation=i.join(", "),B-=r,B||Ht())}function Ht(){q(()=>{B||(R.forEach(t=>{let e=t.__svelte_stylesheet,n=e.cssRules.length;for(;n--;)e.deleteRule(n);t.__svelte_rules={}}),R.clear())})}var dt;function L(t){dt=t}var $=[];var ht=[],J=[],_t=[],Gt=Promise.resolve(),N=!1;function qt(){N||(N=!0,Gt.then(pt))}function x(t){J.push(t)}var W=!1,V=new Set;function pt(){if(!W){W=!0;do{for(let t=0;t<$.length;t+=1){let e=$[t];L(e),Kt(e.$$)}for(L(null),$.length=0;ht.length;)ht.pop()();for(let t=0;t{k=null})),k}function U(t,e,n){t.dispatchEvent(Jt(`${e?"intro":"outro"}${n}`))}var z=new Set,m;function mt(){m={r:0,c:[],p:m}}function yt(){m.r||b(m.c),m=m.p}function C(t,e){t&&t.i&&(z.delete(t),t.i(e))}function X(t,e,n,i){if(t&&t.o){if(z.has(t))return;z.add(t),m.c.push(()=>{z.delete(t),i&&(n&&t.d(1),i())}),t.o(e)}}var Rt={duration:0};function Z(t,e,n,i){let r=e(t,n),c=i?0:1,s=null,l=null,a=null;function o(){a&&Tt(t,a)}function y(u,h){let _=u.b-c;return h*=Math.abs(_),{a:c,b:u.b,d:_,duration:h,start:u.start,end:u.start+h,group:u.group}}function f(u){let{delay:h=0,duration:_=300,easing:w=j,tick:g=p,css:F}=r||Rt,H={start:It()+h,b:u};u||(H.group=m,m.r+=1),s||l?l=H:(F&&(o(),a=ft(t,c,u,_,h,w,F)),u&&g(0,1),s=y(H,_),x(()=>U(t,u,"start")),Et(I=>{if(l&&I>l.start&&(s=y(l,_),l=null,U(t,s.b,"start"),F&&(o(),a=ft(t,c,s.b,s.duration,0,w,r.css))),s){if(I>=s.end)g(c=s.b,1-c),U(t,s.b,"end"),l||(s.b?o():--s.group.r||b(s.group.c)),s=null;else if(I>=s.start){let Ct=I-s.start;c=s.a+s.d*w(Ct/s.duration),g(c,1-c)}}return!!(s||l)}))}return{run(u){S(r)?Pt().then(()=>{r=r(),f(u)}):f(u)},end(){o(),s=l=null}}}var re=typeof window!="undefined"?window:typeof globalThis!="undefined"?globalThis:global;var oe=new Set(["allowfullscreen","allowpaymentrequest","async","autofocus","autoplay","checked","controls","default","defer","disabled","formnovalidate","hidden","ismap","loop","multiple","muted","nomodule","novalidate","open","playsinline","readonly","required","reversed","selected"]);function Nt(t,e,n,i){let{fragment:r,on_mount:c,on_destroy:s,after_update:l}=t.$$;r&&r.m(e,n),i||x(()=>{let a=c.map(G).filter(S);s?s.push(...a):b(a),t.$$.on_mount=[]}),l.forEach(x)}function gt(t,e){let n=t.$$;n.fragment!==null&&(b(n.on_destroy),n.fragment&&n.fragment.d(e),n.on_destroy=n.fragment=null,n.ctx=[])}function Wt(t,e){t.$$.dirty[0]===-1&&($.push(t),qt(),t.$$.dirty.fill(0)),t.$$.dirty[e/31|0]|=1<{let _=h.length?h[0]:u;return o.ctx&&r(o.ctx[f],o.ctx[f]=_)&&(!o.skip_bound&&o.bound[f]&&o.bound[f](_),y&&Wt(t,f)),u}):[],o.update(),y=!0,b(o.before_update),o.fragment=i?i(o.ctx):!1,e.target){if(e.hydrate){jt();let f=Lt(e.target);o.fragment&&o.fragment.l(f),f.forEach(D)}else o.fragment&&o.fragment.c();e.intro&&C(t.$$.fragment),Nt(t,e.target,e.anchor,e.customElement),Ot(),pt()}L(a)}var Vt;typeof HTMLElement=="function"&&(Vt=class extends HTMLElement{constructor(){super();this.attachShadow({mode:"open"})}connectedCallback(){let{on_mount:t}=this.$$;this.$$.on_disconnect=t.map(G).filter(S);for(let e in this.$$.slotted)this.appendChild(this.$$.slotted[e])}attributeChangedCallback(t,e,n){this[t]=n}disconnectedCallback(){b(this.$$.on_disconnect)}$destroy(){gt(this,1),this.$destroy=p}$on(t,e){let n=this.$$.callbacks[t]||(this.$$.callbacks[t]=[]);return n.push(e),()=>{let i=n.indexOf(e);i!==-1&&n.splice(i,1)}}$set(t){this.$$set&&!et(t)&&(this.$$.skip_bound=!0,this.$$set(t),this.$$.skip_bound=!1)}});var Q=class{$destroy(){gt(this,1),this.$destroy=p}$on(e,n){let i=this.$$.callbacks[e]||(this.$$.callbacks[e]=[]);return i.push(n),()=>{let r=i.indexOf(n);r!==-1&&i.splice(r,1)}}$set(e){this.$$set&&!et(e)&&(this.$$.skip_bound=!0,this.$$set(e),this.$$.skip_bound=!1)}};var M=[];function wt(t,e=p){let n,i=new Set;function r(l){if(O(t,l)&&(t=l,n)){let a=!M.length;for(let o of i)o[1](),M.push(o,t);if(a){for(let o=0;o{i.delete(o),i.size===0&&(n(),n=null)}}return{set:r,update:c,subscribe:s}}var T=wt(!1);function Ft(){T.set(!0)}function vt(){T.set(!1)}function Y(t,{delay:e=0,duration:n=400,easing:i=j}={}){let r=+getComputedStyle(t).opacity;return{delay:e,duration:n,easing:i,css:c=>`opacity: ${c*r}`}}function Ut(t){ct(t,"svelte-181h7z",`.wails-reconnect-overlay.svelte-181h7z{position:fixed;top:0;left:0;width:100%;height:100%;backdrop-filter:blur(2px) saturate(0%) contrast(50%) brightness(25%);z-index:999999\r
+ }.wails-reconnect-overlay-content.svelte-181h7z{position:relative;top:50%;transform:translateY(-50%);margin:0;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEsAAAA7CAMAAAAEsocZAAAC91BMVEUAAACzQ0PjMjLkMjLZLS7XLS+vJCjkMjKlEx6uGyHjMDGiFx7GJyrAISjUKy3mMzPlMjLjMzOsGyDKJirkMjK6HyXmMjLgMDC6IiLcMjLULC3MJyrRKSy+IibmMzPmMjK7ISXlMjLIJimzHSLkMjKtGiHZLC7BIifgMDCpGSDFIivcLy+yHSKoGR+eFBzNKCvlMjKxHSPkMTKxHSLmMjLKJyq5ICXDJCe6ISXdLzDkMjLmMzPFJSm2HyTlMTLhMDGyHSKUEBmhFx24HyTCJCjHJijjMzOiFh7mMjJ6BhDaLDCuGyOKABjnMzPGJinJJiquHCGEChSmGB/pMzOiFh7VKy3OKCu1HiSvHCLjMTLMKCrBIyeICxWxHCLDIyjSKizBIyh+CBO9ISa6ISWDChS9Iie1HyXVLC7FJSrLKCrlMjLiMTGPDhicFRywGyKXFBuhFx1/BxO7IiXkMTGeFBx8BxLkMTGnGR/GJCi4ICWsGyGJDxXSLS2yGiHSKi3CJCfnMzPQKiyECRTKJiq6ISWUERq/Iye0HiPDJCjGJSm6ICaPDxiTEBrdLy+3HyXSKiy0HyOQEBi4ICWhFh1+CBO9IieODhfSKyzWLC2LDhh8BxHKKCq7ISWaFBzkMzPqNDTTLC3EJSiHDBacExyvGyO1HyTPKCy+IieoGSC7ISaVEhrMKCvQKyusGyG0HiKACBPIJSq/JCaABxR5BRLEJCnkMzPJJinEJimPDRZ2BRKqHx/jMjLnMzPgMDHULC3NKSvQKSzsNDTWLS7SKyy3HyTKJyrDJSjbLzDYLC6mGB/GJSnVLC61HiPLKCrHJSm/Iye8Iia6ICWzHSKxHCLaLi/PKSupGR+7ICXpMzPbLi/IJinJJSmsGyGrGiCkFx6PDheJCxaFChXBIyfAIieSDxmBCBPlMjLeLzDdLzC5HySMDRe+ISWvGyGcFBzSKSzPJyvMJyrEJCjDIyefFRyWERriMDHUKiy/ISaZExv0NjbwNTXuNDTrMzMI0c+yAAAAu3RSTlMAA8HR/gwGgAj+MEpGCsC+hGpjQjYnIxgWBfzx7urizMrFqqB1bF83KhsR/fz8+/r5+fXv7unZ1tC+t6mmopqKdW1nYVpVRjUeHhIQBPr59/b28/Hx8ODg3NvUw8O/vKeim5aNioiDgn1vZWNjX1xUU1JPTUVFPT08Mi4qJyIh/Pv7+/n4+Pf39fT08/Du7efn5uXj4uHa19XNwsG/vrq2tbSuramlnpyYkpGNiIZ+enRraGVjVVBKOzghdjzRsAAABJVJREFUWMPtllVQG1EYhTc0ASpoobS0FCulUHd3oUjd3d3d3d3d3d2b7CYhnkBCCHGDEIK7Vh56d0NpOgwkYfLQzvA9ZrLfnPvfc+8uVEst/yheBJup3Nya2MjU6pa/jWLZtxjXpZFtVB4uVNI6m5gIruNkVFebqIb5Ug2ym4TIEM/gtUOGbg613oBzjAzZFrZ+lXu/3TIiMXXS5M6HTvrNHeLpZLEh6suGNW9fzZ9zd/qVi2eOHygqi5cDE5GUrJocONgzyqo0UXNSUlKSEhMztFqtXq9vNxImAmS3g7Y6QlbjdBWVGW36jt4wDGTUXjUsafh5zJWRkdFuZGtWGnCRmg+HasiGMUClTTzW0ZuVgLlGDIPM4Lhi0IrVq+tv2hS21fNrSONQgpM9DsJ4t3fM9PkvJuKj2ZjrZwvILKvaSTgciUSirjt6dOfOpyd169bDb9rMOwF9Hj4OD100gY0YXYb299bjzMrqj9doNByJWlVXFB9DT5dmJuvy+cq83JyuS6ayEYSHulKL8dmFnBkrCeZlHKMrC5XRhXGCZB2Ty1fkleRQaMCFT2DBsEafzRFJu7/2MicbKynPhQUDLiZwMWLJZKNLzoLbJBYVcurSmbmn+rcyJ8vCMgmlmaW6gnwun/+3C96VpAUuET1ZgRR36r2xWlnYSnf3oKABA14uXDDvydxHs6cpTV1p3hlJ2rJCiUjIZCByItXg8sHJijuvT64CuMTABUYvb6NN1Jdp1PH7D7f3bo2eS5KvW4RJr7atWT5w4MBBg9zdBw9+37BS7QIoFS5WnIaj12dr1DEXFgdvr4fh4eFl+u/wz8uf3jjHic8s4DL2Dal0IANyUBeCRCcwOBJV26JsjSpGwHVuSai69jvqD+jr56OgtKy0zAAK5mLTVBKVKL5tNthGAR9JneJQ/bFsHNzy+U7IlCYROxtMpIjR0ceoQVnowracLLpAQWETqV361bPoFo3cEbz2zYLZM7t3HWXcxmiBOgttS1ycWkTXMWh4mGigdug9DFdttqCFgTN6nD0q1XEVSoCxEjyFCi2eNC6Z69MRVIImJ6JQSf5gcFVCuF+aDhCa1F6MJFDaiNBQAh2TMfWBjhmLsAxUjG/fmjs0qjJck8D0GPBcuUuZW1LS/tIsPzqmQt17PvZQknlwnf4tHDBc+7t5VV3QQCkdc+Ur8/hdrz0but0RCumWiYbiKmLJ7EVbRomj4Q7+y5wsaXvfTGFpQcHB7n2WbG4MGdniw2Tm8xl5Yhr7MrSYHQ3uampz10aWyHyuzxvqaW/6W4MjXAUD3QV2aw97ZxhGjxCohYf5TpTHMXU1BbsAuoFnkRygVieIGAbqiF7rrH4rfWpKJouBCtyHJF8ctEyGubBa+C6NsMYEUonJFITHZqWBxXUA12Dv76Tf/PgOBmeNiiLG1pcKo1HAq8jLpY4JU1yWEixVNaOgoRJAKBSZHTZTU+wJOMtUDZvlVITC6FTlksyrEBoPHXpxxbzdaqzigUtVDkJVIOtVQ9UEOR4VGUh/kHWq0edJ6CxnZ+eePXva2bnY/cF/I1RLLf8vvwDANdMSMegxcAAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position:center\r
+ }.wails-reconnect-overlay-loadingspinner.svelte-181h7z{pointer-events:none;width:2.5em;height:2.5em;border:.4em solid transparent;border-color:#f00 #eee0 #f00 #eee0;border-radius:50%;animation:svelte-181h7z-loadingspin 1s linear infinite;margin:auto;padding:2.5em\r
+ }@keyframes svelte-181h7z-loadingspin{100%{transform:rotate(360deg)}}`)}function xt(t){let e,n,i;return{c(){e=A("div"),e.innerHTML='',at(e,"class","wails-reconnect-overlay svelte-181h7z")},m(r,c){P(r,e,c),i=!0},i(r){i||(x(()=>{n||(n=Z(e,Y,{duration:300},!0)),n.run(1)}),i=!0)},o(r){n||(n=Z(e,Y,{duration:300},!1)),n.run(0),i=!1},d(r){r&&D(e),r&&n&&n.end()}}}function Xt(t){let e,n,i=t[0]&&xt(t);return{c(){i&&i.c(),e=ut()},m(r,c){i&&i.m(r,c),P(r,e,c),n=!0},p(r,[c]){r[0]?i?c&1&&C(i,1):(i=xt(r),i.c(),C(i,1),i.m(e.parentNode,e)):i&&(mt(),X(i,1,1,()=>{i=null}),yt())},i(r){n||(C(i),n=!0)},o(r){X(i),n=!1},d(r){i&&i.d(r),r&&D(e)}}}function Zt(t,e,n){let i;return it(t,T,r=>n(0,i=r)),[i]}var Mt=class extends Q{constructor(e){super();bt(this,e,Zt,Xt,O,{},Ut)}},St=Mt;var Qt={};Qt.overlay=new St({target:document.body,anchor:document.querySelector("#wails-spinner")});var d=null,$t;window.onbeforeunload=function(){d&&(d.onclose=function(){},d.close(),d=null)};kt();function Yt(){window.WailsInvoke=t=>{d.send(t)}}function te(){E("Connected to backend"),vt(),Yt(),clearInterval($t),d.onclose=ee,d.onmessage=ne}function ee(){E("Disconnected from backend"),d=null,Ft(),kt()}function kt(){$t=setInterval(function(){d==null&&(d=new WebSocket("ws://"+window.location.hostname+":34115/wails/ipc"),d.onopen=te,d.onerror=function(t){return t.stopImmediatePropagation(),t.stopPropagation(),t.preventDefault(),d=null,!1})},250)}function ne(t){if(t.data==="reload"){window.runtime.WindowReload();return}switch(t.data[0]){case"n":window.wails.EventsNotify(t.data.slice(1));break;case"c":let e=t.data.slice(1);window.wails.Callback(e);break;default:E("Unknown message: "+t.data)}}})();
+/*! *****************************************************************************
+Copyright (c) Microsoft Corporation.
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+***************************************************************************** */
diff --git a/v2/internal/frontend/runtime/package.json b/v2/internal/frontend/runtime/package.json
index 58531c0dd..130b5a5b0 100644
--- a/v2/internal/frontend/runtime/package.json
+++ b/v2/internal/frontend/runtime/package.json
@@ -6,7 +6,7 @@
"scripts": {
"build": "run-p build:*",
"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-dev": "esbuild desktop/main.js --bundle --sourcemap=inline --outfile=runtime_dev_desktop.js",
"test": "echo \"Error: no test specified\" && exit 1"
diff --git a/v2/internal/frontend/runtime/runtime_dev_desktop.js b/v2/internal/frontend/runtime/runtime_dev_desktop.js
index 5c39d22a3..1fc7d90bb 100644
--- a/v2/internal/frontend/runtime/runtime_dev_desktop.js
+++ b/v2/internal/frontend/runtime/runtime_dev_desktop.js
@@ -1,285 +1,291 @@
(() => {
- var __defProp = Object.defineProperty;
- var __markAsModule = (target) => __defProp(target, "__esModule", {value: true});
- var __export = (target, all) => {
- __markAsModule(target);
- for (var name in all)
- __defProp(target, name, {get: all[name], enumerable: true});
- };
+ var __defProp = Object.defineProperty;
+ var __markAsModule = (target) => __defProp(target, "__esModule", {value: true});
+ var __export = (target, all) => {
+ __markAsModule(target);
+ for (var name in all)
+ __defProp(target, name, {get: all[name], enumerable: true});
+ };
- // desktop/log.js
- var log_exports = {};
- __export(log_exports, {
- LogDebug: () => LogDebug,
- LogError: () => LogError,
- LogFatal: () => LogFatal,
- LogInfo: () => LogInfo,
- LogLevel: () => LogLevel,
- LogPrint: () => LogPrint,
- LogTrace: () => LogTrace,
- LogWarning: () => LogWarning,
- SetLogLevel: () => SetLogLevel
- });
+ // desktop/log.js
+ var log_exports = {};
+ __export(log_exports, {
+ LogDebug: () => LogDebug,
+ LogError: () => LogError,
+ LogFatal: () => LogFatal,
+ LogInfo: () => LogInfo,
+ LogLevel: () => LogLevel,
+ LogPrint: () => LogPrint,
+ LogTrace: () => LogTrace,
+ LogWarning: () => LogWarning,
+ SetLogLevel: () => SetLogLevel
+ });
- function sendLogMessage(level, message) {
- window.WailsInvoke("L" + level + message);
- }
+ function sendLogMessage(level, message) {
+ window.WailsInvoke("L" + level + message);
+ }
- function LogTrace(message) {
- sendLogMessage("T", message);
- }
+ function LogTrace(message) {
+ sendLogMessage("T", message);
+ }
- function LogPrint(message) {
- sendLogMessage("P", message);
- }
+ function LogPrint(message) {
+ sendLogMessage("P", message);
+ }
- function LogDebug(message) {
- sendLogMessage("D", message);
- }
+ function LogDebug(message) {
+ sendLogMessage("D", message);
+ }
- function LogInfo(message) {
- sendLogMessage("I", message);
- }
+ function LogInfo(message) {
+ sendLogMessage("I", message);
+ }
- function LogWarning(message) {
- sendLogMessage("W", message);
- }
+ function LogWarning(message) {
+ sendLogMessage("W", message);
+ }
- function LogError(message) {
- sendLogMessage("E", message);
- }
+ function LogError(message) {
+ sendLogMessage("E", message);
+ }
- function LogFatal(message) {
- sendLogMessage("F", message);
- }
+ function LogFatal(message) {
+ sendLogMessage("F", message);
+ }
- function SetLogLevel(loglevel) {
- sendLogMessage("S", loglevel);
- }
+ function SetLogLevel(loglevel) {
+ sendLogMessage("S", loglevel);
+ }
- var LogLevel = {
- TRACE: 1,
- DEBUG: 2,
- INFO: 3,
- WARNING: 4,
- ERROR: 5
- };
+ var LogLevel = {
+ TRACE: 1,
+ DEBUG: 2,
+ INFO: 3,
+ WARNING: 4,
+ ERROR: 5
+ };
- // desktop/events.js
- var Listener = class {
- constructor(callback, maxCallbacks) {
- maxCallbacks = maxCallbacks || -1;
- this.Callback = (data) => {
- callback.apply(null, data);
- if (maxCallbacks === -1) {
- return false;
- }
- maxCallbacks -= 1;
- return maxCallbacks === 0;
- };
+ // desktop/events.js
+ var Listener = class {
+ constructor(callback, maxCallbacks) {
+ maxCallbacks = maxCallbacks || -1;
+ this.Callback = (data) => {
+ callback.apply(null, data);
+ if (maxCallbacks === -1) {
+ return false;
}
+ maxCallbacks -= 1;
+ return maxCallbacks === 0;
+ };
+ }
+ };
+ var eventListeners = {};
+
+ function EventsOnMultiple(eventName, callback, maxCallbacks) {
+ eventListeners[eventName] = eventListeners[eventName] || [];
+ const thisListener = new Listener(callback, maxCallbacks);
+ eventListeners[eventName].push(thisListener);
+ }
+
+ function EventsOn(eventName, callback) {
+ EventsOnMultiple(eventName, callback, -1);
+ }
+
+ function EventsOnce(eventName, callback) {
+ EventsOnMultiple(eventName, callback, 1);
+ }
+
+ function notifyListeners(eventData) {
+ let eventName = eventData.name;
+ if (eventListeners[eventName]) {
+ const newEventListenerList = eventListeners[eventName].slice();
+ for (let count = 0; count < eventListeners[eventName].length; count += 1) {
+ const listener = eventListeners[eventName][count];
+ let data = eventData.data;
+ const destroy = listener.Callback(data);
+ if (destroy) {
+ newEventListenerList.splice(count, 1);
+ }
+ }
+ eventListeners[eventName] = newEventListenerList;
+ }
+ }
+
+ function EventsNotify(notifyMessage) {
+ let message;
+ try {
+ message = JSON.parse(notifyMessage);
+ } catch (e) {
+ const error = "Invalid JSON passed to Notify: " + notifyMessage;
+ throw new Error(error);
+ }
+ notifyListeners(message);
+ }
+
+ function EventsEmit(eventName) {
+ const payload = {
+ name: eventName,
+ data: [].slice.apply(arguments).slice(1)
};
- var eventListeners = {};
+ notifyListeners(payload);
+ window.WailsInvoke("EE" + JSON.stringify(payload));
+ }
- function EventsOnMultiple(eventName, callback, maxCallbacks) {
- eventListeners[eventName] = eventListeners[eventName] || [];
- const thisListener = new Listener(callback, maxCallbacks);
- eventListeners[eventName].push(thisListener);
+ function EventsOff(eventName) {
+ eventListeners.delete(eventName);
+ window.WailsInvoke("EX" + eventName);
+ }
+
+ // desktop/calls.js
+ var callbacks = {};
+
+ function cryptoRandom() {
+ var array = new Uint32Array(1);
+ return window.crypto.getRandomValues(array)[0];
+ }
+
+ function basicRandom() {
+ return Math.random() * 9007199254740991;
+ }
+
+ var randomFunc;
+ if (window.crypto) {
+ randomFunc = cryptoRandom;
+ } else {
+ randomFunc = basicRandom;
+ }
+
+ function Call(name, args, timeout) {
+ if (timeout == null) {
+ timeout = 0;
}
-
- function EventsOn(eventName, callback) {
- EventsOnMultiple(eventName, callback, -1);
- }
-
- function EventsOnce(eventName, callback) {
- EventsOnMultiple(eventName, callback, 1);
- }
-
- function notifyListeners(eventData) {
- let eventName = eventData.name;
- if (eventListeners[eventName]) {
- const newEventListenerList = eventListeners[eventName].slice();
- for (let count = 0; count < eventListeners[eventName].length; count += 1) {
- const listener = eventListeners[eventName][count];
- let data = eventData.data;
- const destroy = listener.Callback(data);
- if (destroy) {
- newEventListenerList.splice(count, 1);
- }
- }
- eventListeners[eventName] = newEventListenerList;
- }
- }
-
- function EventsNotify(notifyMessage) {
- let message;
- try {
- message = JSON.parse(notifyMessage);
- } catch (e) {
- const error = "Invalid JSON passed to Notify: " + notifyMessage;
- throw new Error(error);
- }
- notifyListeners(message);
- }
-
- function EventsEmit(eventName) {
+ return new Promise(function (resolve, reject) {
+ var callbackID;
+ do {
+ callbackID = name + "-" + randomFunc();
+ } while (callbacks[callbackID]);
+ var timeoutHandle;
+ if (timeout > 0) {
+ timeoutHandle = setTimeout(function () {
+ reject(Error("Call to " + name + " timed out. Request ID: " + callbackID));
+ }, timeout);
+ }
+ callbacks[callbackID] = {
+ timeoutHandle,
+ reject,
+ resolve
+ };
+ try {
const payload = {
- name: eventName,
- data: [].slice.apply(arguments).slice(1)
+ name,
+ args,
+ callbackID
};
- notifyListeners(payload);
- window.WailsInvoke("EE" + JSON.stringify(payload));
- }
-
- function EventsOff(eventName) {
- eventListeners.delete(eventName);
- window.WailsInvoke("EX" + eventName);
- }
-
- // desktop/calls.js
- var callbacks = {};
-
- function cryptoRandom() {
- var array = new Uint32Array(1);
- return window.crypto.getRandomValues(array)[0];
- }
-
- function basicRandom() {
- return Math.random() * 9007199254740991;
- }
-
- var randomFunc;
- if (window.crypto) {
- randomFunc = cryptoRandom;
- } else {
- randomFunc = basicRandom;
- }
-
- function Call(name, args, timeout) {
- if (timeout == null) {
- timeout = 0;
- }
- return new Promise(function (resolve, reject) {
- var callbackID;
- do {
- callbackID = name + "-" + randomFunc();
- } while (callbacks[callbackID]);
- var timeoutHandle;
- if (timeout > 0) {
- timeoutHandle = setTimeout(function () {
- reject(Error("Call to " + name + " timed out. Request ID: " + callbackID));
- }, timeout);
- }
- callbacks[callbackID] = {
- timeoutHandle,
- reject,
- resolve
- };
- try {
- const payload = {
- name,
- args,
- callbackID
- };
- window.WailsInvoke("C" + JSON.stringify(payload));
- } catch (e) {
- console.error(e);
- }
- });
- }
-
- function Callback(incomingMessage) {
- var message;
- try {
- message = JSON.parse(incomingMessage);
- } catch (e) {
- const error = `Invalid JSON passed to callback: ${e.message}. Message: ${incomingMessage}`;
- wails.LogDebug(error);
- throw new Error(error);
- }
- var callbackID = message.callbackid;
- var callbackData = callbacks[callbackID];
- if (!callbackData) {
- const error = `Callback '${callbackID}' not registered!!!`;
- console.error(error);
- throw new Error(error);
- }
- clearTimeout(callbackData.timeoutHandle);
- delete callbacks[callbackID];
- if (message.error) {
- callbackData.reject(message.error);
- } else {
- callbackData.resolve(message.result);
- }
- }
-
- // desktop/bindings.js
- window.backend = {};
-
- function SetBindings(bindingsMap) {
- try {
- bindingsMap = JSON.parse(bindingsMap);
- } catch (e) {
- console.error(e);
- }
- window.backend = window.backend || {};
- Object.keys(bindingsMap).forEach((packageName) => {
- window.backend[packageName] = window.backend[packageName] || {};
- Object.keys(bindingsMap[packageName]).forEach((structName) => {
- window.backend[packageName][structName] = window.backend[packageName][structName] || {};
- Object.keys(bindingsMap[packageName][structName]).forEach((methodName) => {
- window.backend[packageName][structName][methodName] = function () {
- let timeout = 0;
-
- function dynamic() {
- const args = [].slice.call(arguments);
- return Call([packageName, structName, methodName].join("."), args, timeout);
- }
-
- dynamic.setTimeout = function (newTimeout) {
- timeout = newTimeout;
- };
- dynamic.getTimeout = function () {
- return timeout;
- };
- return dynamic;
- }();
- });
- });
- });
- }
-
- // desktop/main.js
- window.backend = {};
- window.runtime = {
- ...log_exports,
- EventsOn,
- EventsOnce,
- EventsOnMultiple,
- EventsEmit,
- EventsOff
- };
- window.wails = {
- Callback,
- EventsNotify,
- SetBindings,
- eventListeners,
- callbacks
- };
- window.wails.SetBindings(window.wailsbindings);
- delete window.wails.SetBindings;
- delete window.wailsbindings;
- window.addEventListener("mousedown", (e) => {
- let currentElement = e.target;
- while (currentElement != null) {
- if (currentElement.hasAttribute("data-wails-no-drag")) {
- break;
- } else if (currentElement.hasAttribute("data-wails-drag")) {
- window.WailsInvoke("drag");
- break;
- }
- currentElement = currentElement.parentElement;
- }
+ window.WailsInvoke("C" + JSON.stringify(payload));
+ } catch (e) {
+ console.error(e);
+ }
});
+ }
+
+ function Callback(incomingMessage) {
+ var message;
+ try {
+ message = JSON.parse(incomingMessage);
+ } catch (e) {
+ const error = `Invalid JSON passed to callback: ${e.message}. Message: ${incomingMessage}`;
+ wails.LogDebug(error);
+ throw new Error(error);
+ }
+ var callbackID = message.callbackid;
+ var callbackData = callbacks[callbackID];
+ if (!callbackData) {
+ const error = `Callback '${callbackID}' not registered!!!`;
+ console.error(error);
+ throw new Error(error);
+ }
+ clearTimeout(callbackData.timeoutHandle);
+ delete callbacks[callbackID];
+ if (message.error) {
+ callbackData.reject(message.error);
+ } else {
+ callbackData.resolve(message.result);
+ }
+ }
+
+ // desktop/bindings.js
+ window.backend = {};
+
+ function SetBindings(bindingsMap) {
+ try {
+ bindingsMap = JSON.parse(bindingsMap);
+ } catch (e) {
+ console.error(e);
+ }
+ window.backend = window.backend || {};
+ Object.keys(bindingsMap).forEach((packageName) => {
+ window.backend[packageName] = window.backend[packageName] || {};
+ Object.keys(bindingsMap[packageName]).forEach((structName) => {
+ window.backend[packageName][structName] = window.backend[packageName][structName] || {};
+ Object.keys(bindingsMap[packageName][structName]).forEach((methodName) => {
+ window.backend[packageName][structName][methodName] = function () {
+ let timeout = 0;
+
+ function dynamic() {
+ const args = [].slice.call(arguments);
+ return Call([packageName, structName, methodName].join("."), args, timeout);
+ }
+
+ dynamic.setTimeout = function (newTimeout) {
+ timeout = newTimeout;
+ };
+ dynamic.getTimeout = function () {
+ return timeout;
+ };
+ return dynamic;
+ }();
+ });
+ });
+ });
+ }
+
+ // desktop/window.js
+ function WindowReload() {
+ window.location.reload();
+ }
+
+ // desktop/main.js
+ window.backend = {};
+ window.runtime = {
+ ...log_exports,
+ EventsOn,
+ EventsOnce,
+ EventsOnMultiple,
+ EventsEmit,
+ EventsOff,
+ WindowReload
+ };
+ window.wails = {
+ Callback,
+ EventsNotify,
+ SetBindings,
+ eventListeners,
+ callbacks
+ };
+ window.wails.SetBindings(window.wailsbindings);
+ delete window.wails.SetBindings;
+ delete window.wailsbindings;
+ window.addEventListener("mousedown", (e) => {
+ let currentElement = e.target;
+ while (currentElement != null) {
+ if (currentElement.hasAttribute("data-wails-no-drag")) {
+ break;
+ } else if (currentElement.hasAttribute("data-wails-drag")) {
+ window.WailsInvoke("drag");
+ break;
+ }
+ currentElement = currentElement.parentElement;
+ }
+ });
})();
-//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiZGVza3RvcC9sb2cuanMiLCAiZGVza3RvcC9ldmVudHMuanMiLCAiZGVza3RvcC9jYWxscy5qcyIsICJkZXNrdG9wL2JpbmRpbmdzLmpzIiwgImRlc2t0b3AvbWFpbi5qcyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLypcclxuIF8gICAgICAgX18gICAgICBfIF9fXHJcbnwgfCAgICAgLyAvX19fIF8oXykgL19fX19cclxufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xyXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcclxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXHJcblRoZSBsaWdodHdlaWdodCBmcmFtZXdvcmsgZm9yIHdlYi1saWtlIGFwcHNcclxuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxyXG4qL1xyXG5cclxuLyoganNoaW50IGVzdmVyc2lvbjogNiAqL1xyXG5cclxuLyoqXHJcbiAqIFNlbmRzIGEgbG9nIG1lc3NhZ2UgdG8gdGhlIGJhY2tlbmQgd2l0aCB0aGUgZ2l2ZW4gbGV2ZWwgKyBtZXNzYWdlXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBsZXZlbFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxyXG4gKi9cclxuZnVuY3Rpb24gc2VuZExvZ01lc3NhZ2UobGV2ZWwsIG1lc3NhZ2UpIHtcclxuXHJcblx0Ly8gTG9nIE1lc3NhZ2UgZm9ybWF0OlxyXG5cdC8vIGxbdHlwZV1bbWVzc2FnZV1cclxuXHR3aW5kb3cuV2FpbHNJbnZva2UoJ0wnICsgbGV2ZWwgKyBtZXNzYWdlKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIExvZyB0aGUgZ2l2ZW4gdHJhY2UgbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBMb2dUcmFjZShtZXNzYWdlKSB7XHJcblx0c2VuZExvZ01lc3NhZ2UoJ1QnLCBtZXNzYWdlKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIExvZyB0aGUgZ2l2ZW4gbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBMb2dQcmludChtZXNzYWdlKSB7XHJcblx0c2VuZExvZ01lc3NhZ2UoJ1AnLCBtZXNzYWdlKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIExvZyB0aGUgZ2l2ZW4gZGVidWcgbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBMb2dEZWJ1ZyhtZXNzYWdlKSB7XHJcblx0c2VuZExvZ01lc3NhZ2UoJ0QnLCBtZXNzYWdlKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIExvZyB0aGUgZ2l2ZW4gaW5mbyBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIExvZ0luZm8obWVzc2FnZSkge1xyXG5cdHNlbmRMb2dNZXNzYWdlKCdJJywgbWVzc2FnZSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBMb2cgdGhlIGdpdmVuIHdhcm5pbmcgbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBMb2dXYXJuaW5nKG1lc3NhZ2UpIHtcclxuXHRzZW5kTG9nTWVzc2FnZSgnVycsIG1lc3NhZ2UpO1xyXG59XHJcblxyXG4vKipcclxuICogTG9nIHRoZSBnaXZlbiBlcnJvciBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIExvZ0Vycm9yKG1lc3NhZ2UpIHtcclxuXHRzZW5kTG9nTWVzc2FnZSgnRScsIG1lc3NhZ2UpO1xyXG59XHJcblxyXG4vKipcclxuICogTG9nIHRoZSBnaXZlbiBmYXRhbCBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIExvZ0ZhdGFsKG1lc3NhZ2UpIHtcclxuXHRzZW5kTG9nTWVzc2FnZSgnRicsIG1lc3NhZ2UpO1xyXG59XHJcblxyXG4vKipcclxuICogU2V0cyB0aGUgTG9nIGxldmVsIHRvIHRoZSBnaXZlbiBsb2cgbGV2ZWxcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge251bWJlcn0gbG9nbGV2ZWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBTZXRMb2dMZXZlbChsb2dsZXZlbCkge1xyXG5cdHNlbmRMb2dNZXNzYWdlKCdTJywgbG9nbGV2ZWwpO1xyXG59XHJcblxyXG4vLyBMb2cgbGV2ZWxzXHJcbmV4cG9ydCBjb25zdCBMb2dMZXZlbCA9IHtcclxuXHRUUkFDRTogMSxcclxuXHRERUJVRzogMixcclxuXHRJTkZPOiAzLFxyXG5cdFdBUk5JTkc6IDQsXHJcblx0RVJST1I6IDUsXHJcbn07XHJcbiIsICIvKlxyXG4gXyAgICAgICBfXyAgICAgIF8gX19cclxufCB8ICAgICAvIC9fX18gXyhfKSAvX19fX1xyXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXHJcbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxyXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cclxuVGhlIGxpZ2h0d2VpZ2h0IGZyYW1ld29yayBmb3Igd2ViLWxpa2UgYXBwc1xyXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XHJcbiovXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDYgKi9cclxuXHJcbi8vIERlZmluZXMgYSBzaW5nbGUgbGlzdGVuZXIgd2l0aCBhIG1heGltdW0gbnVtYmVyIG9mIHRpbWVzIHRvIGNhbGxiYWNrXHJcblxyXG4vKipcclxuICogVGhlIExpc3RlbmVyIGNsYXNzIGRlZmluZXMgYSBsaXN0ZW5lciEgOi0pXHJcbiAqXHJcbiAqIEBjbGFzcyBMaXN0ZW5lclxyXG4gKi9cclxuY2xhc3MgTGlzdGVuZXIge1xyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIExpc3RlbmVyLlxyXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBtYXhDYWxsYmFja3NcclxuICAgICAqIEBtZW1iZXJvZiBMaXN0ZW5lclxyXG4gICAgICovXHJcbiAgICBjb25zdHJ1Y3RvcihjYWxsYmFjaywgbWF4Q2FsbGJhY2tzKSB7XHJcbiAgICAgICAgLy8gRGVmYXVsdCBvZiAtMSBtZWFucyBpbmZpbml0ZVxyXG4gICAgICAgIG1heENhbGxiYWNrcyA9IG1heENhbGxiYWNrcyB8fCAtMTtcclxuICAgICAgICAvLyBDYWxsYmFjayBpbnZva2VzIHRoZSBjYWxsYmFjayB3aXRoIHRoZSBnaXZlbiBkYXRhXHJcbiAgICAgICAgLy8gUmV0dXJucyB0cnVlIGlmIHRoaXMgbGlzdGVuZXIgc2hvdWxkIGJlIGRlc3Ryb3llZFxyXG4gICAgICAgIHRoaXMuQ2FsbGJhY2sgPSAoZGF0YSkgPT4ge1xyXG4gICAgICAgICAgICBjYWxsYmFjay5hcHBseShudWxsLCBkYXRhKTtcclxuICAgICAgICAgICAgLy8gSWYgbWF4Q2FsbGJhY2tzIGlzIGluZmluaXRlLCByZXR1cm4gZmFsc2UgKGRvIG5vdCBkZXN0cm95KVxyXG4gICAgICAgICAgICBpZiAobWF4Q2FsbGJhY2tzID09PSAtMSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIC8vIERlY3JlbWVudCBtYXhDYWxsYmFja3MuIFJldHVybiB0cnVlIGlmIG5vdyAwLCBvdGhlcndpc2UgZmFsc2VcclxuICAgICAgICAgICAgbWF4Q2FsbGJhY2tzIC09IDE7XHJcbiAgICAgICAgICAgIHJldHVybiBtYXhDYWxsYmFja3MgPT09IDA7XHJcbiAgICAgICAgfTtcclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IGNvbnN0IGV2ZW50TGlzdGVuZXJzID0ge307XHJcblxyXG4vKipcclxuICogUmVnaXN0ZXJzIGFuIGV2ZW50IGxpc3RlbmVyIHRoYXQgd2lsbCBiZSBpbnZva2VkIGBtYXhDYWxsYmFja3NgIHRpbWVzIGJlZm9yZSBiZWluZyBkZXN0cm95ZWRcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXHJcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhDYWxsYmFja3NcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG1heENhbGxiYWNrcykge1xyXG4gICAgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0gfHwgW107XHJcbiAgICBjb25zdCB0aGlzTGlzdGVuZXIgPSBuZXcgTGlzdGVuZXIoY2FsbGJhY2ssIG1heENhbGxiYWNrcyk7XHJcbiAgICBldmVudExpc3RlbmVyc1tldmVudE5hbWVdLnB1c2godGhpc0xpc3RlbmVyKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBldmVyeSB0aW1lIHRoZSBldmVudCBpcyBlbWl0dGVkXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxyXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFja1xyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEV2ZW50c09uKGV2ZW50TmFtZSwgY2FsbGJhY2spIHtcclxuICAgIEV2ZW50c09uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgLTEpO1xyXG59XHJcblxyXG4vKipcclxuICogUmVnaXN0ZXJzIGFuIGV2ZW50IGxpc3RlbmVyIHRoYXQgd2lsbCBiZSBpbnZva2VkIG9uY2UgdGhlbiBkZXN0cm95ZWRcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXHJcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzT25jZShldmVudE5hbWUsIGNhbGxiYWNrKSB7XHJcbiAgICBFdmVudHNPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIDEpO1xyXG59XHJcblxyXG5mdW5jdGlvbiBub3RpZnlMaXN0ZW5lcnMoZXZlbnREYXRhKSB7XHJcblxyXG4gICAgLy8gR2V0IHRoZSBldmVudCBuYW1lXHJcbiAgICBsZXQgZXZlbnROYW1lID0gZXZlbnREYXRhLm5hbWU7XHJcblxyXG4gICAgLy8gQ2hlY2sgaWYgd2UgaGF2ZSBhbnkgbGlzdGVuZXJzIGZvciB0aGlzIGV2ZW50XHJcbiAgICBpZiAoZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSkge1xyXG5cclxuICAgICAgICAvLyBLZWVwIGEgbGlzdCBvZiBsaXN0ZW5lciBpbmRleGVzIHRvIGRlc3Ryb3lcclxuICAgICAgICBjb25zdCBuZXdFdmVudExpc3RlbmVyTGlzdCA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0uc2xpY2UoKTtcclxuXHJcbiAgICAgICAgLy8gSXRlcmF0ZSBsaXN0ZW5lcnNcclxuICAgICAgICBmb3IgKGxldCBjb3VudCA9IDA7IGNvdW50IDwgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXS5sZW5ndGg7IGNvdW50ICs9IDEpIHtcclxuXHJcbiAgICAgICAgICAgIC8vIEdldCBuZXh0IGxpc3RlbmVyXHJcbiAgICAgICAgICAgIGNvbnN0IGxpc3RlbmVyID0gZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXVtjb3VudF07XHJcblxyXG4gICAgICAgICAgICBsZXQgZGF0YSA9IGV2ZW50RGF0YS5kYXRhO1xyXG5cclxuICAgICAgICAgICAgLy8gRG8gdGhlIGNhbGxiYWNrXHJcbiAgICAgICAgICAgIGNvbnN0IGRlc3Ryb3kgPSBsaXN0ZW5lci5DYWxsYmFjayhkYXRhKTtcclxuICAgICAgICAgICAgaWYgKGRlc3Ryb3kpIHtcclxuICAgICAgICAgICAgICAgIC8vIGlmIHRoZSBsaXN0ZW5lciBpbmRpY2F0ZWQgdG8gZGVzdHJveSBpdHNlbGYsIGFkZCBpdCB0byB0aGUgZGVzdHJveSBsaXN0XHJcbiAgICAgICAgICAgICAgICBuZXdFdmVudExpc3RlbmVyTGlzdC5zcGxpY2UoY291bnQsIDEpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBVcGRhdGUgY2FsbGJhY2tzIHdpdGggbmV3IGxpc3Qgb2YgbGlzdGVuZXJzXHJcbiAgICAgICAgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSA9IG5ld0V2ZW50TGlzdGVuZXJMaXN0O1xyXG4gICAgfVxyXG59XHJcblxyXG4vKipcclxuICogTm90aWZ5IGluZm9ybXMgZnJvbnRlbmQgbGlzdGVuZXJzIHRoYXQgYW4gZXZlbnQgd2FzIGVtaXR0ZWQgd2l0aCB0aGUgZ2l2ZW4gZGF0YVxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBub3RpZnlNZXNzYWdlIC0gZW5jb2RlZCBub3RpZmljYXRpb24gbWVzc2FnZVxyXG5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNOb3RpZnkobm90aWZ5TWVzc2FnZSkge1xyXG4gICAgLy8gUGFyc2UgdGhlIG1lc3NhZ2VcclxuICAgIGxldCBtZXNzYWdlO1xyXG4gICAgdHJ5IHtcclxuICAgICAgICBtZXNzYWdlID0gSlNPTi5wYXJzZShub3RpZnlNZXNzYWdlKTtcclxuICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICBjb25zdCBlcnJvciA9ICdJbnZhbGlkIEpTT04gcGFzc2VkIHRvIE5vdGlmeTogJyArIG5vdGlmeU1lc3NhZ2U7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGVycm9yKTtcclxuICAgIH1cclxuICAgIG5vdGlmeUxpc3RlbmVycyhtZXNzYWdlKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEVtaXQgYW4gZXZlbnQgd2l0aCB0aGUgZ2l2ZW4gbmFtZSBhbmQgZGF0YVxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNFbWl0KGV2ZW50TmFtZSkge1xyXG5cclxuICAgIGNvbnN0IHBheWxvYWQgPSB7XHJcbiAgICAgICAgbmFtZTogZXZlbnROYW1lLFxyXG4gICAgICAgIGRhdGE6IFtdLnNsaWNlLmFwcGx5KGFyZ3VtZW50cykuc2xpY2UoMSksXHJcbiAgICB9O1xyXG5cclxuICAgIC8vIE5vdGlmeSBKUyBsaXN0ZW5lcnNcclxuICAgIG5vdGlmeUxpc3RlbmVycyhwYXlsb2FkKTtcclxuXHJcbiAgICAvLyBOb3RpZnkgR28gbGlzdGVuZXJzXHJcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ0VFJyArIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIEV2ZW50c09mZihldmVudE5hbWUpIHtcclxuICAgIC8vIFJlbW92ZSBsb2NhbCBsaXN0ZW5lcnNcclxuICAgIGV2ZW50TGlzdGVuZXJzLmRlbGV0ZShldmVudE5hbWUpO1xyXG5cclxuICAgIC8vIE5vdGlmeSBHbyBsaXN0ZW5lcnNcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnRVgnICsgZXZlbnROYW1lKTtcclxufSIsICIvKlxyXG4gXyAgICAgICBfXyAgICAgIF8gX19cclxufCB8ICAgICAvIC9fX18gXyhfKSAvX19fX1xyXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXHJcbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxyXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cclxuVGhlIGxpZ2h0d2VpZ2h0IGZyYW1ld29yayBmb3Igd2ViLWxpa2UgYXBwc1xyXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XHJcbiovXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDYgKi9cclxuXHJcbmV4cG9ydCBjb25zdCBjYWxsYmFja3MgPSB7fTtcclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIGEgbnVtYmVyIGZyb20gdGhlIG5hdGl2ZSBicm93c2VyIHJhbmRvbSBmdW5jdGlvblxyXG4gKlxyXG4gKiBAcmV0dXJucyBudW1iZXJcclxuICovXHJcbmZ1bmN0aW9uIGNyeXB0b1JhbmRvbSgpIHtcclxuXHR2YXIgYXJyYXkgPSBuZXcgVWludDMyQXJyYXkoMSk7XHJcblx0cmV0dXJuIHdpbmRvdy5jcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKGFycmF5KVswXTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgYSBudW1iZXIgdXNpbmcgZGEgb2xkLXNrb29sIE1hdGguUmFuZG9tXHJcbiAqIEkgbGlrZXMgdG8gY2FsbCBpdCBMT0xSYW5kb21cclxuICpcclxuICogQHJldHVybnMgbnVtYmVyXHJcbiAqL1xyXG5mdW5jdGlvbiBiYXNpY1JhbmRvbSgpIHtcclxuXHRyZXR1cm4gTWF0aC5yYW5kb20oKSAqIDkwMDcxOTkyNTQ3NDA5OTE7XHJcbn1cclxuXHJcbi8vIFBpY2sgYSByYW5kb20gbnVtYmVyIGZ1bmN0aW9uIGJhc2VkIG9uIGJyb3dzZXIgY2FwYWJpbGl0eVxyXG52YXIgcmFuZG9tRnVuYztcclxuaWYgKHdpbmRvdy5jcnlwdG8pIHtcclxuXHRyYW5kb21GdW5jID0gY3J5cHRvUmFuZG9tO1xyXG59IGVsc2Uge1xyXG5cdHJhbmRvbUZ1bmMgPSBiYXNpY1JhbmRvbTtcclxufVxyXG5cclxuXHJcbi8qKlxyXG4gKiBDYWxsIHNlbmRzIGEgbWVzc2FnZSB0byB0aGUgYmFja2VuZCB0byBjYWxsIHRoZSBiaW5kaW5nIHdpdGggdGhlXHJcbiAqIGdpdmVuIGRhdGEuIEEgcHJvbWlzZSBpcyByZXR1cm5lZCBhbmQgd2lsbCBiZSBjb21wbGV0ZWQgd2hlbiB0aGVcclxuICogYmFja2VuZCByZXNwb25kcy4gVGhpcyB3aWxsIGJlIHJlc29sdmVkIHdoZW4gdGhlIGNhbGwgd2FzIHN1Y2Nlc3NmdWxcclxuICogb3IgcmVqZWN0ZWQgaWYgYW4gZXJyb3IgaXMgcGFzc2VkIGJhY2suXHJcbiAqIFRoZXJlIGlzIGEgdGltZW91dCBtZWNoYW5pc20uIElmIHRoZSBjYWxsIGRvZXNuJ3QgcmVzcG9uZCBpbiB0aGUgZ2l2ZW5cclxuICogdGltZSAoaW4gbWlsbGlzZWNvbmRzKSB0aGVuIHRoZSBwcm9taXNlIGlzIHJlamVjdGVkLlxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzXHJcbiAqIEBwYXJhbSB7bnVtYmVyPX0gdGltZW91dFxyXG4gKiBAcmV0dXJuc1xyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIENhbGwobmFtZSwgYXJncywgdGltZW91dCkge1xyXG5cclxuXHQvLyBUaW1lb3V0IGluZmluaXRlIGJ5IGRlZmF1bHRcclxuXHRpZiAodGltZW91dCA9PSBudWxsKSB7XHJcblx0XHR0aW1lb3V0ID0gMDtcclxuXHR9XHJcblxyXG5cdC8vIENyZWF0ZSBhIHByb21pc2VcclxuXHRyZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xyXG5cclxuXHRcdC8vIENyZWF0ZSBhIHVuaXF1ZSBjYWxsYmFja0lEXHJcblx0XHR2YXIgY2FsbGJhY2tJRDtcclxuXHRcdGRvIHtcclxuXHRcdFx0Y2FsbGJhY2tJRCA9IG5hbWUgKyAnLScgKyByYW5kb21GdW5jKCk7XHJcblx0XHR9IHdoaWxlIChjYWxsYmFja3NbY2FsbGJhY2tJRF0pO1xyXG5cclxuXHRcdHZhciB0aW1lb3V0SGFuZGxlO1xyXG5cdFx0Ly8gU2V0IHRpbWVvdXRcclxuXHRcdGlmICh0aW1lb3V0ID4gMCkge1xyXG5cdFx0XHR0aW1lb3V0SGFuZGxlID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XHJcblx0XHRcdFx0cmVqZWN0KEVycm9yKCdDYWxsIHRvICcgKyBuYW1lICsgJyB0aW1lZCBvdXQuIFJlcXVlc3QgSUQ6ICcgKyBjYWxsYmFja0lEKSk7XHJcblx0XHRcdH0sIHRpbWVvdXQpO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIFN0b3JlIGNhbGxiYWNrXHJcblx0XHRjYWxsYmFja3NbY2FsbGJhY2tJRF0gPSB7XHJcblx0XHRcdHRpbWVvdXRIYW5kbGU6IHRpbWVvdXRIYW5kbGUsXHJcblx0XHRcdHJlamVjdDogcmVqZWN0LFxyXG5cdFx0XHRyZXNvbHZlOiByZXNvbHZlXHJcblx0XHR9O1xyXG5cclxuXHRcdHRyeSB7XHJcblx0XHRcdGNvbnN0IHBheWxvYWQgPSB7XHJcblx0XHRcdFx0bmFtZSxcclxuXHRcdFx0XHRhcmdzLFxyXG5cdFx0XHRcdGNhbGxiYWNrSUQsXHJcblx0XHRcdH07XHJcblxyXG5cdFx0XHQvLyBNYWtlIHRoZSBjYWxsXHJcblx0XHRcdHdpbmRvdy5XYWlsc0ludm9rZSgnQycgKyBKU09OLnN0cmluZ2lmeShwYXlsb2FkKSk7XHJcblx0XHR9IGNhdGNoIChlKSB7XHJcblx0XHRcdC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxyXG5cdFx0XHRjb25zb2xlLmVycm9yKGUpO1xyXG5cdFx0fVxyXG5cdH0pO1xyXG59XHJcblxyXG5cclxuXHJcbi8qKlxyXG4gKiBDYWxsZWQgYnkgdGhlIGJhY2tlbmQgdG8gcmV0dXJuIGRhdGEgdG8gYSBwcmV2aW91c2x5IGNhbGxlZFxyXG4gKiBiaW5kaW5nIGludm9jYXRpb25cclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gaW5jb21pbmdNZXNzYWdlXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gQ2FsbGJhY2soaW5jb21pbmdNZXNzYWdlKSB7XHJcblx0Ly8gRGVjb2RlIHRoZSBtZXNzYWdlIC0gQ3JlZGl0OiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMTM4NjU2ODBcclxuXHQvL2luY29taW5nTWVzc2FnZSA9IGRlY29kZVVSSUNvbXBvbmVudChpbmNvbWluZ01lc3NhZ2UucmVwbGFjZSgvXFxzKy9nLCAnJykucmVwbGFjZSgvWzAtOWEtZl17Mn0vZywgJyUkJicpKTtcclxuXHJcblx0Ly8gUGFyc2UgdGhlIG1lc3NhZ2VcclxuXHR2YXIgbWVzc2FnZTtcclxuXHR0cnkge1xyXG5cdFx0bWVzc2FnZSA9IEpTT04ucGFyc2UoaW5jb21pbmdNZXNzYWdlKTtcclxuXHR9IGNhdGNoIChlKSB7XHJcblx0XHRjb25zdCBlcnJvciA9IGBJbnZhbGlkIEpTT04gcGFzc2VkIHRvIGNhbGxiYWNrOiAke2UubWVzc2FnZX0uIE1lc3NhZ2U6ICR7aW5jb21pbmdNZXNzYWdlfWA7XHJcblx0XHR3YWlscy5Mb2dEZWJ1ZyhlcnJvcik7XHJcblx0XHR0aHJvdyBuZXcgRXJyb3IoZXJyb3IpO1xyXG5cdH1cclxuXHR2YXIgY2FsbGJhY2tJRCA9IG1lc3NhZ2UuY2FsbGJhY2tpZDtcclxuXHR2YXIgY2FsbGJhY2tEYXRhID0gY2FsbGJhY2tzW2NhbGxiYWNrSURdO1xyXG5cdGlmICghY2FsbGJhY2tEYXRhKSB7XHJcblx0XHRjb25zdCBlcnJvciA9IGBDYWxsYmFjayAnJHtjYWxsYmFja0lEfScgbm90IHJlZ2lzdGVyZWQhISFgO1xyXG5cdFx0Y29uc29sZS5lcnJvcihlcnJvcik7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcclxuXHRcdHRocm93IG5ldyBFcnJvcihlcnJvcik7XHJcblx0fVxyXG5cdGNsZWFyVGltZW91dChjYWxsYmFja0RhdGEudGltZW91dEhhbmRsZSk7XHJcblxyXG5cdGRlbGV0ZSBjYWxsYmFja3NbY2FsbGJhY2tJRF07XHJcblxyXG5cdGlmIChtZXNzYWdlLmVycm9yKSB7XHJcblx0XHRjYWxsYmFja0RhdGEucmVqZWN0KG1lc3NhZ2UuZXJyb3IpO1xyXG5cdH0gZWxzZSB7XHJcblx0XHRjYWxsYmFja0RhdGEucmVzb2x2ZShtZXNzYWdlLnJlc3VsdCk7XHJcblx0fVxyXG59XHJcbiIsICIvKlxyXG4gXyAgICAgICBfXyAgICAgIF8gX18gICAgXHJcbnwgfCAgICAgLyAvX19fIF8oXykgL19fX19cclxufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xyXG58IHwvIHwvIC8gL18vIC8gLyAoX18gICkgXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fLyAgXHJcblRoZSBsaWdodHdlaWdodCBmcmFtZXdvcmsgZm9yIHdlYi1saWtlIGFwcHNcclxuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxyXG4qL1xyXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA2ICovXHJcblxyXG5pbXBvcnQgeyBDYWxsIH0gZnJvbSAnLi9jYWxscyc7XHJcblxyXG53aW5kb3cuYmFja2VuZCA9IHt9O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIFNldEJpbmRpbmdzKGJpbmRpbmdzTWFwKSB7XHJcblx0dHJ5IHtcclxuXHRcdGJpbmRpbmdzTWFwID0gSlNPTi5wYXJzZShiaW5kaW5nc01hcCk7XHJcblx0fSBjYXRjaCAoZSkge1xyXG5cdFx0Y29uc29sZS5lcnJvcihlKTtcclxuXHR9XHJcblxyXG5cdC8vIEluaXRpYWxpc2UgdGhlIGJhY2tlbmQgbWFwXHJcblx0d2luZG93LmJhY2tlbmQgPSB3aW5kb3cuYmFja2VuZCB8fCB7fTtcclxuXHJcblx0Ly8gSXRlcmF0ZSBwYWNrYWdlIG5hbWVzXHJcblx0T2JqZWN0LmtleXMoYmluZGluZ3NNYXApLmZvckVhY2goKHBhY2thZ2VOYW1lKSA9PiB7XHJcblxyXG5cdFx0Ly8gQ3JlYXRlIGlubmVyIG1hcCBpZiBpdCBkb2Vzbid0IGV4aXN0XHJcblx0XHR3aW5kb3cuYmFja2VuZFtwYWNrYWdlTmFtZV0gPSB3aW5kb3cuYmFja2VuZFtwYWNrYWdlTmFtZV0gfHwge307XHJcblxyXG5cdFx0Ly8gSXRlcmF0ZSBzdHJ1Y3QgbmFtZXNcclxuXHRcdE9iamVjdC5rZXlzKGJpbmRpbmdzTWFwW3BhY2thZ2VOYW1lXSkuZm9yRWFjaCgoc3RydWN0TmFtZSkgPT4ge1xyXG5cclxuXHRcdFx0Ly8gQ3JlYXRlIGlubmVyIG1hcCBpZiBpdCBkb2Vzbid0IGV4aXN0XHJcblx0XHRcdHdpbmRvdy5iYWNrZW5kW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXSA9IHdpbmRvdy5iYWNrZW5kW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXSB8fCB7fTtcclxuXHJcblx0XHRcdE9iamVjdC5rZXlzKGJpbmRpbmdzTWFwW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXSkuZm9yRWFjaCgobWV0aG9kTmFtZSkgPT4ge1xyXG5cclxuXHRcdFx0XHR3aW5kb3cuYmFja2VuZFtwYWNrYWdlTmFtZV1bc3RydWN0TmFtZV1bbWV0aG9kTmFtZV0gPSBmdW5jdGlvbiAoKSB7XHJcblxyXG5cdFx0XHRcdFx0Ly8gTm8gdGltZW91dCBieSBkZWZhdWx0XHJcblx0XHRcdFx0XHRsZXQgdGltZW91dCA9IDA7XHJcblxyXG5cdFx0XHRcdFx0Ly8gQWN0dWFsIGZ1bmN0aW9uXHJcblx0XHRcdFx0XHRmdW5jdGlvbiBkeW5hbWljKCkge1xyXG5cdFx0XHRcdFx0XHRjb25zdCBhcmdzID0gW10uc2xpY2UuY2FsbChhcmd1bWVudHMpO1xyXG5cdFx0XHRcdFx0XHRyZXR1cm4gQ2FsbChbcGFja2FnZU5hbWUsIHN0cnVjdE5hbWUsIG1ldGhvZE5hbWVdLmpvaW4oJy4nKSwgYXJncywgdGltZW91dCk7XHJcblx0XHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdFx0Ly8gQWxsb3cgc2V0dGluZyB0aW1lb3V0IHRvIGZ1bmN0aW9uXHJcblx0XHRcdFx0XHRkeW5hbWljLnNldFRpbWVvdXQgPSBmdW5jdGlvbiAobmV3VGltZW91dCkge1xyXG5cdFx0XHRcdFx0XHR0aW1lb3V0ID0gbmV3VGltZW91dDtcclxuXHRcdFx0XHRcdH07XHJcblxyXG5cdFx0XHRcdFx0Ly8gQWxsb3cgZ2V0dGluZyB0aW1lb3V0IHRvIGZ1bmN0aW9uXHJcblx0XHRcdFx0XHRkeW5hbWljLmdldFRpbWVvdXQgPSBmdW5jdGlvbiAoKSB7XHJcblx0XHRcdFx0XHRcdHJldHVybiB0aW1lb3V0O1xyXG5cdFx0XHRcdFx0fTtcclxuXHJcblx0XHRcdFx0XHRyZXR1cm4gZHluYW1pYztcclxuXHRcdFx0XHR9KCk7XHJcblx0XHRcdH0pO1xyXG5cdFx0fSk7XHJcblx0fSk7XHJcbn1cclxuIiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgbGlnaHR3ZWlnaHQgZnJhbWV3b3JrIGZvciB3ZWItbGlrZSBhcHBzXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xyXG5pbXBvcnQgKiBhcyBMb2cgZnJvbSAnLi9sb2cnO1xyXG5pbXBvcnQge1xyXG4gICAgZXZlbnRMaXN0ZW5lcnMsXHJcbiAgICBFdmVudHNFbWl0LFxyXG4gICAgRXZlbnRzTm90aWZ5LFxyXG4gICAgRXZlbnRzT2ZmLFxyXG4gICAgRXZlbnRzT24sXHJcbiAgICBFdmVudHNPbmNlLFxyXG4gICAgRXZlbnRzT25NdWx0aXBsZVxyXG59IGZyb20gJy4vZXZlbnRzJztcclxuaW1wb3J0IHtDYWxsYmFjaywgY2FsbGJhY2tzfSBmcm9tICcuL2NhbGxzJztcclxuaW1wb3J0IHtTZXRCaW5kaW5nc30gZnJvbSBcIi4vYmluZGluZ3NcIjtcclxuXHJcbi8vIEJhY2tlbmQgaXMgd2hlcmUgdGhlIEdvIHN0cnVjdCB3cmFwcGVycyBnZXQgYm91bmQgdG9cclxud2luZG93LmJhY2tlbmQgPSB7fTtcclxuXHJcbndpbmRvdy5ydW50aW1lID0ge1xyXG4gICAgLi4uTG9nLFxyXG4gICAgRXZlbnRzT24sXHJcbiAgICBFdmVudHNPbmNlLFxyXG4gICAgRXZlbnRzT25NdWx0aXBsZSxcclxuICAgIEV2ZW50c0VtaXQsXHJcbiAgICBFdmVudHNPZmYsXHJcbn07XHJcblxyXG4vLyBJbml0aWFsaXNlIGdsb2JhbCBpZiBub3QgYWxyZWFkeVxyXG53aW5kb3cud2FpbHMgPSB7XHJcbiAgICBDYWxsYmFjayxcclxuICAgIEV2ZW50c05vdGlmeSxcclxuICAgIFNldEJpbmRpbmdzLFxyXG4gICAgZXZlbnRMaXN0ZW5lcnMsXHJcbiAgICBjYWxsYmFja3NcclxufTtcclxuXHJcbndpbmRvdy53YWlscy5TZXRCaW5kaW5ncyh3aW5kb3cud2FpbHNiaW5kaW5ncyk7XHJcbmRlbGV0ZSB3aW5kb3cud2FpbHMuU2V0QmluZGluZ3M7XHJcbmRlbGV0ZSB3aW5kb3cud2FpbHNiaW5kaW5ncztcclxuXHJcbi8vIFNldHVwIGRyYWcgaGFuZGxlclxyXG4vLyBCYXNlZCBvbiBjb2RlIGZyb206IGh0dHBzOi8vZ2l0aHViLmNvbS9wYXRyMG51cy9EZXNrR2FwXHJcbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCAoZSkgPT4ge1xyXG4gICAgbGV0IGN1cnJlbnRFbGVtZW50ID0gZS50YXJnZXQ7XHJcbiAgICB3aGlsZSAoY3VycmVudEVsZW1lbnQgIT0gbnVsbCkge1xyXG4gICAgICAgIGlmIChjdXJyZW50RWxlbWVudC5oYXNBdHRyaWJ1dGUoJ2RhdGEtd2FpbHMtbm8tZHJhZycpKSB7XHJcbiAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEVsZW1lbnQuaGFzQXR0cmlidXRlKCdkYXRhLXdhaWxzLWRyYWcnKSkge1xyXG4gICAgICAgICAgICB3aW5kb3cuV2FpbHNJbnZva2UoXCJkcmFnXCIpO1xyXG4gICAgICAgICAgICBicmVhaztcclxuICAgICAgICB9XHJcbiAgICAgICAgY3VycmVudEVsZW1lbnQgPSBjdXJyZW50RWxlbWVudC5wYXJlbnRFbGVtZW50O1xyXG4gICAgfVxyXG59KTtcclxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQWtCQSwwQkFBd0IsT0FBTyxTQUFTO0FBSXZDLFdBQU8sWUFBWSxNQUFNLFFBQVE7QUFBQTtBQVMzQixvQkFBa0IsU0FBUztBQUNqQyxtQkFBZSxLQUFLO0FBQUE7QUFTZCxvQkFBa0IsU0FBUztBQUNqQyxtQkFBZSxLQUFLO0FBQUE7QUFTZCxvQkFBa0IsU0FBUztBQUNqQyxtQkFBZSxLQUFLO0FBQUE7QUFTZCxtQkFBaUIsU0FBUztBQUNoQyxtQkFBZSxLQUFLO0FBQUE7QUFTZCxzQkFBb0IsU0FBUztBQUNuQyxtQkFBZSxLQUFLO0FBQUE7QUFTZCxvQkFBa0IsU0FBUztBQUNqQyxtQkFBZSxLQUFLO0FBQUE7QUFTZCxvQkFBa0IsU0FBUztBQUNqQyxtQkFBZSxLQUFLO0FBQUE7QUFTZCx1QkFBcUIsVUFBVTtBQUNyQyxtQkFBZSxLQUFLO0FBQUE7QUFJZCxNQUFNLFdBQVc7QUFBQSxJQUN2QixPQUFPO0FBQUEsSUFDUCxPQUFPO0FBQUEsSUFDUCxNQUFNO0FBQUEsSUFDTixTQUFTO0FBQUEsSUFDVCxPQUFPO0FBQUE7OztBQzdGUix1QkFBZTtBQUFBLElBT1gsWUFBWSxVQUFVLGNBQWM7QUFFaEMscUJBQWUsZ0JBQWdCO0FBRy9CLFdBQUssV0FBVyxDQUFDLFNBQVM7QUFDdEIsaUJBQVMsTUFBTSxNQUFNO0FBRXJCLFlBQUksaUJBQWlCLElBQUk7QUFDckIsaUJBQU87QUFBQTtBQUdYLHdCQUFnQjtBQUNoQixlQUFPLGlCQUFpQjtBQUFBO0FBQUE7QUFBQTtBQUs3QixNQUFNLGlCQUFpQjtBQVV2Qiw0QkFBMEIsV0FBVyxVQUFVLGNBQWM7QUFDaEUsbUJBQWUsYUFBYSxlQUFlLGNBQWM7QUFDekQsVUFBTSxlQUFl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bUJBQWEsUUFBUSxRQUFRO0FBQUE7QUFBQTs7O0FDOUgvQixTQUFPLFVBQVU7QUFFVix1QkFBcUIsYUFBYTtBQUN4QyxRQUFJO0FBQ0gsb0JBQWMsS0FBSyxNQUFNO0FBQUEsYUFDakIsR0FBUDtBQUNELGNBQVEsTUFBTTtBQUFBO0FBSWYsV0FBTyxVQUFVLE9BQU8sV0FBVztBQUduQyxXQUFPLEtBQUssYUFBYSxRQUFRLENBQUMsZ0JBQWdCO0FBR2pELGFBQU8sUUFBUSxlQUFlLE9BQU8sUUFBUSxnQkFBZ0I7QUFHN0QsYUFBTyxLQUFLLFlBQVksY0FBYyxRQUFRLENBQUMsZUFBZTtBQUc3RCxlQUFPLFFBQVEsYUFBYSxjQUFjLE9BQU8sUUFBUSxhQUFhLGVBQWU7QUFFckYsZUFBTyxLQUFLLFlBQVksYUFBYSxhQUFhLFFBQVEsQ0FBQyxlQUFlO0FBRXpFLGlCQUFPLFFBQVEsYUFBYSxZQUFZLGNBQWMsV0FBWTtBQUdqRSxnQkFBSSxVQUFVO0FBR2QsK0JBQW1CO0FBQ2xCLG9CQUFNLE9BQU8sR0FBRyxNQUFNLEtBQUs7QUFDM0IscUJBQU8sS0FBSyxDQUFDLGFBQWEsWUFBWSxZQUFZLEtBQUssTUFBTSxNQUFNO0FBQUE7QUFJcEUsb0JBQVEsYUFBYSxTQUFVLFlBQVk7QUFDMUMsd0JBQVU7QUFBQTtBQUlYLG9CQUFRLGFBQWEsV0FBWTtBQUNoQyxxQkFBTztBQUFBO0FBR1IsbUJBQU87QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBOzs7QUNwQ1osU0FBTyxVQUFVO0FBRWpCLFNBQU8sVUFBVTtBQUFBLE9BQ1Y7QUFBQSxJQUNIO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBO0FBSUosU0FBTyxRQUFRO0FBQUEsSUFDWDtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQTtBQUdKLFNBQU8sTUFBTSxZQUFZLE9BQU87QUFDaEMsU0FBTyxPQUFPLE1BQU07QUFDcEIsU0FBTyxPQUFPO0FBSWQsU0FBTyxpQkFBaUIsYUFBYSxDQUFDLE1BQU07QUFDeEMsUUFBSSxpQkFBaUIsRUFBRTtBQUN2QixXQUFPLGtCQUFrQixNQUFNO0FBQzNCLFVBQUksZUFBZSxhQUFhLHVCQUF1QjtBQUNuRDtBQUFBLGlCQUNPLGVBQWUsYUFBYSxvQkFBb0I7QUFDdkQsZUFBTyxZQUFZO0FBQ25CO0FBQUE7QUFFSix1QkFBaUIsZUFBZTtBQUFBO0FBQUE7IiwKICAibmFtZXMiOiBbXQp9Cg==
+//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiZGVza3RvcC9sb2cuanMiLCAiZGVza3RvcC9ldmVudHMuanMiLCAiZGVza3RvcC9jYWxscy5qcyIsICJkZXNrdG9wL2JpbmRpbmdzLmpzIiwgImRlc2t0b3Avd2luZG93LmpzIiwgImRlc2t0b3AvbWFpbi5qcyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLypcclxuIF8gICAgICAgX18gICAgICBfIF9fXHJcbnwgfCAgICAgLyAvX19fIF8oXykgL19fX19cclxufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xyXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcclxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXHJcblRoZSBsaWdodHdlaWdodCBmcmFtZXdvcmsgZm9yIHdlYi1saWtlIGFwcHNcclxuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxyXG4qL1xyXG5cclxuLyoganNoaW50IGVzdmVyc2lvbjogNiAqL1xyXG5cclxuLyoqXHJcbiAqIFNlbmRzIGEgbG9nIG1lc3NhZ2UgdG8gdGhlIGJhY2tlbmQgd2l0aCB0aGUgZ2l2ZW4gbGV2ZWwgKyBtZXNzYWdlXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBsZXZlbFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxyXG4gKi9cclxuZnVuY3Rpb24gc2VuZExvZ01lc3NhZ2UobGV2ZWwsIG1lc3NhZ2UpIHtcclxuXHJcblx0Ly8gTG9nIE1lc3NhZ2UgZm9ybWF0OlxyXG5cdC8vIGxbdHlwZV1bbWVzc2FnZV1cclxuXHR3aW5kb3cuV2FpbHNJbnZva2UoJ0wnICsgbGV2ZWwgKyBtZXNzYWdlKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIExvZyB0aGUgZ2l2ZW4gdHJhY2UgbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBMb2dUcmFjZShtZXNzYWdlKSB7XHJcblx0c2VuZExvZ01lc3NhZ2UoJ1QnLCBtZXNzYWdlKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIExvZyB0aGUgZ2l2ZW4gbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBMb2dQcmludChtZXNzYWdlKSB7XHJcblx0c2VuZExvZ01lc3NhZ2UoJ1AnLCBtZXNzYWdlKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIExvZyB0aGUgZ2l2ZW4gZGVidWcgbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBMb2dEZWJ1ZyhtZXNzYWdlKSB7XHJcblx0c2VuZExvZ01lc3NhZ2UoJ0QnLCBtZXNzYWdlKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIExvZyB0aGUgZ2l2ZW4gaW5mbyBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIExvZ0luZm8obWVzc2FnZSkge1xyXG5cdHNlbmRMb2dNZXNzYWdlKCdJJywgbWVzc2FnZSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBMb2cgdGhlIGdpdmVuIHdhcm5pbmcgbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBMb2dXYXJuaW5nKG1lc3NhZ2UpIHtcclxuXHRzZW5kTG9nTWVzc2FnZSgnVycsIG1lc3NhZ2UpO1xyXG59XHJcblxyXG4vKipcclxuICogTG9nIHRoZSBnaXZlbiBlcnJvciBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIExvZ0Vycm9yKG1lc3NhZ2UpIHtcclxuXHRzZW5kTG9nTWVzc2FnZSgnRScsIG1lc3NhZ2UpO1xyXG59XHJcblxyXG4vKipcclxuICogTG9nIHRoZSBnaXZlbiBmYXRhbCBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIExvZ0ZhdGFsKG1lc3NhZ2UpIHtcclxuXHRzZW5kTG9nTWVzc2FnZSgnRicsIG1lc3NhZ2UpO1xyXG59XHJcblxyXG4vKipcclxuICogU2V0cyB0aGUgTG9nIGxldmVsIHRvIHRoZSBnaXZlbiBsb2cgbGV2ZWxcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge251bWJlcn0gbG9nbGV2ZWxcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBTZXRMb2dMZXZlbChsb2dsZXZlbCkge1xyXG5cdHNlbmRMb2dNZXNzYWdlKCdTJywgbG9nbGV2ZWwpO1xyXG59XHJcblxyXG4vLyBMb2cgbGV2ZWxzXHJcbmV4cG9ydCBjb25zdCBMb2dMZXZlbCA9IHtcclxuXHRUUkFDRTogMSxcclxuXHRERUJVRzogMixcclxuXHRJTkZPOiAzLFxyXG5cdFdBUk5JTkc6IDQsXHJcblx0RVJST1I6IDUsXHJcbn07XHJcbiIsICIvKlxyXG4gXyAgICAgICBfXyAgICAgIF8gX19cclxufCB8ICAgICAvIC9fX18gXyhfKSAvX19fX1xyXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXHJcbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxyXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cclxuVGhlIGxpZ2h0d2VpZ2h0IGZyYW1ld29yayBmb3Igd2ViLWxpa2UgYXBwc1xyXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XHJcbiovXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDYgKi9cclxuXHJcbi8vIERlZmluZXMgYSBzaW5nbGUgbGlzdGVuZXIgd2l0aCBhIG1heGltdW0gbnVtYmVyIG9mIHRpbWVzIHRvIGNhbGxiYWNrXHJcblxyXG4vKipcclxuICogVGhlIExpc3RlbmVyIGNsYXNzIGRlZmluZXMgYSBsaXN0ZW5lciEgOi0pXHJcbiAqXHJcbiAqIEBjbGFzcyBMaXN0ZW5lclxyXG4gKi9cclxuY2xhc3MgTGlzdGVuZXIge1xyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIExpc3RlbmVyLlxyXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBtYXhDYWxsYmFja3NcclxuICAgICAqIEBtZW1iZXJvZiBMaXN0ZW5lclxyXG4gICAgICovXHJcbiAgICBjb25zdHJ1Y3RvcihjYWxsYmFjaywgbWF4Q2FsbGJhY2tzKSB7XHJcbiAgICAgICAgLy8gRGVmYXVsdCBvZiAtMSBtZWFucyBpbmZpbml0ZVxyXG4gICAgICAgIG1heENhbGxiYWNrcyA9IG1heENhbGxiYWNrcyB8fCAtMTtcclxuICAgICAgICAvLyBDYWxsYmFjayBpbnZva2VzIHRoZSBjYWxsYmFjayB3aXRoIHRoZSBnaXZlbiBkYXRhXHJcbiAgICAgICAgLy8gUmV0dXJucyB0cnVlIGlmIHRoaXMgbGlzdGVuZXIgc2hvdWxkIGJlIGRlc3Ryb3llZFxyXG4gICAgICAgIHRoaXMuQ2FsbGJhY2sgPSAoZGF0YSkgPT4ge1xyXG4gICAgICAgICAgICBjYWxsYmFjay5hcHBseShudWxsLCBkYXRhKTtcclxuICAgICAgICAgICAgLy8gSWYgbWF4Q2FsbGJhY2tzIGlzIGluZmluaXRlLCByZXR1cm4gZmFsc2UgKGRvIG5vdCBkZXN0cm95KVxyXG4gICAgICAgICAgICBpZiAobWF4Q2FsbGJhY2tzID09PSAtMSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIC8vIERlY3JlbWVudCBtYXhDYWxsYmFja3MuIFJldHVybiB0cnVlIGlmIG5vdyAwLCBvdGhlcndpc2UgZmFsc2VcclxuICAgICAgICAgICAgbWF4Q2FsbGJhY2tzIC09IDE7XHJcbiAgICAgICAgICAgIHJldHVybiBtYXhDYWxsYmFja3MgPT09IDA7XHJcbiAgICAgICAgfTtcclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IGNvbnN0IGV2ZW50TGlzdGVuZXJzID0ge307XHJcblxyXG4vKipcclxuICogUmVnaXN0ZXJzIGFuIGV2ZW50IGxpc3RlbmVyIHRoYXQgd2lsbCBiZSBpbnZva2VkIGBtYXhDYWxsYmFja3NgIHRpbWVzIGJlZm9yZSBiZWluZyBkZXN0cm95ZWRcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXHJcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhDYWxsYmFja3NcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG1heENhbGxiYWNrcykge1xyXG4gICAgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0gfHwgW107XHJcbiAgICBjb25zdCB0aGlzTGlzdGVuZXIgPSBuZXcgTGlzdGVuZXIoY2FsbGJhY2ssIG1heENhbGxiYWNrcyk7XHJcbiAgICBldmVudExpc3RlbmVyc1tldmVudE5hbWVdLnB1c2godGhpc0xpc3RlbmVyKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBldmVyeSB0aW1lIHRoZSBldmVudCBpcyBlbWl0dGVkXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxyXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFja1xyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEV2ZW50c09uKGV2ZW50TmFtZSwgY2FsbGJhY2spIHtcclxuICAgIEV2ZW50c09uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgLTEpO1xyXG59XHJcblxyXG4vKipcclxuICogUmVnaXN0ZXJzIGFuIGV2ZW50IGxpc3RlbmVyIHRoYXQgd2lsbCBiZSBpbnZva2VkIG9uY2UgdGhlbiBkZXN0cm95ZWRcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXHJcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzT25jZShldmVudE5hbWUsIGNhbGxiYWNrKSB7XHJcbiAgICBFdmVudHNPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIDEpO1xyXG59XHJcblxyXG5mdW5jdGlvbiBub3RpZnlMaXN0ZW5lcnMoZXZlbnREYXRhKSB7XHJcblxyXG4gICAgLy8gR2V0IHRoZSBldmVudCBuYW1lXHJcbiAgICBsZXQgZXZlbnROYW1lID0gZXZlbnREYXRhLm5hbWU7XHJcblxyXG4gICAgLy8gQ2hlY2sgaWYgd2UgaGF2ZSBhbnkgbGlzdGVuZXJzIGZvciB0aGlzIGV2ZW50XHJcbiAgICBpZiAoZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSkge1xyXG5cclxuICAgICAgICAvLyBLZWVwIGEgbGlzdCBvZiBsaXN0ZW5lciBpbmRleGVzIHRvIGRlc3Ryb3lcclxuICAgICAgICBjb25zdCBuZXdFdmVudExpc3RlbmVyTGlzdCA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0uc2xpY2UoKTtcclxuXHJcbiAgICAgICAgLy8gSXRlcmF0ZSBsaXN0ZW5lcnNcclxuICAgICAgICBmb3IgKGxldCBjb3VudCA9IDA7IGNvdW50IDwgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXS5sZW5ndGg7IGNvdW50ICs9IDEpIHtcclxuXHJcbiAgICAgICAgICAgIC8vIEdldCBuZXh0IGxpc3RlbmVyXHJcbiAgICAgICAgICAgIGNvbnN0IGxpc3RlbmVyID0gZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXVtjb3VudF07XHJcblxyXG4gICAgICAgICAgICBsZXQgZGF0YSA9IGV2ZW50RGF0YS5kYXRhO1xyXG5cclxuICAgICAgICAgICAgLy8gRG8gdGhlIGNhbGxiYWNrXHJcbiAgICAgICAgICAgIGNvbnN0IGRlc3Ryb3kgPSBsaXN0ZW5lci5DYWxsYmFjayhkYXRhKTtcclxuICAgICAgICAgICAgaWYgKGRlc3Ryb3kpIHtcclxuICAgICAgICAgICAgICAgIC8vIGlmIHRoZSBsaXN0ZW5lciBpbmRpY2F0ZWQgdG8gZGVzdHJveSBpdHNlbGYsIGFkZCBpdCB0byB0aGUgZGVzdHJveSBsaXN0XHJcbiAgICAgICAgICAgICAgICBuZXdFdmVudExpc3RlbmVyTGlzdC5zcGxpY2UoY291bnQsIDEpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBVcGRhdGUgY2FsbGJhY2tzIHdpdGggbmV3IGxpc3Qgb2YgbGlzdGVuZXJzXHJcbiAgICAgICAgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSA9IG5ld0V2ZW50TGlzdGVuZXJMaXN0O1xyXG4gICAgfVxyXG59XHJcblxyXG4vKipcclxuICogTm90aWZ5IGluZm9ybXMgZnJvbnRlbmQgbGlzdGVuZXJzIHRoYXQgYW4gZXZlbnQgd2FzIGVtaXR0ZWQgd2l0aCB0aGUgZ2l2ZW4gZGF0YVxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBub3RpZnlNZXNzYWdlIC0gZW5jb2RlZCBub3RpZmljYXRpb24gbWVzc2FnZVxyXG5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNOb3RpZnkobm90aWZ5TWVzc2FnZSkge1xyXG4gICAgLy8gUGFyc2UgdGhlIG1lc3NhZ2VcclxuICAgIGxldCBtZXNzYWdlO1xyXG4gICAgdHJ5IHtcclxuICAgICAgICBtZXNzYWdlID0gSlNPTi5wYXJzZShub3RpZnlNZXNzYWdlKTtcclxuICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICBjb25zdCBlcnJvciA9ICdJbnZhbGlkIEpTT04gcGFzc2VkIHRvIE5vdGlmeTogJyArIG5vdGlmeU1lc3NhZ2U7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGVycm9yKTtcclxuICAgIH1cclxuICAgIG5vdGlmeUxpc3RlbmVycyhtZXNzYWdlKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEVtaXQgYW4gZXZlbnQgd2l0aCB0aGUgZ2l2ZW4gbmFtZSBhbmQgZGF0YVxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNFbWl0KGV2ZW50TmFtZSkge1xyXG5cclxuICAgIGNvbnN0IHBheWxvYWQgPSB7XHJcbiAgICAgICAgbmFtZTogZXZlbnROYW1lLFxyXG4gICAgICAgIGRhdGE6IFtdLnNsaWNlLmFwcGx5KGFyZ3VtZW50cykuc2xpY2UoMSksXHJcbiAgICB9O1xyXG5cclxuICAgIC8vIE5vdGlmeSBKUyBsaXN0ZW5lcnNcclxuICAgIG5vdGlmeUxpc3RlbmVycyhwYXlsb2FkKTtcclxuXHJcbiAgICAvLyBOb3RpZnkgR28gbGlzdGVuZXJzXHJcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ0VFJyArIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIEV2ZW50c09mZihldmVudE5hbWUpIHtcclxuICAgIC8vIFJlbW92ZSBsb2NhbCBsaXN0ZW5lcnNcclxuICAgIGV2ZW50TGlzdGVuZXJzLmRlbGV0ZShldmVudE5hbWUpO1xyXG5cclxuICAgIC8vIE5vdGlmeSBHbyBsaXN0ZW5lcnNcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnRVgnICsgZXZlbnROYW1lKTtcclxufSIsICIvKlxyXG4gXyAgICAgICBfXyAgICAgIF8gX19cclxufCB8ICAgICAvIC9fX18gXyhfKSAvX19fX1xyXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXHJcbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxyXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cclxuVGhlIGxpZ2h0d2VpZ2h0IGZyYW1ld29yayBmb3Igd2ViLWxpa2UgYXBwc1xyXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XHJcbiovXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDYgKi9cclxuXHJcbmV4cG9ydCBjb25zdCBjYWxsYmFja3MgPSB7fTtcclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIGEgbnVtYmVyIGZyb20gdGhlIG5hdGl2ZSBicm93c2VyIHJhbmRvbSBmdW5jdGlvblxyXG4gKlxyXG4gKiBAcmV0dXJucyBudW1iZXJcclxuICovXHJcbmZ1bmN0aW9uIGNyeXB0b1JhbmRvbSgpIHtcclxuXHR2YXIgYXJyYXkgPSBuZXcgVWludDMyQXJyYXkoMSk7XHJcblx0cmV0dXJuIHdpbmRvdy5jcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKGFycmF5KVswXTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgYSBudW1iZXIgdXNpbmcgZGEgb2xkLXNrb29sIE1hdGguUmFuZG9tXHJcbiAqIEkgbGlrZXMgdG8gY2FsbCBpdCBMT0xSYW5kb21cclxuICpcclxuICogQHJldHVybnMgbnVtYmVyXHJcbiAqL1xyXG5mdW5jdGlvbiBiYXNpY1JhbmRvbSgpIHtcclxuXHRyZXR1cm4gTWF0aC5yYW5kb20oKSAqIDkwMDcxOTkyNTQ3NDA5OTE7XHJcbn1cclxuXHJcbi8vIFBpY2sgYSByYW5kb20gbnVtYmVyIGZ1bmN0aW9uIGJhc2VkIG9uIGJyb3dzZXIgY2FwYWJpbGl0eVxyXG52YXIgcmFuZG9tRnVuYztcclxuaWYgKHdpbmRvdy5jcnlwdG8pIHtcclxuXHRyYW5kb21GdW5jID0gY3J5cHRvUmFuZG9tO1xyXG59IGVsc2Uge1xyXG5cdHJhbmRvbUZ1bmMgPSBiYXNpY1JhbmRvbTtcclxufVxyXG5cclxuXHJcbi8qKlxyXG4gKiBDYWxsIHNlbmRzIGEgbWVzc2FnZSB0byB0aGUgYmFja2VuZCB0byBjYWxsIHRoZSBiaW5kaW5nIHdpdGggdGhlXHJcbiAqIGdpdmVuIGRhdGEuIEEgcHJvbWlzZSBpcyByZXR1cm5lZCBhbmQgd2lsbCBiZSBjb21wbGV0ZWQgd2hlbiB0aGVcclxuICogYmFja2VuZCByZXNwb25kcy4gVGhpcyB3aWxsIGJlIHJlc29sdmVkIHdoZW4gdGhlIGNhbGwgd2FzIHN1Y2Nlc3NmdWxcclxuICogb3IgcmVqZWN0ZWQgaWYgYW4gZXJyb3IgaXMgcGFzc2VkIGJhY2suXHJcbiAqIFRoZXJlIGlzIGEgdGltZW91dCBtZWNoYW5pc20uIElmIHRoZSBjYWxsIGRvZXNuJ3QgcmVzcG9uZCBpbiB0aGUgZ2l2ZW5cclxuICogdGltZSAoaW4gbWlsbGlzZWNvbmRzKSB0aGVuIHRoZSBwcm9taXNlIGlzIHJlamVjdGVkLlxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzXHJcbiAqIEBwYXJhbSB7bnVtYmVyPX0gdGltZW91dFxyXG4gKiBAcmV0dXJuc1xyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIENhbGwobmFtZSwgYXJncywgdGltZW91dCkge1xyXG5cclxuXHQvLyBUaW1lb3V0IGluZmluaXRlIGJ5IGRlZmF1bHRcclxuXHRpZiAodGltZW91dCA9PSBudWxsKSB7XHJcblx0XHR0aW1lb3V0ID0gMDtcclxuXHR9XHJcblxyXG5cdC8vIENyZWF0ZSBhIHByb21pc2VcclxuXHRyZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xyXG5cclxuXHRcdC8vIENyZWF0ZSBhIHVuaXF1ZSBjYWxsYmFja0lEXHJcblx0XHR2YXIgY2FsbGJhY2tJRDtcclxuXHRcdGRvIHtcclxuXHRcdFx0Y2FsbGJhY2tJRCA9IG5hbWUgKyAnLScgKyByYW5kb21GdW5jKCk7XHJcblx0XHR9IHdoaWxlIChjYWxsYmFja3NbY2FsbGJhY2tJRF0pO1xyXG5cclxuXHRcdHZhciB0aW1lb3V0SGFuZGxlO1xyXG5cdFx0Ly8gU2V0IHRpbWVvdXRcclxuXHRcdGlmICh0aW1lb3V0ID4gMCkge1xyXG5cdFx0XHR0aW1lb3V0SGFuZGxlID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XHJcblx0XHRcdFx0cmVqZWN0KEVycm9yKCdDYWxsIHRvICcgKyBuYW1lICsgJyB0aW1lZCBvdXQuIFJlcXVlc3QgSUQ6ICcgKyBjYWxsYmFja0lEKSk7XHJcblx0XHRcdH0sIHRpbWVvdXQpO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIFN0b3JlIGNhbGxiYWNrXHJcblx0XHRjYWxsYmFja3NbY2FsbGJhY2tJRF0gPSB7XHJcblx0XHRcdHRpbWVvdXRIYW5kbGU6IHRpbWVvdXRIYW5kbGUsXHJcblx0XHRcdHJlamVjdDogcmVqZWN0LFxyXG5cdFx0XHRyZXNvbHZlOiByZXNvbHZlXHJcblx0XHR9O1xyXG5cclxuXHRcdHRyeSB7XHJcblx0XHRcdGNvbnN0IHBheWxvYWQgPSB7XHJcblx0XHRcdFx0bmFtZSxcclxuXHRcdFx0XHRhcmdzLFxyXG5cdFx0XHRcdGNhbGxiYWNrSUQsXHJcblx0XHRcdH07XHJcblxyXG5cdFx0XHQvLyBNYWtlIHRoZSBjYWxsXHJcblx0XHRcdHdpbmRvdy5XYWlsc0ludm9rZSgnQycgKyBKU09OLnN0cmluZ2lmeShwYXlsb2FkKSk7XHJcblx0XHR9IGNhdGNoIChlKSB7XHJcblx0XHRcdC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxyXG5cdFx0XHRjb25zb2xlLmVycm9yKGUpO1xyXG5cdFx0fVxyXG5cdH0pO1xyXG59XHJcblxyXG5cclxuXHJcbi8qKlxyXG4gKiBDYWxsZWQgYnkgdGhlIGJhY2tlbmQgdG8gcmV0dXJuIGRhdGEgdG8gYSBwcmV2aW91c2x5IGNhbGxlZFxyXG4gKiBiaW5kaW5nIGludm9jYXRpb25cclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gaW5jb21pbmdNZXNzYWdlXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gQ2FsbGJhY2soaW5jb21pbmdNZXNzYWdlKSB7XHJcblx0Ly8gRGVjb2RlIHRoZSBtZXNzYWdlIC0gQ3JlZGl0OiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMTM4NjU2ODBcclxuXHQvL2luY29taW5nTWVzc2FnZSA9IGRlY29kZVVSSUNvbXBvbmVudChpbmNvbWluZ01lc3NhZ2UucmVwbGFjZSgvXFxzKy9nLCAnJykucmVwbGFjZSgvWzAtOWEtZl17Mn0vZywgJyUkJicpKTtcclxuXHJcblx0Ly8gUGFyc2UgdGhlIG1lc3NhZ2VcclxuXHR2YXIgbWVzc2FnZTtcclxuXHR0cnkge1xyXG5cdFx0bWVzc2FnZSA9IEpTT04ucGFyc2UoaW5jb21pbmdNZXNzYWdlKTtcclxuXHR9IGNhdGNoIChlKSB7XHJcblx0XHRjb25zdCBlcnJvciA9IGBJbnZhbGlkIEpTT04gcGFzc2VkIHRvIGNhbGxiYWNrOiAke2UubWVzc2FnZX0uIE1lc3NhZ2U6ICR7aW5jb21pbmdNZXNzYWdlfWA7XHJcblx0XHR3YWlscy5Mb2dEZWJ1ZyhlcnJvcik7XHJcblx0XHR0aHJvdyBuZXcgRXJyb3IoZXJyb3IpO1xyXG5cdH1cclxuXHR2YXIgY2FsbGJhY2tJRCA9IG1lc3NhZ2UuY2FsbGJhY2tpZDtcclxuXHR2YXIgY2FsbGJhY2tEYXRhID0gY2FsbGJhY2tzW2NhbGxiYWNrSURdO1xyXG5cdGlmICghY2FsbGJhY2tEYXRhKSB7XHJcblx0XHRjb25zdCBlcnJvciA9IGBDYWxsYmFjayAnJHtjYWxsYmFja0lEfScgbm90IHJlZ2lzdGVyZWQhISFgO1xyXG5cdFx0Y29uc29sZS5lcnJvcihlcnJvcik7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcclxuXHRcdHRocm93IG5ldyBFcnJvcihlcnJvcik7XHJcblx0fVxyXG5cdGNsZWFyVGltZW91dChjYWxsYmFja0RhdGEudGltZW91dEhhbmRsZSk7XHJcblxyXG5cdGRlbGV0ZSBjYWxsYmFja3NbY2FsbGJhY2tJRF07XHJcblxyXG5cdGlmIChtZXNzYWdlLmVycm9yKSB7XHJcblx0XHRjYWxsYmFja0RhdGEucmVqZWN0KG1lc3NhZ2UuZXJyb3IpO1xyXG5cdH0gZWxzZSB7XHJcblx0XHRjYWxsYmFja0RhdGEucmVzb2x2ZShtZXNzYWdlLnJlc3VsdCk7XHJcblx0fVxyXG59XHJcbiIsICIvKlxyXG4gXyAgICAgICBfXyAgICAgIF8gX18gICAgXHJcbnwgfCAgICAgLyAvX19fIF8oXykgL19fX19cclxufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xyXG58IHwvIHwvIC8gL18vIC8gLyAoX18gICkgXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fLyAgXHJcblRoZSBsaWdodHdlaWdodCBmcmFtZXdvcmsgZm9yIHdlYi1saWtlIGFwcHNcclxuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxyXG4qL1xyXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA2ICovXHJcblxyXG5pbXBvcnQgeyBDYWxsIH0gZnJvbSAnLi9jYWxscyc7XHJcblxyXG53aW5kb3cuYmFja2VuZCA9IHt9O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIFNldEJpbmRpbmdzKGJpbmRpbmdzTWFwKSB7XHJcblx0dHJ5IHtcclxuXHRcdGJpbmRpbmdzTWFwID0gSlNPTi5wYXJzZShiaW5kaW5nc01hcCk7XHJcblx0fSBjYXRjaCAoZSkge1xyXG5cdFx0Y29uc29sZS5lcnJvcihlKTtcclxuXHR9XHJcblxyXG5cdC8vIEluaXRpYWxpc2UgdGhlIGJhY2tlbmQgbWFwXHJcblx0d2luZG93LmJhY2tlbmQgPSB3aW5kb3cuYmFja2VuZCB8fCB7fTtcclxuXHJcblx0Ly8gSXRlcmF0ZSBwYWNrYWdlIG5hbWVzXHJcblx0T2JqZWN0LmtleXMoYmluZGluZ3NNYXApLmZvckVhY2goKHBhY2thZ2VOYW1lKSA9PiB7XHJcblxyXG5cdFx0Ly8gQ3JlYXRlIGlubmVyIG1hcCBpZiBpdCBkb2Vzbid0IGV4aXN0XHJcblx0XHR3aW5kb3cuYmFja2VuZFtwYWNrYWdlTmFtZV0gPSB3aW5kb3cuYmFja2VuZFtwYWNrYWdlTmFtZV0gfHwge307XHJcblxyXG5cdFx0Ly8gSXRlcmF0ZSBzdHJ1Y3QgbmFtZXNcclxuXHRcdE9iamVjdC5rZXlzKGJpbmRpbmdzTWFwW3BhY2thZ2VOYW1lXSkuZm9yRWFjaCgoc3RydWN0TmFtZSkgPT4ge1xyXG5cclxuXHRcdFx0Ly8gQ3JlYXRlIGlubmVyIG1hcCBpZiBpdCBkb2Vzbid0IGV4aXN0XHJcblx0XHRcdHdpbmRvdy5iYWNrZW5kW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXSA9IHdpbmRvdy5iYWNrZW5kW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXSB8fCB7fTtcclxuXHJcblx0XHRcdE9iamVjdC5rZXlzKGJpbmRpbmdzTWFwW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXSkuZm9yRWFjaCgobWV0aG9kTmFtZSkgPT4ge1xyXG5cclxuXHRcdFx0XHR3aW5kb3cuYmFja2VuZFtwYWNrYWdlTmFtZV1bc3RydWN0TmFtZV1bbWV0aG9kTmFtZV0gPSBmdW5jdGlvbiAoKSB7XHJcblxyXG5cdFx0XHRcdFx0Ly8gTm8gdGltZW91dCBieSBkZWZhdWx0XHJcblx0XHRcdFx0XHRsZXQgdGltZW91dCA9IDA7XHJcblxyXG5cdFx0XHRcdFx0Ly8gQWN0dWFsIGZ1bmN0aW9uXHJcblx0XHRcdFx0XHRmdW5jdGlvbiBkeW5hbWljKCkge1xyXG5cdFx0XHRcdFx0XHRjb25zdCBhcmdzID0gW10uc2xpY2UuY2FsbChhcmd1bWVudHMpO1xyXG5cdFx0XHRcdFx0XHRyZXR1cm4gQ2FsbChbcGFja2FnZU5hbWUsIHN0cnVjdE5hbWUsIG1ldGhvZE5hbWVdLmpvaW4oJy4nKSwgYXJncywgdGltZW91dCk7XHJcblx0XHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdFx0Ly8gQWxsb3cgc2V0dGluZyB0aW1lb3V0IHRvIGZ1bmN0aW9uXHJcblx0XHRcdFx0XHRkeW5hbWljLnNldFRpbWVvdXQgPSBmdW5jdGlvbiAobmV3VGltZW91dCkge1xyXG5cdFx0XHRcdFx0XHR0aW1lb3V0ID0gbmV3VGltZW91dDtcclxuXHRcdFx0XHRcdH07XHJcblxyXG5cdFx0XHRcdFx0Ly8gQWxsb3cgZ2V0dGluZyB0aW1lb3V0IHRvIGZ1bmN0aW9uXHJcblx0XHRcdFx0XHRkeW5hbWljLmdldFRpbWVvdXQgPSBmdW5jdGlvbiAoKSB7XHJcblx0XHRcdFx0XHRcdHJldHVybiB0aW1lb3V0O1xyXG5cdFx0XHRcdFx0fTtcclxuXHJcblx0XHRcdFx0XHRyZXR1cm4gZHluYW1pYztcclxuXHRcdFx0XHR9KCk7XHJcblx0XHRcdH0pO1xyXG5cdFx0fSk7XHJcblx0fSk7XHJcbn1cclxuIiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgbGlnaHR3ZWlnaHQgZnJhbWV3b3JrIGZvciB3ZWItbGlrZSBhcHBzXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1JlbG9hZCgpIHtcclxuICAgIHdpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKTtcclxufVxyXG4iLCAiLypcclxuIF9cdCAgIF9fXHQgIF8gX19cclxufCB8XHQgLyAvX19fIF8oXykgL19fX19cclxufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xyXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcclxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXHJcblRoZSBsaWdodHdlaWdodCBmcmFtZXdvcmsgZm9yIHdlYi1saWtlIGFwcHNcclxuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxyXG4qL1xyXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXHJcbmltcG9ydCAqIGFzIExvZyBmcm9tICcuL2xvZyc7XHJcbmltcG9ydCB7ZXZlbnRMaXN0ZW5lcnMsIEV2ZW50c0VtaXQsIEV2ZW50c05vdGlmeSwgRXZlbnRzT2ZmLCBFdmVudHNPbiwgRXZlbnRzT25jZSwgRXZlbnRzT25NdWx0aXBsZX0gZnJvbSAnLi9ldmVudHMnO1xyXG5pbXBvcnQge0NhbGxiYWNrLCBjYWxsYmFja3N9IGZyb20gJy4vY2FsbHMnO1xyXG5pbXBvcnQge1NldEJpbmRpbmdzfSBmcm9tIFwiLi9iaW5kaW5nc1wiO1xyXG5pbXBvcnQge1dpbmRvd1JlbG9hZH0gZnJvbSBcIi4vd2luZG93XCI7XHJcblxyXG4vLyBCYWNrZW5kIGlzIHdoZXJlIHRoZSBHbyBzdHJ1Y3Qgd3JhcHBlcnMgZ2V0IGJvdW5kIHRvXHJcbndpbmRvdy5iYWNrZW5kID0ge307XHJcblxyXG53aW5kb3cucnVudGltZSA9IHtcclxuICAgIC4uLkxvZyxcclxuICAgIEV2ZW50c09uLFxyXG4gICAgRXZlbnRzT25jZSxcclxuICAgIEV2ZW50c09uTXVsdGlwbGUsXHJcbiAgICBFdmVudHNFbWl0LFxyXG4gICAgRXZlbnRzT2ZmLFxyXG4gICAgV2luZG93UmVsb2FkLFxyXG59O1xyXG5cclxuLy8gSW5pdGlhbGlzZSBnbG9iYWwgaWYgbm90IGFscmVhZHlcclxud2luZG93LndhaWxzID0ge1xyXG4gICAgQ2FsbGJhY2ssXHJcbiAgICBFdmVudHNOb3RpZnksXHJcbiAgICBTZXRCaW5kaW5ncyxcclxuICAgIGV2ZW50TGlzdGVuZXJzLFxyXG4gICAgY2FsbGJhY2tzXHJcbn07XHJcblxyXG53aW5kb3cud2FpbHMuU2V0QmluZGluZ3Mod2luZG93LndhaWxzYmluZGluZ3MpO1xyXG5kZWxldGUgd2luZG93LndhaWxzLlNldEJpbmRpbmdzO1xyXG5kZWxldGUgd2luZG93LndhaWxzYmluZGluZ3M7XHJcblxyXG4vLyBTZXR1cCBkcmFnIGhhbmRsZXJcclxuLy8gQmFzZWQgb24gY29kZSBmcm9tOiBodHRwczovL2dpdGh1Yi5jb20vcGF0cjBudXMvRGVza0dhcFxyXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgKGUpID0+IHtcclxuICAgIGxldCBjdXJyZW50RWxlbWVudCA9IGUudGFyZ2V0O1xyXG4gICAgd2hpbGUgKGN1cnJlbnRFbGVtZW50ICE9IG51bGwpIHtcclxuICAgICAgICBpZiAoY3VycmVudEVsZW1lbnQuaGFzQXR0cmlidXRlKCdkYXRhLXdhaWxzLW5vLWRyYWcnKSkge1xyXG4gICAgICAgICAgICBicmVhaztcclxuICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRFbGVtZW50Lmhhc0F0dHJpYnV0ZSgnZGF0YS13YWlscy1kcmFnJykpIHtcclxuICAgICAgICAgICAgd2luZG93LldhaWxzSW52b2tlKFwiZHJhZ1wiKTtcclxuICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGN1cnJlbnRFbGVtZW50ID0gY3VycmVudEVsZW1lbnQucGFyZW50RWxlbWVudDtcclxuICAgIH1cclxufSk7XHJcbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFrQkEsMEJBQXdCLE9BQU8sU0FBUztBQUl2QyxXQUFPLFlBQVksTUFBTSxRQUFRO0FBQUE7QUFTM0Isb0JBQWtCLFNBQVM7QUFDakMsbUJBQWUsS0FBSztBQUFBO0FBU2Qsb0JBQWtCLFNBQVM7QUFDakMsbUJBQWUsS0FBSztBQUFBO0FBU2Qsb0JBQWtCLFNBQVM7QUFDakMsbUJBQWUsS0FBSztBQUFBO0FBU2QsbUJBQWlCLFNBQVM7QUFDaEMsbUJBQWUsS0FBSztBQUFBO0FBU2Qsc0JBQW9CLFNBQVM7QUFDbkMsbUJBQWUsS0FBSztBQUFBO0FBU2Qsb0JBQWtCLFNBQVM7QUFDakMsbUJBQWUsS0FBSztBQUFBO0FBU2Qsb0JBQWtCLFNBQVM7QUFDakMsbUJBQWUsS0FBSztBQUFBO0FBU2QsdUJBQXFCLFVBQVU7QUFDckMsbUJBQWUsS0FBSztBQUFBO0FBSWQsTUFB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
diff --git a/v2/internal/frontend/runtime/runtime_prod_desktop.js b/v2/internal/frontend/runtime/runtime_prod_desktop.js
index 75670e39f..993bc84ee 100644
--- a/v2/internal/frontend/runtime/runtime_prod_desktop.js
+++ b/v2/internal/frontend/runtime/runtime_prod_desktop.js
@@ -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;o0&&(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;t0&&(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}});})();
diff --git a/v2/internal/process/process.go b/v2/internal/process/process.go
index 55c0f79b4..8727799fc 100644
--- a/v2/internal/process/process.go
+++ b/v2/internal/process/process.go
@@ -3,22 +3,18 @@ package process
import (
"os"
"os/exec"
-
- "github.com/wailsapp/wails/v2/pkg/clilogger"
)
// Process defines a process that can be executed
type Process struct {
- logger *clilogger.CLILogger
cmd *exec.Cmd
exitChannel chan bool
Running bool
}
// 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{
- logger: logger,
cmd: exec.Command(cmd, args...),
exitChannel: make(chan bool, 1),
}
@@ -28,7 +24,7 @@ func NewProcess(logger *clilogger.CLILogger, cmd string, args ...string) *Proces
}
// Start the process
-func (p *Process) Start() error {
+func (p *Process) Start(exitCodeChannel chan int) error {
err := p.cmd.Start()
if err != nil {
@@ -37,13 +33,14 @@ func (p *Process) Start() error {
p.Running = true
- go func(cmd *exec.Cmd, running *bool, logger *clilogger.CLILogger, exitChannel chan bool) {
- logger.Println("Starting process (PID: %d)", cmd.Process.Pid)
- _ = cmd.Wait()
- logger.Println("Exiting process (PID: %d)", cmd.Process.Pid)
+ go func(cmd *exec.Cmd, running *bool, exitChannel chan bool, exitCodeChannel chan int) {
+ err := cmd.Wait()
+ if err == nil {
+ exitCodeChannel <- 0
+ }
*running = false
exitChannel <- true
- }(p.cmd, &p.Running, p.logger, p.exitChannel)
+ }(p.cmd, &p.Running, p.exitChannel, exitCodeChannel)
return nil
}
diff --git a/v2/pkg/runtime/window.go b/v2/pkg/runtime/window.go
index 50c05d8f3..d098b474d 100644
--- a/v2/pkg/runtime/window.go
+++ b/v2/pkg/runtime/window.go
@@ -28,6 +28,12 @@ func WindowCenter(ctx context.Context) {
appFrontend.WindowCenter()
}
+// WindowReload will reload the window contents
+func WindowReload(ctx context.Context) {
+ appFrontend := getFrontend(ctx)
+ appFrontend.WindowReload()
+}
+
// WindowShow shows the window if hidden
func WindowShow(ctx context.Context) {
appFrontend := getFrontend(ctx)