diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 0b1397fb5..1c31a1cba 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -11,7 +11,9 @@ body:
Before submitting this issue, please do the following:
- Do a web search for your error. This usually leads to a much better understanding of the issue.
- Prove that the error is indeed a Wails bug and not an application bug, with a specific set of steps to reproduce.
- - Search both the issue tracker (even closed issues) and discussion forums.
+ - Search the issue tracker using [this link](https://github.com/wailsapp/wails/issues?q=is%3Aissue+).
+ - Search the [discussion forums](https://github.com/wailsapp/wails/discussions?discussions_q=type+your+issue+here).
+ - Read the [Troubleshooting Guide](https://wails.io/docs/next/guides/troubleshooting).
- Try to fix it yourself. Keep a list of things you have done to fix the problem.
If after doing all the above, the problem remains, please continue with this ticket providing *all* the information requested.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
index 317b10cdd..292a039a2 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.yml
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -7,6 +7,7 @@ body:
- type: markdown
attributes:
value: |
+ Before opening a feature request, please check the [Roadmap](https://github.com/wailsapp/wails/discussions/1484) to see if it has already been requested.
***Please note: No new feature requests are being accepted for Wails v1***
- type: textarea
diff --git a/.github/stale.yml b/.github/stale.yml
index a0c92fdff..c99691f70 100644
--- a/.github/stale.yml
+++ b/.github/stale.yml
@@ -8,7 +8,7 @@ exemptLabels:
- security
- onhold
- inprogress
- - "Selected for development"
+ - "Selected For Development"
# Label to use when marking an issue as stale
staleLabel: wontfix
# Comment to post when marking an issue as stale. Set to `false` to disable
diff --git a/README.md b/README.md
index d846b36d1..9544568ea 100644
--- a/README.md
+++ b/README.md
@@ -106,8 +106,8 @@ This project is supported by these kind people / companies:
-
-
+
+
@@ -158,9 +158,6 @@ This project is supported by these kind people / companies:
-
-
-
@@ -194,12 +191,23 @@ This project is supported by these kind people / companies:
-
-
+
+
+
+
+
+
+
+
+## Roadmap
+
+The project roadmap may be found [here](https://github.com/wailsapp/wails/discussions/1484). Please consult
+this before open up an enhancement request.
+
## Installation
The installation instructions are on the [official website](https://wails.io/docs/gettingstarted/installation).
@@ -211,8 +219,8 @@ The installation instructions are on the [official website](https://wails.io/doc
- Is this an alternative to Electron?
Depends on your requirements. It's designed to make it easy for Go programmers to make lightweight desktop
- applications or add a frontend to their existing applications. Whilst Wails does not currently offer hooks into native
- elements such as menus, this may change in the future.
+ applications or add a frontend to their existing applications. Wails v2 does offer native elements such as menus
+ and dialogs, so it is becoming a lightweight electron alternative.
- Who is this project aimed at?
diff --git a/README.zh-Hans.md b/README.zh-Hans.md
index 014104a74..334ece9b6 100644
--- a/README.zh-Hans.md
+++ b/README.zh-Hans.md
@@ -116,8 +116,8 @@ Wails v2 已针对所有 3 个平台发布了 Beta 版。如果您有兴趣尝
-
-
+
+
@@ -168,9 +168,6 @@ Wails v2 已针对所有 3 个平台发布了 Beta 版。如果您有兴趣尝
-
-
-
@@ -204,8 +201,14 @@ Wails v2 已针对所有 3 个平台发布了 Beta 版。如果您有兴趣尝
-
-
+
+
+
+
+
+
+
+
diff --git a/v2/cmd/wails/internal/commands/build/build.go b/v2/cmd/wails/internal/commands/build/build.go
index 22134658a..bffff9e52 100644
--- a/v2/cmd/wails/internal/commands/build/build.go
+++ b/v2/cmd/wails/internal/commands/build/build.go
@@ -99,6 +99,12 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
trimpath := false
command.BoolFlag("trimpath", "Remove all file system paths from the resulting executable", &trimpath)
+ raceDetector := false
+ command.BoolFlag("race", "Build with Go's race detector", &raceDetector)
+
+ windowsConsole := false
+ command.BoolFlag("windowsconsole", "Keep the console when building for Windows", &windowsConsole)
+
command.Action(func() error {
quiet := verbosity == 0
@@ -180,6 +186,8 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
UserTags: userTags,
WebView2Strategy: wv2rtstrategy,
TrimPath: trimpath,
+ RaceDetector: raceDetector,
+ WindowsConsole: windowsConsole,
}
// Start a new tabwriter
@@ -197,6 +205,7 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
_, _ = fmt.Fprintf(w, "Clean Build Dir: \t%t\n", buildOptions.CleanBuildDirectory)
_, _ = fmt.Fprintf(w, "LDFlags: \t\"%s\"\n", buildOptions.LDFlags)
_, _ = fmt.Fprintf(w, "Tags: \t[%s]\n", strings.Join(buildOptions.UserTags, ","))
+ _, _ = fmt.Fprintf(w, "Race Detector: \t%t\n", buildOptions.RaceDetector)
if len(buildOptions.OutputFile) > 0 && targets.Length() == 1 {
_, _ = fmt.Fprintf(w, "Output File: \t%s\n", buildOptions.OutputFile)
}
@@ -229,6 +238,7 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
"linux",
"linux/amd64",
"linux/arm64",
+ "linux/arm",
"windows",
"windows/amd64",
"windows/arm64",
@@ -259,10 +269,9 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
// Calculate platform and arch
platformSplit := strings.Split(platform, "/")
buildOptions.Platform = platformSplit[0]
+ buildOptions.Arch = runtime.GOARCH
if system.IsAppleSilicon {
buildOptions.Arch = "arm64"
- } else {
- buildOptions.Arch = runtime.GOARCH
}
if len(platformSplit) == 2 {
buildOptions.Arch = platformSplit[1]
@@ -330,7 +339,7 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
// Output stats
buildOptions.Logger.Println(fmt.Sprintf("Built '%s' in %s.\n", outputFilename, time.Since(start).Round(time.Millisecond).String()))
- outputBinaries[platform] = outputFilename
+ outputBinaries[buildOptions.Platform+"/"+buildOptions.Arch] = outputFilename
})
if targetErr != nil {
diff --git a/v2/cmd/wails/internal/commands/dev/dev.go b/v2/cmd/wails/internal/commands/dev/dev.go
index 712e7ea65..97604ee33 100644
--- a/v2/cmd/wails/internal/commands/dev/dev.go
+++ b/v2/cmd/wails/internal/commands/dev/dev.go
@@ -2,6 +2,7 @@ package dev
import (
"context"
+ "errors"
"fmt"
"io"
"net"
@@ -36,16 +37,25 @@ import (
)
func LogGreen(message string, args ...interface{}) {
+ if len(message) == 0 {
+ return
+ }
text := fmt.Sprintf(message, args...)
println(colour.Green(text))
}
func LogRed(message string, args ...interface{}) {
+ if len(message) == 0 {
+ return
+ }
text := fmt.Sprintf(message, args...)
println(colour.Red(text))
}
func LogDarkYellow(message string, args ...interface{}) {
+ if len(message) == 0 {
+ return
+ }
text := fmt.Sprintf(message, args...)
println(colour.DarkYellow(text))
}
@@ -66,6 +76,7 @@ type devFlags struct {
reloadDirs string
openBrowser bool
noReload bool
+ noGen bool
wailsjsdir string
tags string
verbosity int
@@ -75,6 +86,7 @@ type devFlags struct {
devServer string
appargs string
saveConfig bool
+ raceDetector bool
frontendDevServerURL string
}
@@ -92,6 +104,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
command.StringFlag("reloaddirs", "Additional directories to trigger reloads (comma separated)", &flags.reloadDirs)
command.BoolFlag("browser", "Open application in browser", &flags.openBrowser)
command.BoolFlag("noreload", "Disable reload on asset change", &flags.noReload)
+ command.BoolFlag("nogen", "Disable generate module", &flags.noGen)
command.StringFlag("wailsjsdir", "Directory to generate the Wails JS modules", &flags.wailsjsdir)
command.StringFlag("tags", "tags to pass to Go compiler (quoted and space separated)", &flags.tags)
command.IntFlag("v", "Verbosity level (0 - silent, 1 - standard, 2 - verbose)", &flags.verbosity)
@@ -100,8 +113,9 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
command.IntFlag("debounce", "The amount of time to wait to trigger a reload on change", &flags.debounceMS)
command.StringFlag("devserver", "The address of the wails dev server", &flags.devServer)
command.StringFlag("frontenddevserverurl", "The url of the external frontend dev server to use", &flags.frontendDevServerURL)
- command.StringFlag("appargs", "arguments to pass to the underlying app (quoted and space searated)", &flags.appargs)
+ command.StringFlag("appargs", "arguments to pass to the underlying app (quoted and space separated)", &flags.appargs)
command.BoolFlag("save", "Save given flags as defaults", &flags.saveConfig)
+ command.BoolFlag("race", "Build with Go's race detector", &flags.raceDetector)
command.Action(func() error {
// Create logger
@@ -148,22 +162,22 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
return err
}
- self := os.Args[0]
- if flags.tags != "" {
- err = runCommand(cwd, true, self, "generate", "module", "-tags", flags.tags)
- } else {
- err = runCommand(cwd, true, self, "generate", "module")
- }
- if err != nil {
- return err
+ if !flags.noGen {
+ self := os.Args[0]
+ if flags.tags != "" {
+ err = runCommand(cwd, true, self, "generate", "module", "-tags", flags.tags)
+ } else {
+ err = runCommand(cwd, true, self, "generate", "module")
+ }
+ if err != nil {
+ return err
+ }
}
buildOptions := generateBuildOptions(flags)
buildOptions.Logger = logger
buildOptions.UserTags = internal.ParseUserTags(flags.tags)
- var debugBinaryProcess *process.Process = nil
-
// Setup signal handler
quitChannel := make(chan os.Signal, 1)
signal.Notify(quitChannel, os.Interrupt, os.Kill, syscall.SIGTERM)
@@ -171,19 +185,23 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
// Do initial build
logger.Println("Building application for development...")
- newProcess, appBinary, err := restartApp(buildOptions, debugBinaryProcess, flags, exitCodeChannel)
+ debugBinaryProcess, appBinary, err := restartApp(buildOptions, nil, flags, exitCodeChannel)
if err != nil {
return err
}
- if newProcess != nil {
- debugBinaryProcess = newProcess
- }
+ defer func() {
+ if err := killProcessAndCleanupBinary(debugBinaryProcess, appBinary); err != nil {
+ LogDarkYellow("Unable to kill process and cleanup binary: %s", err)
+ }
+ }()
// frontend:dev:watcher command.
if command := projectConfig.DevWatcherCommand; command != "" {
- var devCommandWaitGroup sync.WaitGroup
- closer := runFrontendDevWatcherCommand(cwd, command, &devCommandWaitGroup)
- defer closer(&devCommandWaitGroup)
+ closer, err := runFrontendDevWatcherCommand(cwd, command)
+ if err != nil {
+ return err
+ }
+ defer closer()
}
// open browser
@@ -215,22 +233,17 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
LogGreen("Using reload debounce setting of %d milliseconds", flags.debounceMS)
// Watch for changes and trigger restartApp()
- doWatcherLoop(buildOptions, debugBinaryProcess, flags, watcher, exitCodeChannel, quitChannel, devServerURL)
+ debugBinaryProcess = doWatcherLoop(buildOptions, debugBinaryProcess, flags, watcher, exitCodeChannel, quitChannel, devServerURL)
- // Kill the current program if running
- if debugBinaryProcess != nil {
- err := debugBinaryProcess.Kill()
- if err != nil {
- return err
- }
- }
-
- // Remove dev binary
- err = os.Remove(appBinary)
- if err != nil {
+ // Kill the current program if running and remove dev binary
+ if err := killProcessAndCleanupBinary(debugBinaryProcess, appBinary); err != nil {
return err
}
+ // Reset the process and the binary so the defer knows about it and is a nop.
+ debugBinaryProcess = nil
+ appBinary = ""
+
LogGreen("Development mode exited")
return nil
@@ -238,6 +251,22 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
return nil
}
+func killProcessAndCleanupBinary(process *process.Process, binary string) error {
+ if process != nil && process.Running {
+ if err := process.Kill(); err != nil {
+ return err
+ }
+ }
+
+ if binary != "" {
+ err := os.Remove(binary)
+ if err != nil && !errors.Is(err, os.ErrNotExist) {
+ return err
+ }
+ }
+ return nil
+}
+
func syncGoModVersion(cwd string) error {
gomodFilename := filepath.Join(cwd, "go.mod")
gomodData, err := os.ReadFile(gomodFilename)
@@ -299,6 +328,7 @@ func generateBuildOptions(flags devFlags) *build.Options {
IgnoreFrontend: false,
Verbosity: flags.verbosity,
WailsJSDir: flags.wailsjsdir,
+ RaceDetector: flags.raceDetector,
}
return result
@@ -381,35 +411,39 @@ func loadAndMergeProjectConfig(cwd string, flags *devFlags) (*project.Project, e
}
// runFrontendDevWatcherCommand will run the `frontend:dev:watcher` command if it was given, ex- `npm run dev`
-func runFrontendDevWatcherCommand(cwd string, devCommand string, wg *sync.WaitGroup) func(group *sync.WaitGroup) {
- LogGreen("Running frontend dev watcher command: '%s'", devCommand)
+func runFrontendDevWatcherCommand(cwd string, devCommand string) (func(), error) {
ctx, cancel := context.WithCancel(context.Background())
dir := filepath.Join(cwd, "frontend")
cmdSlice := strings.Split(devCommand, " ")
- wg.Add(1)
cmd := exec.CommandContext(ctx, cmdSlice[0], cmdSlice[1:]...)
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
cmd.Dir = dir
-
setParentGID(cmd)
- go func(ctx context.Context, devCommand string, cwd string, wg *sync.WaitGroup) {
- err := cmd.Run()
- if err != nil {
+ if err := cmd.Start(); err != nil {
+ cancel()
+ return nil, fmt.Errorf("Unable to start frontend DevWatcher: %w", err)
+ }
+
+ LogGreen("Running frontend DevWatcher command: '%s'", devCommand)
+ var wg sync.WaitGroup
+ wg.Add(1)
+ go func() {
+ if err := cmd.Wait(); err != nil {
if err.Error() != "exit status 1" {
- LogRed("Error from '%s': %s", devCommand, err.Error())
+ LogRed("Error from DevWatcher '%s': %s", devCommand, err.Error())
}
}
- LogGreen("Dev command exited!")
+ LogGreen("DevWatcher command exited!")
wg.Done()
- }(ctx, devCommand, cwd, wg)
+ }()
- return func(wg *sync.WaitGroup) {
+ return func() {
killProc(cmd, devCommand)
- LogGreen("Dev command killed!")
+ LogGreen("DevWatcher command killed!")
cancel()
wg.Wait()
- }
+ }, nil
}
// initialiseWatcher creates the project directory watcher that will trigger recompile
@@ -456,8 +490,13 @@ func restartApp(buildOptions *build.Options, debugBinaryProcess *process.Process
appBinary, err := build.Build(buildOptions)
println()
if err != nil {
- LogRed("Build error - continuing to run current version")
- LogDarkYellow(err.Error())
+ LogRed("Build error - " + err.Error())
+
+ msg := "Continuing to run current version"
+ if debugBinaryProcess == nil {
+ msg = "No version running, build will be retriggered as soon as changes have been detected"
+ }
+ LogDarkYellow(msg)
return nil, "", nil
}
@@ -503,12 +542,8 @@ func restartApp(buildOptions *build.Options, debugBinaryProcess *process.Process
}
// doWatcherLoop is the main watch loop that runs while dev is active
-func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Process, flags devFlags, watcher *fsnotify.Watcher, exitCodeChannel chan int, quitChannel chan os.Signal, devServerURL *url.URL) {
+func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Process, flags devFlags, watcher *fsnotify.Watcher, exitCodeChannel chan int, quitChannel chan os.Signal, devServerURL *url.URL) *process.Process {
// Main Loop
- var (
- err error
- newBinaryProcess *process.Process
- )
var extensionsThatTriggerARebuild = sliceToMap(strings.Split(flags.extensions, ","))
var dirsThatTriggerAReload []string
for _, dir := range strings.Split(flags.reloadDirs, ",") {
@@ -534,7 +569,7 @@ func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Proc
assetDirURL := joinPath(devServerURL, "/wails/assetdir")
reloadURL := joinPath(devServerURL, "/wails/reload")
for quit == false {
- //reload := false
+ // reload := false
select {
case exitCode := <-exitCodeChannel:
if exitCode == 0 {
@@ -579,7 +614,7 @@ func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Proc
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!
+ // node_modules is BANNED!
if !strings.Contains(item.Name, "node_modules") {
err := watcher.Add(item.Name)
if err != nil {
@@ -594,7 +629,7 @@ func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Proc
rebuild = false
LogGreen("[Rebuild triggered] files updated")
// Try and build the app
- newBinaryProcess, _, err = restartApp(buildOptions, debugBinaryProcess, flags, exitCodeChannel)
+ newBinaryProcess, _, err := restartApp(buildOptions, debugBinaryProcess, flags, exitCodeChannel)
if err != nil {
LogRed("Error during build: %s", err.Error())
continue
@@ -640,7 +675,7 @@ func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Proc
}
if reload {
reload = false
- _, err = http.Get(reloadURL)
+ _, err := http.Get(reloadURL)
if err != nil {
LogRed("Error during refresh: %s", err.Error())
}
@@ -650,6 +685,7 @@ func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Proc
quit = true
}
}
+ return debugBinaryProcess
}
func joinPath(url *url.URL, subPath string) string {
diff --git a/v2/cmd/wails/internal/commands/dev/dev_other.go b/v2/cmd/wails/internal/commands/dev/dev_other.go
index 15267ceb2..c93aecfe4 100644
--- a/v2/cmd/wails/internal/commands/dev/dev_other.go
+++ b/v2/cmd/wails/internal/commands/dev/dev_other.go
@@ -6,6 +6,8 @@ package dev
import (
"os/exec"
"syscall"
+
+ "golang.org/x/sys/unix"
)
func setParentGID(cmd *exec.Cmd) {
@@ -15,6 +17,10 @@ func setParentGID(cmd *exec.Cmd) {
}
func killProc(cmd *exec.Cmd, devCommand string) {
+ if cmd == nil || cmd.Process == nil {
+ return
+ }
+
// Experiencing the same issue on macOS BigSur
// I'm using Vite, but I would imagine this could be an issue with Node (npm) in general
// Also, after several edit/rebuild cycles any abnormal shutdown (crash or CTRL-C) may still leave Node running
@@ -22,7 +28,7 @@ func killProc(cmd *exec.Cmd, devCommand string) {
// Not tested on *nix
pgid, err := syscall.Getpgid(cmd.Process.Pid)
if err == nil {
- err := syscall.Kill(-pgid, 15) // note the minus sign
+ err := syscall.Kill(-pgid, unix.SIGTERM) // note the minus sign
if err != nil {
LogRed("Error from '%s' when attempting to kill the process: %s", devCommand, err.Error())
}
diff --git a/v2/cmd/wails/internal/commands/generate/module.go b/v2/cmd/wails/internal/commands/generate/module.go
index d4b87f392..62d8257c7 100644
--- a/v2/cmd/wails/internal/commands/generate/module.go
+++ b/v2/cmd/wails/internal/commands/generate/module.go
@@ -50,10 +50,8 @@ func AddModuleCommand(app *clir.Cli, parent *clir.Command, w io.Writer) error {
return fmt.Errorf("%s\n%s\n%s", stdout, stderr, err)
}
- err = os.Remove(filename)
- if err != nil {
- return err
- }
+ // Best effort removal of temp file
+ _ = os.Remove(filename)
return nil
})
diff --git a/v2/cmd/wails/internal/commands/generate/template/base/go.sum b/v2/cmd/wails/internal/commands/generate/template/base/go.sum
index 63a3181cc..92f4d6d57 100644
--- a/v2/cmd/wails/internal/commands/generate/template/base/go.sum
+++ b/v2/cmd/wails/internal/commands/generate/template/base/go.sum
@@ -53,8 +53,6 @@ github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oO
github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA=
github.com/leaanthony/go-ansi-parser v1.0.1 h1:97v6c5kYppVsbScf4r/VZdXyQ21KQIfeQOk2DgKxGG4=
github.com/leaanthony/go-ansi-parser v1.0.1/go.mod h1:7arTzgVI47srICYhvgUV4CGd063sGEeoSlych5yeSPM=
-github.com/leaanthony/go-common-file-dialog v1.0.3 h1:O0uGjKnWtdEADGrkg+TyAAbZylykMwwx/MNEXn9fp+Y=
-github.com/leaanthony/go-common-file-dialog v1.0.3/go.mod h1:TGhEc9eSJgRsupZ+iH1ZgAOnEo9zp05cRH2j08RPrF0=
github.com/leaanthony/gosod v1.0.3 h1:Fnt+/B6NjQOVuCWOKYRREZnjGyvg+mEhd1nkkA04aTQ=
github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4=
github.com/leaanthony/idgen v1.0.0/go.mod h1:4nBZnt8ml/f/ic/EVQuLxuj817RccT2fyrUaZFxrcVA=
diff --git a/v2/cmd/wails/internal/commands/generate/template/base/go.tmpl.mod b/v2/cmd/wails/internal/commands/generate/template/base/go.tmpl.mod
index 1555a4829..fcef41340 100644
--- a/v2/cmd/wails/internal/commands/generate/template/base/go.tmpl.mod
+++ b/v2/cmd/wails/internal/commands/generate/template/base/go.tmpl.mod
@@ -12,7 +12,6 @@ module changeme
github.com/labstack/echo/v4 v4.7.2 // indirect
github.com/labstack/gommon v0.3.1 // indirect
github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
- github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
github.com/leaanthony/gosod v1.0.3 // indirect
github.com/leaanthony/slicer v1.5.0 // indirect
github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
diff --git a/v2/cmd/wails/internal/commands/generate/template/base/main.tmpl.go b/v2/cmd/wails/internal/commands/generate/template/base/main.tmpl.go
index c7740ebd0..9c15b8740 100644
--- a/v2/cmd/wails/internal/commands/generate/template/base/main.tmpl.go
+++ b/v2/cmd/wails/internal/commands/generate/template/base/main.tmpl.go
@@ -35,7 +35,7 @@ func main() {
Frameless: false,
StartHidden: false,
HideWindowOnClose: false,
- RGBA: &options.RGBA{R: 255, G: 255, B: 255, A: 255},
+ BackgroundColour: &options.RGBA{R: 255, G: 255, B: 255, A: 255},
Assets: assets,
Menu: nil,
Logger: nil,
diff --git a/v2/cmd/wails/internal/commands/initialise/initialise.go b/v2/cmd/wails/internal/commands/initialise/initialise.go
index 54205e1d6..13a6483bc 100644
--- a/v2/cmd/wails/internal/commands/initialise/initialise.go
+++ b/v2/cmd/wails/internal/commands/initialise/initialise.go
@@ -216,6 +216,16 @@ func initGit(options *templates.Options) error {
return errors.Wrap(err, "Unable to initialise git repository:")
}
+ ignore := []string{
+ "build/bin",
+ "frontend/dist",
+ "frontend/node_modules",
+ }
+ err = os.WriteFile(filepath.Join(options.TargetDir, ".gitignore"), []byte(strings.Join(ignore, "\n")), 0644)
+ if err != nil {
+ return errors.Wrap(err, "Unable to create gitignore")
+ }
+
return nil
}
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/base/main.tmpl.go b/v2/cmd/wails/internal/commands/initialise/templates/base/main.tmpl.go
index c60affe67..feeeaa186 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/base/main.tmpl.go
+++ b/v2/cmd/wails/internal/commands/initialise/templates/base/main.tmpl.go
@@ -16,11 +16,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
- OnStartup: app.startup,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ Assets: assets,
+ BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
+ OnStartup: app.startup,
Bind: []interface{}{
app,
},
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.d.ts b/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.d.ts
index bcacbec00..8d816307f 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.d.ts
@@ -167,9 +167,9 @@ export function WindowMinimise(): void;
// Restores the window to the dimensions and position prior to minimising.
export function WindowUnminimise(): void;
-// [WindowSetRGBA](https://wails.io/docs/reference/runtime/window#windowsetrgba)
+// [WindowSetBackgroundColour](https://wails.io/docs/reference/runtime/window#windowsetbackgroundcolour)
// Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels.
-export function WindowSetRGBA(R: number, G: number, B: number, A: number): void;
+export function WindowSetBackgroundColour(R: number, G: number, B: number, A: number): void;
// [BrowserOpenURL](https://wails.io/docs/reference/runtime/browser#browseropenurl)
// Opens the given URL in the system browser.
@@ -177,7 +177,7 @@ export function BrowserOpenURL(url: string): void;
// [Environment](https://wails.io/docs/reference/runtime/intro#environment)
// Returns information about the environment
-export function Environment(): EnvironmentInfo;
+export function Environment(): Promise;
// [Quit](https://wails.io/docs/reference/runtime/intro#quit)
// Quits the application.
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.js b/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.js
index 8f47e62f1..73f607ba7 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.js
+++ b/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.js
@@ -41,7 +41,7 @@ export function EventsOnMultiple(eventName, callback, maxCallbacks) {
}
export function EventsOn(eventName, callback) {
- OnMultiple(eventName, callback, -1);
+ EventsOnMultiple(eventName, callback, -1);
}
export function EventsOff(eventName) {
@@ -49,7 +49,7 @@ export function EventsOff(eventName) {
}
export function EventsOnce(eventName, callback) {
- OnMultiple(eventName, callback, 1);
+ EventsOnMultiple(eventName, callback, 1);
}
export function EventsEmit(eventName) {
@@ -145,8 +145,8 @@ export function WindowUnminimise() {
window.runtime.WindowUnminimise();
}
-export function WindowSetRGBA(RGBA) {
- window.runtime.WindowSetRGBA(RGBA);
+export function WindowSetBackgroundColour(R, G, B, A) {
+ window.runtime.WindowSetBackgroundColour(R, G, B, A);
}
export function BrowserOpenURL(url) {
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/lit-ts/frontend/src/my-element.ts b/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/lit-ts/frontend/src/my-element.ts
index fc5ebbbed..1b313b759 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/lit-ts/frontend/src/my-element.ts
+++ b/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/lit-ts/frontend/src/my-element.ts
@@ -68,32 +68,31 @@ export class MyElement extends LitElement {
}
`
-}
-@property()
-resultText = "Please enter your name below 👇"
+ @property()
+ resultText = "Please enter your name below 👇"
-greet()
-{
- let thisName = this.shadowRoot.getElementById('name').value
- Greet(thisName).then(result => {
- this.resultText = result
- });
-}
+ greet() {
+ let thisName = (this.shadowRoot.getElementById('name') as HTMLInputElement)?.value;
+ if (thisName) {
+ Greet(thisName).then(result => {
+ this.resultText = result
+ });
+ }
+ }
-render()
-{
- return html`
-
-
-
${this.resultText}
-
-
-
-
-
- `
-}
+ render() {
+ return html`
+
+
+
${this.resultText}
+
+
+
+
+
+ `
+ }
}
declare global {
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/preact-ts/frontend/src/app.tsx b/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/preact-ts/frontend/src/app.tsx
index bffcb461c..05d7c32d0 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/preact-ts/frontend/src/app.tsx
+++ b/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/preact-ts/frontend/src/app.tsx
@@ -19,7 +19,7 @@ export function App(props: any) {
{resultText}
-
+
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/preact/frontend/src/app.jsx b/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/preact/frontend/src/app.jsx
index a50cfd089..1ada97ac4 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/preact/frontend/src/app.jsx
+++ b/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/preact/frontend/src/app.jsx
@@ -19,7 +19,7 @@ export function App(props) {
{resultText}
-
+
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/preact/frontend/src/main.jsx b/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/preact/frontend/src/main.jsx
index 41787dabc..5a7bfa9ea 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/preact/frontend/src/main.jsx
+++ b/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/preact/frontend/src/main.jsx
@@ -1,5 +1,14 @@
-import {render} from 'preact';
-import {App} from './app';
-import './style.css';
+import React from 'react'
+import { createRoot } from 'react-dom/client'
+import './style.css'
+import App from './App'
-render(, document.getElementById('app'));
+const container = document.getElementById('root')
+
+const root = createRoot(container)
+
+root.render(
+
+
+
+)
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/react-ts/frontend/src/App.tsx b/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/react-ts/frontend/src/App.tsx
index 7895c66cf..a6e56f9f8 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/react-ts/frontend/src/App.tsx
+++ b/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/react-ts/frontend/src/App.tsx
@@ -18,7 +18,7 @@ function App() {
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/react/frontend/src/main.jsx b/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/react/frontend/src/main.jsx
index a6c27f6a8..5a7bfa9ea 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/react/frontend/src/main.jsx
+++ b/v2/cmd/wails/internal/commands/initialise/templates/generate/assets/react/frontend/src/main.jsx
@@ -1,11 +1,14 @@
import React from 'react'
-import ReactDOM from 'react-dom'
+import { createRoot } from 'react-dom/client'
import './style.css'
import App from './App'
-ReactDOM.render(
-
-
- ,
- document.getElementById('root')
+const container = document.getElementById('root')
+
+const root = createRoot(container)
+
+root.render(
+
+
+
)
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/generate/generate.go b/v2/cmd/wails/internal/commands/initialise/templates/generate/generate.go
index 329cad6b4..a488f0fbf 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/generate/generate.go
+++ b/v2/cmd/wails/internal/commands/initialise/templates/generate/generate.go
@@ -7,7 +7,7 @@ import (
"github.com/leaanthony/debme"
"github.com/leaanthony/gosod"
- "github.com/wailsapp/wails/v2/cmd/wails/internal/commands/initialise/templates/generate/s"
+ "github.com/wailsapp/wails/v2/internal/s"
)
//go:embed assets/common/*
@@ -163,6 +163,13 @@ func main() {
for _, t := range templates {
createTemplate(t)
}
+
+ // copy plain template
+ s.ECHO("Copying plain template")
+ s.RMDIR("../templates/plain")
+ s.COPYDIR("plain", "../templates/plain")
+
+ s.ECHO(`Until an auto fix is done, add "@babel/types": "^7.17.10" to vite-ts/frontend/package.json`)
}
func rebuildRuntime() {
@@ -220,16 +227,5 @@ func createTemplate(template *template) {
err = g.Extract(".", nil)
checkError(err)
- //s.ECHO("HERE")
- //s.EXEC("wails init -n " + shortName + "test -t ./" + shortName)
- //s.ECHO("HERE")
- //s.CD(shortName + "test")
- //s.ECHO("HERE")
- //s.REPLACEALL("go.mod", s.Sub{"// replace": "replace"})
- //s.ECHO("HERE")
- //s.EXEC("wails build -debug")
- //s.ECHO("HERE")
s.CD(cwd)
-
- s.ECHO(`Until an auto fix is done, add "@babel/types": "^7.17.10" to vite-ts/frontend/package.json`)
}
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/.gitignore b/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/.gitignore
new file mode 100644
index 000000000..b92a6f8bf
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/.gitignore
@@ -0,0 +1,12 @@
+# Wails bin directory
+build/bin
+# Wails Windows NSIS support files
+build/windows/installer/wails_tools.nsh
+build/windows/installer/tmp/
+
+# IDEs
+.idea
+.vscode
+
+# The black hole that is...
+node_modules
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/README.md b/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/README.md
new file mode 100644
index 000000000..9fcd85bdd
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/README.md
@@ -0,0 +1,18 @@
+# README
+
+## About
+
+This template uses plain JS / HTML and CSS.
+
+You can configure the project by editing `wails.json`. More information about the project settings can be found
+here: https://wails.io/docs/reference/project-config
+
+## Live Development
+
+To run in live development mode, run `wails dev` in the project directory. The frontend dev server will run
+on http://localhost:34115. Open this in your browser to connect to your application.
+
+## Building
+
+For a production build, use `wails build`.
+
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/app.go b/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/app.go
new file mode 100644
index 000000000..224be7156
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/app.go
@@ -0,0 +1,44 @@
+package main
+
+import (
+ "context"
+ "fmt"
+)
+
+// App struct
+type App struct {
+ ctx context.Context
+}
+
+// NewApp creates a new App application struct
+func NewApp() *App {
+ return &App{}
+}
+
+// startup is called at application startup
+func (a *App) startup(ctx context.Context) {
+ // Perform your setup here
+ a.ctx = ctx
+}
+
+// domReady is called after front-end resources have been loaded
+func (a App) domReady(ctx context.Context) {
+ // Add your action here
+}
+
+// beforeClose is called when the application is about to quit,
+// either by clicking the window close button or calling runtime.Quit.
+// Returning true will cause the application to continue, false will continue shutdown as normal.
+func (a *App) beforeClose(ctx context.Context) (prevent bool) {
+ return false
+}
+
+// shutdown is called at application termination
+func (a *App) shutdown(ctx context.Context) {
+ // Perform your teardown here
+}
+
+// Greet returns a greeting for the given name
+func (a *App) Greet(name string) string {
+ return fmt.Sprintf("Hello %s, It's show time!", name)
+}
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/frontend/src/assets/fonts/OFL.txt b/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/frontend/src/assets/fonts/OFL.txt
new file mode 100644
index 000000000..9cac04ce8
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/frontend/src/assets/fonts/OFL.txt
@@ -0,0 +1,93 @@
+Copyright 2016 The Nunito Project Authors (contact@sansoxygen.com),
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2 b/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2
new file mode 100644
index 000000000..2f9cc5964
Binary files /dev/null and b/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2 differ
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/frontend/src/assets/images/logo-universal.png b/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/frontend/src/assets/images/logo-universal.png
new file mode 100644
index 000000000..be568b847
Binary files /dev/null and b/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/frontend/src/assets/images/logo-universal.png differ
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/frontend/src/index.tmpl.html b/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/frontend/src/index.tmpl.html
new file mode 100644
index 000000000..e904c489c
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/frontend/src/index.tmpl.html
@@ -0,0 +1,21 @@
+
+
+
+
+
+ {{.ProjectName}}
+
+
+
+
+
+
+ `
+ }
}
declare global {
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.d.ts b/v2/cmd/wails/internal/commands/initialise/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.d.ts
index bcacbec00..8d816307f 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.d.ts
@@ -167,9 +167,9 @@ export function WindowMinimise(): void;
// Restores the window to the dimensions and position prior to minimising.
export function WindowUnminimise(): void;
-// [WindowSetRGBA](https://wails.io/docs/reference/runtime/window#windowsetrgba)
+// [WindowSetBackgroundColour](https://wails.io/docs/reference/runtime/window#windowsetbackgroundcolour)
// Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels.
-export function WindowSetRGBA(R: number, G: number, B: number, A: number): void;
+export function WindowSetBackgroundColour(R: number, G: number, B: number, A: number): void;
// [BrowserOpenURL](https://wails.io/docs/reference/runtime/browser#browseropenurl)
// Opens the given URL in the system browser.
@@ -177,7 +177,7 @@ export function BrowserOpenURL(url: string): void;
// [Environment](https://wails.io/docs/reference/runtime/intro#environment)
// Returns information about the environment
-export function Environment(): EnvironmentInfo;
+export function Environment(): Promise;
// [Quit](https://wails.io/docs/reference/runtime/intro#quit)
// Quits the application.
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.js b/v2/cmd/wails/internal/commands/initialise/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.js
index 8f47e62f1..73f607ba7 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.js
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.js
@@ -41,7 +41,7 @@ export function EventsOnMultiple(eventName, callback, maxCallbacks) {
}
export function EventsOn(eventName, callback) {
- OnMultiple(eventName, callback, -1);
+ EventsOnMultiple(eventName, callback, -1);
}
export function EventsOff(eventName) {
@@ -49,7 +49,7 @@ export function EventsOff(eventName) {
}
export function EventsOnce(eventName, callback) {
- OnMultiple(eventName, callback, 1);
+ EventsOnMultiple(eventName, callback, 1);
}
export function EventsEmit(eventName) {
@@ -145,8 +145,8 @@ export function WindowUnminimise() {
window.runtime.WindowUnminimise();
}
-export function WindowSetRGBA(RGBA) {
- window.runtime.WindowSetRGBA(RGBA);
+export function WindowSetBackgroundColour(R, G, B, A) {
+ window.runtime.WindowSetBackgroundColour(R, G, B, A);
}
export function BrowserOpenURL(url) {
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/lit-ts/main.tmpl.go b/v2/cmd/wails/internal/commands/initialise/templates/templates/lit-ts/main.tmpl.go
index c60affe67..feeeaa186 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/lit-ts/main.tmpl.go
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/lit-ts/main.tmpl.go
@@ -16,11 +16,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
- OnStartup: app.startup,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ Assets: assets,
+ BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
+ OnStartup: app.startup,
Bind: []interface{}{
app,
},
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/lit/frontend/package.json b/v2/cmd/wails/internal/commands/initialise/templates/templates/lit/frontend/package.json
index 9ddc2e9f4..cb172cb12 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/lit/frontend/package.json
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/lit/frontend/package.json
@@ -17,6 +17,6 @@
"lit": "^2.0.2"
},
"devDependencies": {
- "vite": "^2.9.5"
+ "vite": "^2.9.9"
}
}
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/lit/frontend/wailsjs/runtime/runtime.d.ts b/v2/cmd/wails/internal/commands/initialise/templates/templates/lit/frontend/wailsjs/runtime/runtime.d.ts
index bcacbec00..8d816307f 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/lit/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/lit/frontend/wailsjs/runtime/runtime.d.ts
@@ -167,9 +167,9 @@ export function WindowMinimise(): void;
// Restores the window to the dimensions and position prior to minimising.
export function WindowUnminimise(): void;
-// [WindowSetRGBA](https://wails.io/docs/reference/runtime/window#windowsetrgba)
+// [WindowSetBackgroundColour](https://wails.io/docs/reference/runtime/window#windowsetbackgroundcolour)
// Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels.
-export function WindowSetRGBA(R: number, G: number, B: number, A: number): void;
+export function WindowSetBackgroundColour(R: number, G: number, B: number, A: number): void;
// [BrowserOpenURL](https://wails.io/docs/reference/runtime/browser#browseropenurl)
// Opens the given URL in the system browser.
@@ -177,7 +177,7 @@ export function BrowserOpenURL(url: string): void;
// [Environment](https://wails.io/docs/reference/runtime/intro#environment)
// Returns information about the environment
-export function Environment(): EnvironmentInfo;
+export function Environment(): Promise;
// [Quit](https://wails.io/docs/reference/runtime/intro#quit)
// Quits the application.
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/lit/frontend/wailsjs/runtime/runtime.js b/v2/cmd/wails/internal/commands/initialise/templates/templates/lit/frontend/wailsjs/runtime/runtime.js
index 8f47e62f1..73f607ba7 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/lit/frontend/wailsjs/runtime/runtime.js
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/lit/frontend/wailsjs/runtime/runtime.js
@@ -41,7 +41,7 @@ export function EventsOnMultiple(eventName, callback, maxCallbacks) {
}
export function EventsOn(eventName, callback) {
- OnMultiple(eventName, callback, -1);
+ EventsOnMultiple(eventName, callback, -1);
}
export function EventsOff(eventName) {
@@ -49,7 +49,7 @@ export function EventsOff(eventName) {
}
export function EventsOnce(eventName, callback) {
- OnMultiple(eventName, callback, 1);
+ EventsOnMultiple(eventName, callback, 1);
}
export function EventsEmit(eventName) {
@@ -145,8 +145,8 @@ export function WindowUnminimise() {
window.runtime.WindowUnminimise();
}
-export function WindowSetRGBA(RGBA) {
- window.runtime.WindowSetRGBA(RGBA);
+export function WindowSetBackgroundColour(R, G, B, A) {
+ window.runtime.WindowSetBackgroundColour(R, G, B, A);
}
export function BrowserOpenURL(url) {
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/lit/main.tmpl.go b/v2/cmd/wails/internal/commands/initialise/templates/templates/lit/main.tmpl.go
index c60affe67..feeeaa186 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/lit/main.tmpl.go
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/lit/main.tmpl.go
@@ -16,11 +16,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
- OnStartup: app.startup,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ Assets: assets,
+ BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
+ OnStartup: app.startup,
Bind: []interface{}{
app,
},
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/plain/.gitignore b/v2/cmd/wails/internal/commands/initialise/templates/templates/plain/.gitignore
new file mode 100644
index 000000000..b92a6f8bf
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/plain/.gitignore
@@ -0,0 +1,12 @@
+# Wails bin directory
+build/bin
+# Wails Windows NSIS support files
+build/windows/installer/wails_tools.nsh
+build/windows/installer/tmp/
+
+# IDEs
+.idea
+.vscode
+
+# The black hole that is...
+node_modules
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/plain/README.md b/v2/cmd/wails/internal/commands/initialise/templates/templates/plain/README.md
new file mode 100644
index 000000000..9fcd85bdd
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/plain/README.md
@@ -0,0 +1,18 @@
+# README
+
+## About
+
+This template uses plain JS / HTML and CSS.
+
+You can configure the project by editing `wails.json`. More information about the project settings can be found
+here: https://wails.io/docs/reference/project-config
+
+## Live Development
+
+To run in live development mode, run `wails dev` in the project directory. The frontend dev server will run
+on http://localhost:34115. Open this in your browser to connect to your application.
+
+## Building
+
+For a production build, use `wails build`.
+
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/plain/app.go b/v2/cmd/wails/internal/commands/initialise/templates/templates/plain/app.go
new file mode 100644
index 000000000..224be7156
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/plain/app.go
@@ -0,0 +1,44 @@
+package main
+
+import (
+ "context"
+ "fmt"
+)
+
+// App struct
+type App struct {
+ ctx context.Context
+}
+
+// NewApp creates a new App application struct
+func NewApp() *App {
+ return &App{}
+}
+
+// startup is called at application startup
+func (a *App) startup(ctx context.Context) {
+ // Perform your setup here
+ a.ctx = ctx
+}
+
+// domReady is called after front-end resources have been loaded
+func (a App) domReady(ctx context.Context) {
+ // Add your action here
+}
+
+// beforeClose is called when the application is about to quit,
+// either by clicking the window close button or calling runtime.Quit.
+// Returning true will cause the application to continue, false will continue shutdown as normal.
+func (a *App) beforeClose(ctx context.Context) (prevent bool) {
+ return false
+}
+
+// shutdown is called at application termination
+func (a *App) shutdown(ctx context.Context) {
+ // Perform your teardown here
+}
+
+// Greet returns a greeting for the given name
+func (a *App) Greet(name string) string {
+ return fmt.Sprintf("Hello %s, It's show time!", name)
+}
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/plain/frontend/src/assets/fonts/OFL.txt b/v2/cmd/wails/internal/commands/initialise/templates/templates/plain/frontend/src/assets/fonts/OFL.txt
new file mode 100644
index 000000000..9cac04ce8
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/plain/frontend/src/assets/fonts/OFL.txt
@@ -0,0 +1,93 @@
+Copyright 2016 The Nunito Project Authors (contact@sansoxygen.com),
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/plain/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2 b/v2/cmd/wails/internal/commands/initialise/templates/templates/plain/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2
new file mode 100644
index 000000000..2f9cc5964
Binary files /dev/null and b/v2/cmd/wails/internal/commands/initialise/templates/templates/plain/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2 differ
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/plain/frontend/src/assets/images/logo-universal.png b/v2/cmd/wails/internal/commands/initialise/templates/templates/plain/frontend/src/assets/images/logo-universal.png
new file mode 100644
index 000000000..be568b847
Binary files /dev/null and b/v2/cmd/wails/internal/commands/initialise/templates/templates/plain/frontend/src/assets/images/logo-universal.png differ
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/plain/frontend/src/index.tmpl.html b/v2/cmd/wails/internal/commands/initialise/templates/templates/plain/frontend/src/index.tmpl.html
new file mode 100644
index 000000000..a8a434a37
--- /dev/null
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/plain/frontend/src/index.tmpl.html
@@ -0,0 +1,21 @@
+
+
+
+
+
+ {{.ProjectName}}
+
+
+
+
+
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact-ts/frontend/src/preact.d.ts b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact-ts/frontend/src/preact.d.ts
index ac79d62a4..e69de29bb 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact-ts/frontend/src/preact.d.ts
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact-ts/frontend/src/preact.d.ts
@@ -1 +0,0 @@
-import JSX = preact.JSX
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact-ts/frontend/vite.config.ts b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact-ts/frontend/vite.config.ts
index e3bdaffe8..25845ba4b 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact-ts/frontend/vite.config.ts
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact-ts/frontend/vite.config.ts
@@ -1,4 +1,4 @@
-import { defineConfig } from 'vite'
+import {defineConfig} from 'vite'
import preact from '@preact/preset-vite'
// https://vitejs.dev/config/
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.d.ts b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.d.ts
index bcacbec00..8d816307f 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.d.ts
@@ -167,9 +167,9 @@ export function WindowMinimise(): void;
// Restores the window to the dimensions and position prior to minimising.
export function WindowUnminimise(): void;
-// [WindowSetRGBA](https://wails.io/docs/reference/runtime/window#windowsetrgba)
+// [WindowSetBackgroundColour](https://wails.io/docs/reference/runtime/window#windowsetbackgroundcolour)
// Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels.
-export function WindowSetRGBA(R: number, G: number, B: number, A: number): void;
+export function WindowSetBackgroundColour(R: number, G: number, B: number, A: number): void;
// [BrowserOpenURL](https://wails.io/docs/reference/runtime/browser#browseropenurl)
// Opens the given URL in the system browser.
@@ -177,7 +177,7 @@ export function BrowserOpenURL(url: string): void;
// [Environment](https://wails.io/docs/reference/runtime/intro#environment)
// Returns information about the environment
-export function Environment(): EnvironmentInfo;
+export function Environment(): Promise;
// [Quit](https://wails.io/docs/reference/runtime/intro#quit)
// Quits the application.
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.js b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.js
index 8f47e62f1..73f607ba7 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.js
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.js
@@ -41,7 +41,7 @@ export function EventsOnMultiple(eventName, callback, maxCallbacks) {
}
export function EventsOn(eventName, callback) {
- OnMultiple(eventName, callback, -1);
+ EventsOnMultiple(eventName, callback, -1);
}
export function EventsOff(eventName) {
@@ -49,7 +49,7 @@ export function EventsOff(eventName) {
}
export function EventsOnce(eventName, callback) {
- OnMultiple(eventName, callback, 1);
+ EventsOnMultiple(eventName, callback, 1);
}
export function EventsEmit(eventName) {
@@ -145,8 +145,8 @@ export function WindowUnminimise() {
window.runtime.WindowUnminimise();
}
-export function WindowSetRGBA(RGBA) {
- window.runtime.WindowSetRGBA(RGBA);
+export function WindowSetBackgroundColour(R, G, B, A) {
+ window.runtime.WindowSetBackgroundColour(R, G, B, A);
}
export function BrowserOpenURL(url) {
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact-ts/main.tmpl.go b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact-ts/main.tmpl.go
index c60affe67..feeeaa186 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact-ts/main.tmpl.go
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact-ts/main.tmpl.go
@@ -16,11 +16,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
- OnStartup: app.startup,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ Assets: assets,
+ BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
+ OnStartup: app.startup,
Bind: []interface{}{
app,
},
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/package.json b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/package.json
index 9c4bd75c5..0908feee0 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/package.json
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/package.json
@@ -12,6 +12,6 @@
},
"devDependencies": {
"@preact/preset-vite": "^2.1.5",
- "vite": "^2.9.5"
+ "vite": "^2.9.9"
}
}
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/src/app.jsx b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/src/app.jsx
index a50cfd089..1ada97ac4 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/src/app.jsx
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/src/app.jsx
@@ -19,7 +19,7 @@ export function App(props) {
{resultText}
-
+
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/src/main.jsx b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/src/main.jsx
index 41787dabc..e50e105db 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/src/main.jsx
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/src/main.jsx
@@ -1,5 +1,14 @@
-import {render} from 'preact';
-import {App} from './app';
-import './style.css';
+import React from 'react'
+import {createRoot} from 'react-dom/client'
+import './style.css'
+import App from './App'
-render(, document.getElementById('app'));
+const container = document.getElementById('root')
+
+const root = createRoot(container)
+
+root.render(
+
+
+
+)
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/vite.config.js b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/vite.config.js
index e3bdaffe8..25845ba4b 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/vite.config.js
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/vite.config.js
@@ -1,4 +1,4 @@
-import { defineConfig } from 'vite'
+import {defineConfig} from 'vite'
import preact from '@preact/preset-vite'
// https://vitejs.dev/config/
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/wailsjs/runtime/runtime.d.ts b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/wailsjs/runtime/runtime.d.ts
index bcacbec00..8d816307f 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/wailsjs/runtime/runtime.d.ts
@@ -167,9 +167,9 @@ export function WindowMinimise(): void;
// Restores the window to the dimensions and position prior to minimising.
export function WindowUnminimise(): void;
-// [WindowSetRGBA](https://wails.io/docs/reference/runtime/window#windowsetrgba)
+// [WindowSetBackgroundColour](https://wails.io/docs/reference/runtime/window#windowsetbackgroundcolour)
// Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels.
-export function WindowSetRGBA(R: number, G: number, B: number, A: number): void;
+export function WindowSetBackgroundColour(R: number, G: number, B: number, A: number): void;
// [BrowserOpenURL](https://wails.io/docs/reference/runtime/browser#browseropenurl)
// Opens the given URL in the system browser.
@@ -177,7 +177,7 @@ export function BrowserOpenURL(url: string): void;
// [Environment](https://wails.io/docs/reference/runtime/intro#environment)
// Returns information about the environment
-export function Environment(): EnvironmentInfo;
+export function Environment(): Promise;
// [Quit](https://wails.io/docs/reference/runtime/intro#quit)
// Quits the application.
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/wailsjs/runtime/runtime.js b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/wailsjs/runtime/runtime.js
index 8f47e62f1..73f607ba7 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/wailsjs/runtime/runtime.js
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/frontend/wailsjs/runtime/runtime.js
@@ -41,7 +41,7 @@ export function EventsOnMultiple(eventName, callback, maxCallbacks) {
}
export function EventsOn(eventName, callback) {
- OnMultiple(eventName, callback, -1);
+ EventsOnMultiple(eventName, callback, -1);
}
export function EventsOff(eventName) {
@@ -49,7 +49,7 @@ export function EventsOff(eventName) {
}
export function EventsOnce(eventName, callback) {
- OnMultiple(eventName, callback, 1);
+ EventsOnMultiple(eventName, callback, 1);
}
export function EventsEmit(eventName) {
@@ -145,8 +145,8 @@ export function WindowUnminimise() {
window.runtime.WindowUnminimise();
}
-export function WindowSetRGBA(RGBA) {
- window.runtime.WindowSetRGBA(RGBA);
+export function WindowSetBackgroundColour(R, G, B, A) {
+ window.runtime.WindowSetBackgroundColour(R, G, B, A);
}
export function BrowserOpenURL(url) {
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/main.tmpl.go b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/main.tmpl.go
index c60affe67..feeeaa186 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/main.tmpl.go
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/preact/main.tmpl.go
@@ -16,11 +16,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
- OnStartup: app.startup,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ Assets: assets,
+ BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
+ OnStartup: app.startup,
Bind: []interface{}{
app,
},
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/package.json b/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/package.json
index 8be3b8099..d465e2c1e 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/package.json
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/package.json
@@ -16,6 +16,6 @@
"@types/react-dom": "^18.0.0",
"@vitejs/plugin-react": "^1.3.0",
"typescript": "^4.6.3",
- "vite": "^2.9.5"
+ "vite": "^2.9.9"
}
}
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/src/App.tsx b/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/src/App.tsx
index 7895c66cf..a6e56f9f8 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/src/App.tsx
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/src/App.tsx
@@ -18,7 +18,7 @@ function App() {
{resultText}
-
+
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/src/main.tsx b/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/src/main.tsx
index a6c27f6a8..361c8d660 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/src/main.tsx
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/src/main.tsx
@@ -1,11 +1,14 @@
import React from 'react'
-import ReactDOM from 'react-dom'
+import { createRoot } from 'react-dom/client'
import './style.css'
import App from './App'
-ReactDOM.render(
-
-
- ,
- document.getElementById('root')
+const container = document.getElementById('root')
+
+const root = createRoot(container!)
+
+root.render(
+
+
+
)
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/vite.config.ts b/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/vite.config.ts
index b1b5f91e5..49550655a 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/vite.config.ts
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/vite.config.ts
@@ -1,4 +1,4 @@
-import { defineConfig } from 'vite'
+import {defineConfig} from 'vite'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.d.ts b/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.d.ts
index bcacbec00..8d816307f 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.d.ts
@@ -167,9 +167,9 @@ export function WindowMinimise(): void;
// Restores the window to the dimensions and position prior to minimising.
export function WindowUnminimise(): void;
-// [WindowSetRGBA](https://wails.io/docs/reference/runtime/window#windowsetrgba)
+// [WindowSetBackgroundColour](https://wails.io/docs/reference/runtime/window#windowsetbackgroundcolour)
// Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels.
-export function WindowSetRGBA(R: number, G: number, B: number, A: number): void;
+export function WindowSetBackgroundColour(R: number, G: number, B: number, A: number): void;
// [BrowserOpenURL](https://wails.io/docs/reference/runtime/browser#browseropenurl)
// Opens the given URL in the system browser.
@@ -177,7 +177,7 @@ export function BrowserOpenURL(url: string): void;
// [Environment](https://wails.io/docs/reference/runtime/intro#environment)
// Returns information about the environment
-export function Environment(): EnvironmentInfo;
+export function Environment(): Promise;
// [Quit](https://wails.io/docs/reference/runtime/intro#quit)
// Quits the application.
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.js b/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.js
index 8f47e62f1..73f607ba7 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.js
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.js
@@ -41,7 +41,7 @@ export function EventsOnMultiple(eventName, callback, maxCallbacks) {
}
export function EventsOn(eventName, callback) {
- OnMultiple(eventName, callback, -1);
+ EventsOnMultiple(eventName, callback, -1);
}
export function EventsOff(eventName) {
@@ -49,7 +49,7 @@ export function EventsOff(eventName) {
}
export function EventsOnce(eventName, callback) {
- OnMultiple(eventName, callback, 1);
+ EventsOnMultiple(eventName, callback, 1);
}
export function EventsEmit(eventName) {
@@ -145,8 +145,8 @@ export function WindowUnminimise() {
window.runtime.WindowUnminimise();
}
-export function WindowSetRGBA(RGBA) {
- window.runtime.WindowSetRGBA(RGBA);
+export function WindowSetBackgroundColour(R, G, B, A) {
+ window.runtime.WindowSetBackgroundColour(R, G, B, A);
}
export function BrowserOpenURL(url) {
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/main.tmpl.go b/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/main.tmpl.go
index c60affe67..feeeaa186 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/main.tmpl.go
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/react-ts/main.tmpl.go
@@ -16,11 +16,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
- OnStartup: app.startup,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ Assets: assets,
+ BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
+ OnStartup: app.startup,
Bind: []interface{}{
app,
},
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/package.json b/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/package.json
index 6ccd4766f..3c1470704 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/package.json
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/package.json
@@ -15,6 +15,6 @@
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"@vitejs/plugin-react": "^1.3.0",
- "vite": "^2.9.5"
+ "vite": "^2.9.9"
}
}
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/src/App.jsx b/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/src/App.jsx
index 071423476..fd762291f 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/src/App.jsx
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/src/App.jsx
@@ -18,7 +18,7 @@ function App() {
{resultText}
-
+
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/src/main.jsx b/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/src/main.jsx
index a6c27f6a8..e50e105db 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/src/main.jsx
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/src/main.jsx
@@ -1,11 +1,14 @@
import React from 'react'
-import ReactDOM from 'react-dom'
+import {createRoot} from 'react-dom/client'
import './style.css'
import App from './App'
-ReactDOM.render(
+const container = document.getElementById('root')
+
+const root = createRoot(container)
+
+root.render(
- ,
- document.getElementById('root')
+
)
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/vite.config.js b/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/vite.config.js
index b1b5f91e5..49550655a 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/vite.config.js
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/vite.config.js
@@ -1,4 +1,4 @@
-import { defineConfig } from 'vite'
+import {defineConfig} from 'vite'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/wailsjs/runtime/runtime.d.ts b/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/wailsjs/runtime/runtime.d.ts
index bcacbec00..8d816307f 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/wailsjs/runtime/runtime.d.ts
@@ -167,9 +167,9 @@ export function WindowMinimise(): void;
// Restores the window to the dimensions and position prior to minimising.
export function WindowUnminimise(): void;
-// [WindowSetRGBA](https://wails.io/docs/reference/runtime/window#windowsetrgba)
+// [WindowSetBackgroundColour](https://wails.io/docs/reference/runtime/window#windowsetbackgroundcolour)
// Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels.
-export function WindowSetRGBA(R: number, G: number, B: number, A: number): void;
+export function WindowSetBackgroundColour(R: number, G: number, B: number, A: number): void;
// [BrowserOpenURL](https://wails.io/docs/reference/runtime/browser#browseropenurl)
// Opens the given URL in the system browser.
@@ -177,7 +177,7 @@ export function BrowserOpenURL(url: string): void;
// [Environment](https://wails.io/docs/reference/runtime/intro#environment)
// Returns information about the environment
-export function Environment(): EnvironmentInfo;
+export function Environment(): Promise;
// [Quit](https://wails.io/docs/reference/runtime/intro#quit)
// Quits the application.
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/wailsjs/runtime/runtime.js b/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/wailsjs/runtime/runtime.js
index 8f47e62f1..73f607ba7 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/wailsjs/runtime/runtime.js
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/react/frontend/wailsjs/runtime/runtime.js
@@ -41,7 +41,7 @@ export function EventsOnMultiple(eventName, callback, maxCallbacks) {
}
export function EventsOn(eventName, callback) {
- OnMultiple(eventName, callback, -1);
+ EventsOnMultiple(eventName, callback, -1);
}
export function EventsOff(eventName) {
@@ -49,7 +49,7 @@ export function EventsOff(eventName) {
}
export function EventsOnce(eventName, callback) {
- OnMultiple(eventName, callback, 1);
+ EventsOnMultiple(eventName, callback, 1);
}
export function EventsEmit(eventName) {
@@ -145,8 +145,8 @@ export function WindowUnminimise() {
window.runtime.WindowUnminimise();
}
-export function WindowSetRGBA(RGBA) {
- window.runtime.WindowSetRGBA(RGBA);
+export function WindowSetBackgroundColour(R, G, B, A) {
+ window.runtime.WindowSetBackgroundColour(R, G, B, A);
}
export function BrowserOpenURL(url) {
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/react/main.tmpl.go b/v2/cmd/wails/internal/commands/initialise/templates/templates/react/main.tmpl.go
index c60affe67..feeeaa186 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/react/main.tmpl.go
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/react/main.tmpl.go
@@ -16,11 +16,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
- OnStartup: app.startup,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ Assets: assets,
+ BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
+ OnStartup: app.startup,
Bind: []interface{}{
app,
},
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte-ts/frontend/package.json b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte-ts/frontend/package.json
index 7fb9aecdc..955eb00da 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte-ts/frontend/package.json
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte-ts/frontend/package.json
@@ -17,6 +17,6 @@
"svelte-preprocess": "^4.9.8",
"tslib": "^2.3.1",
"typescript": "^4.5.4",
- "vite": "^2.9.5"
+ "vite": "^2.9.9"
}
}
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte-ts/frontend/vite.config.ts b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte-ts/frontend/vite.config.ts
index 401b4d4bd..d37616f9a 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte-ts/frontend/vite.config.ts
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte-ts/frontend/vite.config.ts
@@ -1,5 +1,5 @@
-import { defineConfig } from 'vite'
-import { svelte } from '@sveltejs/vite-plugin-svelte'
+import {defineConfig} from 'vite'
+import {svelte} from '@sveltejs/vite-plugin-svelte'
// https://vitejs.dev/config/
export default defineConfig({
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.d.ts b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.d.ts
index bcacbec00..8d816307f 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.d.ts
@@ -167,9 +167,9 @@ export function WindowMinimise(): void;
// Restores the window to the dimensions and position prior to minimising.
export function WindowUnminimise(): void;
-// [WindowSetRGBA](https://wails.io/docs/reference/runtime/window#windowsetrgba)
+// [WindowSetBackgroundColour](https://wails.io/docs/reference/runtime/window#windowsetbackgroundcolour)
// Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels.
-export function WindowSetRGBA(R: number, G: number, B: number, A: number): void;
+export function WindowSetBackgroundColour(R: number, G: number, B: number, A: number): void;
// [BrowserOpenURL](https://wails.io/docs/reference/runtime/browser#browseropenurl)
// Opens the given URL in the system browser.
@@ -177,7 +177,7 @@ export function BrowserOpenURL(url: string): void;
// [Environment](https://wails.io/docs/reference/runtime/intro#environment)
// Returns information about the environment
-export function Environment(): EnvironmentInfo;
+export function Environment(): Promise;
// [Quit](https://wails.io/docs/reference/runtime/intro#quit)
// Quits the application.
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.js b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.js
index 8f47e62f1..73f607ba7 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.js
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.js
@@ -41,7 +41,7 @@ export function EventsOnMultiple(eventName, callback, maxCallbacks) {
}
export function EventsOn(eventName, callback) {
- OnMultiple(eventName, callback, -1);
+ EventsOnMultiple(eventName, callback, -1);
}
export function EventsOff(eventName) {
@@ -49,7 +49,7 @@ export function EventsOff(eventName) {
}
export function EventsOnce(eventName, callback) {
- OnMultiple(eventName, callback, 1);
+ EventsOnMultiple(eventName, callback, 1);
}
export function EventsEmit(eventName) {
@@ -145,8 +145,8 @@ export function WindowUnminimise() {
window.runtime.WindowUnminimise();
}
-export function WindowSetRGBA(RGBA) {
- window.runtime.WindowSetRGBA(RGBA);
+export function WindowSetBackgroundColour(R, G, B, A) {
+ window.runtime.WindowSetBackgroundColour(R, G, B, A);
}
export function BrowserOpenURL(url) {
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte-ts/main.tmpl.go b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte-ts/main.tmpl.go
index c60affe67..feeeaa186 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte-ts/main.tmpl.go
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte-ts/main.tmpl.go
@@ -16,11 +16,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
- OnStartup: app.startup,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ Assets: assets,
+ BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
+ OnStartup: app.startup,
Bind: []interface{}{
app,
},
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/package.json b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/package.json
index c14404abd..890133352 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/package.json
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/package.json
@@ -11,6 +11,6 @@
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.30",
"svelte": "^3.44.0",
- "vite": "^2.9.5"
+ "vite": "^2.9.9"
}
}
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/vite.config.js b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/vite.config.js
index 401b4d4bd..d37616f9a 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/vite.config.js
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/vite.config.js
@@ -1,5 +1,5 @@
-import { defineConfig } from 'vite'
-import { svelte } from '@sveltejs/vite-plugin-svelte'
+import {defineConfig} from 'vite'
+import {svelte} from '@sveltejs/vite-plugin-svelte'
// https://vitejs.dev/config/
export default defineConfig({
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/wailsjs/runtime/runtime.d.ts b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/wailsjs/runtime/runtime.d.ts
index bcacbec00..8d816307f 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/wailsjs/runtime/runtime.d.ts
@@ -167,9 +167,9 @@ export function WindowMinimise(): void;
// Restores the window to the dimensions and position prior to minimising.
export function WindowUnminimise(): void;
-// [WindowSetRGBA](https://wails.io/docs/reference/runtime/window#windowsetrgba)
+// [WindowSetBackgroundColour](https://wails.io/docs/reference/runtime/window#windowsetbackgroundcolour)
// Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels.
-export function WindowSetRGBA(R: number, G: number, B: number, A: number): void;
+export function WindowSetBackgroundColour(R: number, G: number, B: number, A: number): void;
// [BrowserOpenURL](https://wails.io/docs/reference/runtime/browser#browseropenurl)
// Opens the given URL in the system browser.
@@ -177,7 +177,7 @@ export function BrowserOpenURL(url: string): void;
// [Environment](https://wails.io/docs/reference/runtime/intro#environment)
// Returns information about the environment
-export function Environment(): EnvironmentInfo;
+export function Environment(): Promise;
// [Quit](https://wails.io/docs/reference/runtime/intro#quit)
// Quits the application.
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/wailsjs/runtime/runtime.js b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/wailsjs/runtime/runtime.js
index 8f47e62f1..73f607ba7 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/wailsjs/runtime/runtime.js
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/frontend/wailsjs/runtime/runtime.js
@@ -41,7 +41,7 @@ export function EventsOnMultiple(eventName, callback, maxCallbacks) {
}
export function EventsOn(eventName, callback) {
- OnMultiple(eventName, callback, -1);
+ EventsOnMultiple(eventName, callback, -1);
}
export function EventsOff(eventName) {
@@ -49,7 +49,7 @@ export function EventsOff(eventName) {
}
export function EventsOnce(eventName, callback) {
- OnMultiple(eventName, callback, 1);
+ EventsOnMultiple(eventName, callback, 1);
}
export function EventsEmit(eventName) {
@@ -145,8 +145,8 @@ export function WindowUnminimise() {
window.runtime.WindowUnminimise();
}
-export function WindowSetRGBA(RGBA) {
- window.runtime.WindowSetRGBA(RGBA);
+export function WindowSetBackgroundColour(R, G, B, A) {
+ window.runtime.WindowSetBackgroundColour(R, G, B, A);
}
export function BrowserOpenURL(url) {
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/main.tmpl.go b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/main.tmpl.go
index c60affe67..feeeaa186 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/main.tmpl.go
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/svelte/main.tmpl.go
@@ -16,11 +16,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
- OnStartup: app.startup,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ Assets: assets,
+ BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
+ OnStartup: app.startup,
Bind: []interface{}{
app,
},
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla-ts/frontend/package.json b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla-ts/frontend/package.json
index 7cf9f3e21..37305b4c0 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla-ts/frontend/package.json
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla-ts/frontend/package.json
@@ -9,6 +9,6 @@
},
"devDependencies": {
"typescript": "^4.5.4",
- "vite": "^2.9.5"
+ "vite": "^2.9.9"
}
}
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.d.ts b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.d.ts
index bcacbec00..8d816307f 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.d.ts
@@ -167,9 +167,9 @@ export function WindowMinimise(): void;
// Restores the window to the dimensions and position prior to minimising.
export function WindowUnminimise(): void;
-// [WindowSetRGBA](https://wails.io/docs/reference/runtime/window#windowsetrgba)
+// [WindowSetBackgroundColour](https://wails.io/docs/reference/runtime/window#windowsetbackgroundcolour)
// Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels.
-export function WindowSetRGBA(R: number, G: number, B: number, A: number): void;
+export function WindowSetBackgroundColour(R: number, G: number, B: number, A: number): void;
// [BrowserOpenURL](https://wails.io/docs/reference/runtime/browser#browseropenurl)
// Opens the given URL in the system browser.
@@ -177,7 +177,7 @@ export function BrowserOpenURL(url: string): void;
// [Environment](https://wails.io/docs/reference/runtime/intro#environment)
// Returns information about the environment
-export function Environment(): EnvironmentInfo;
+export function Environment(): Promise;
// [Quit](https://wails.io/docs/reference/runtime/intro#quit)
// Quits the application.
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.js b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.js
index 8f47e62f1..73f607ba7 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.js
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.js
@@ -41,7 +41,7 @@ export function EventsOnMultiple(eventName, callback, maxCallbacks) {
}
export function EventsOn(eventName, callback) {
- OnMultiple(eventName, callback, -1);
+ EventsOnMultiple(eventName, callback, -1);
}
export function EventsOff(eventName) {
@@ -49,7 +49,7 @@ export function EventsOff(eventName) {
}
export function EventsOnce(eventName, callback) {
- OnMultiple(eventName, callback, 1);
+ EventsOnMultiple(eventName, callback, 1);
}
export function EventsEmit(eventName) {
@@ -145,8 +145,8 @@ export function WindowUnminimise() {
window.runtime.WindowUnminimise();
}
-export function WindowSetRGBA(RGBA) {
- window.runtime.WindowSetRGBA(RGBA);
+export function WindowSetBackgroundColour(R, G, B, A) {
+ window.runtime.WindowSetBackgroundColour(R, G, B, A);
}
export function BrowserOpenURL(url) {
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla-ts/main.tmpl.go b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla-ts/main.tmpl.go
index c60affe67..feeeaa186 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla-ts/main.tmpl.go
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla-ts/main.tmpl.go
@@ -16,11 +16,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
- OnStartup: app.startup,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ Assets: assets,
+ BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
+ OnStartup: app.startup,
Bind: []interface{}{
app,
},
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/package.json b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/package.json
index b1420743b..4ac881798 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/package.json
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/package.json
@@ -8,6 +8,6 @@
"preview": "vite preview"
},
"devDependencies": {
- "vite": "^2.9.5"
+ "vite": "^2.9.9"
}
}
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.d.ts b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.d.ts
index bcacbec00..8d816307f 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.d.ts
@@ -167,9 +167,9 @@ export function WindowMinimise(): void;
// Restores the window to the dimensions and position prior to minimising.
export function WindowUnminimise(): void;
-// [WindowSetRGBA](https://wails.io/docs/reference/runtime/window#windowsetrgba)
+// [WindowSetBackgroundColour](https://wails.io/docs/reference/runtime/window#windowsetbackgroundcolour)
// Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels.
-export function WindowSetRGBA(R: number, G: number, B: number, A: number): void;
+export function WindowSetBackgroundColour(R: number, G: number, B: number, A: number): void;
// [BrowserOpenURL](https://wails.io/docs/reference/runtime/browser#browseropenurl)
// Opens the given URL in the system browser.
@@ -177,7 +177,7 @@ export function BrowserOpenURL(url: string): void;
// [Environment](https://wails.io/docs/reference/runtime/intro#environment)
// Returns information about the environment
-export function Environment(): EnvironmentInfo;
+export function Environment(): Promise;
// [Quit](https://wails.io/docs/reference/runtime/intro#quit)
// Quits the application.
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.js b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.js
index 8f47e62f1..73f607ba7 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.js
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.js
@@ -41,7 +41,7 @@ export function EventsOnMultiple(eventName, callback, maxCallbacks) {
}
export function EventsOn(eventName, callback) {
- OnMultiple(eventName, callback, -1);
+ EventsOnMultiple(eventName, callback, -1);
}
export function EventsOff(eventName) {
@@ -49,7 +49,7 @@ export function EventsOff(eventName) {
}
export function EventsOnce(eventName, callback) {
- OnMultiple(eventName, callback, 1);
+ EventsOnMultiple(eventName, callback, 1);
}
export function EventsEmit(eventName) {
@@ -145,8 +145,8 @@ export function WindowUnminimise() {
window.runtime.WindowUnminimise();
}
-export function WindowSetRGBA(RGBA) {
- window.runtime.WindowSetRGBA(RGBA);
+export function WindowSetBackgroundColour(R, G, B, A) {
+ window.runtime.WindowSetBackgroundColour(R, G, B, A);
}
export function BrowserOpenURL(url) {
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/main.tmpl.go b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/main.tmpl.go
index c60affe67..feeeaa186 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/main.tmpl.go
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vanilla/main.tmpl.go
@@ -16,11 +16,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
- OnStartup: app.startup,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ Assets: assets,
+ BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
+ OnStartup: app.startup,
Bind: []interface{}{
app,
},
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/.vscode/extensions.json b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/.vscode/extensions.json
index 3dc5b08bc..57011895d 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/.vscode/extensions.json
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/.vscode/extensions.json
@@ -1,3 +1,5 @@
{
- "recommendations": ["johnsoncodehk.volar"]
+ "recommendations": [
+ "Vue.volar"
+ ]
}
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/README.md b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/README.md
index e43251672..30b15e215 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/README.md
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/README.md
@@ -4,7 +4,7 @@ This template should help get you started developing with Vue 3 and TypeScript i
## Recommended IDE Setup
-- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar)
+- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar)
## Type Support For `.vue` Imports in TS
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/package.json b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/package.json
index 20f61c514..62c7fd6e1 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/package.json
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/package.json
@@ -11,10 +11,9 @@
"vue": "^3.2.25"
},
"devDependencies": {
- "@vitejs/plugin-vue": "^2.3.1",
+ "@vitejs/plugin-vue": "^2.3.3",
"typescript": "^4.5.4",
- "vite": "^2.9.5",
- "vue-tsc": "^0.34.7",
- "@babel/types": "^7.17.10"
+ "vite": "^2.9.9",
+ "vue-tsc": "^0.34.7"
}
}
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/src/env.d.ts b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/src/env.d.ts
index aafef9509..d0c7971d7 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/src/env.d.ts
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/src/env.d.ts
@@ -1,8 +1,8 @@
///
declare module '*.vue' {
- import type { DefineComponent } from 'vue'
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
- const component: DefineComponent<{}, {}, any>
- export default component
+ import type {DefineComponent} from 'vue'
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
+ const component: DefineComponent<{}, {}, any>
+ export default component
}
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/vite.config.ts b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/vite.config.ts
index 315212d69..a30c338ed 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/vite.config.ts
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/vite.config.ts
@@ -1,4 +1,4 @@
-import { defineConfig } from 'vite'
+import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.d.ts b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.d.ts
index bcacbec00..8d816307f 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.d.ts
@@ -167,9 +167,9 @@ export function WindowMinimise(): void;
// Restores the window to the dimensions and position prior to minimising.
export function WindowUnminimise(): void;
-// [WindowSetRGBA](https://wails.io/docs/reference/runtime/window#windowsetrgba)
+// [WindowSetBackgroundColour](https://wails.io/docs/reference/runtime/window#windowsetbackgroundcolour)
// Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels.
-export function WindowSetRGBA(R: number, G: number, B: number, A: number): void;
+export function WindowSetBackgroundColour(R: number, G: number, B: number, A: number): void;
// [BrowserOpenURL](https://wails.io/docs/reference/runtime/browser#browseropenurl)
// Opens the given URL in the system browser.
@@ -177,7 +177,7 @@ export function BrowserOpenURL(url: string): void;
// [Environment](https://wails.io/docs/reference/runtime/intro#environment)
// Returns information about the environment
-export function Environment(): EnvironmentInfo;
+export function Environment(): Promise;
// [Quit](https://wails.io/docs/reference/runtime/intro#quit)
// Quits the application.
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.js b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.js
index 8f47e62f1..73f607ba7 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.js
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.js
@@ -41,7 +41,7 @@ export function EventsOnMultiple(eventName, callback, maxCallbacks) {
}
export function EventsOn(eventName, callback) {
- OnMultiple(eventName, callback, -1);
+ EventsOnMultiple(eventName, callback, -1);
}
export function EventsOff(eventName) {
@@ -49,7 +49,7 @@ export function EventsOff(eventName) {
}
export function EventsOnce(eventName, callback) {
- OnMultiple(eventName, callback, 1);
+ EventsOnMultiple(eventName, callback, 1);
}
export function EventsEmit(eventName) {
@@ -145,8 +145,8 @@ export function WindowUnminimise() {
window.runtime.WindowUnminimise();
}
-export function WindowSetRGBA(RGBA) {
- window.runtime.WindowSetRGBA(RGBA);
+export function WindowSetBackgroundColour(R, G, B, A) {
+ window.runtime.WindowSetBackgroundColour(R, G, B, A);
}
export function BrowserOpenURL(url) {
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/main.tmpl.go b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/main.tmpl.go
index c60affe67..feeeaa186 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/main.tmpl.go
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue-ts/main.tmpl.go
@@ -16,11 +16,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
- OnStartup: app.startup,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ Assets: assets,
+ BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
+ OnStartup: app.startup,
Bind: []interface{}{
app,
},
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/frontend/.vscode/extensions.json b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/frontend/.vscode/extensions.json
index 3dc5b08bc..57011895d 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/frontend/.vscode/extensions.json
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/frontend/.vscode/extensions.json
@@ -1,3 +1,5 @@
{
- "recommendations": ["johnsoncodehk.volar"]
+ "recommendations": [
+ "Vue.volar"
+ ]
}
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/frontend/README.md b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/frontend/README.md
index eea15cef4..02124a7a0 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/frontend/README.md
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/frontend/README.md
@@ -4,4 +4,4 @@ This template should help get you started developing with Vue 3 in Vite. The tem
## Recommended IDE Setup
-- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar)
+- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar)
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/frontend/package.json b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/frontend/package.json
index c0f982635..d171757c8 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/frontend/package.json
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/frontend/package.json
@@ -11,7 +11,7 @@
"vue": "^3.2.25"
},
"devDependencies": {
- "@vitejs/plugin-vue": "^2.3.1",
- "vite": "^2.9.5"
+ "@vitejs/plugin-vue": "^2.3.3",
+ "vite": "^2.9.9"
}
}
\ No newline at end of file
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/frontend/wailsjs/runtime/runtime.d.ts b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/frontend/wailsjs/runtime/runtime.d.ts
index bcacbec00..8d816307f 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/frontend/wailsjs/runtime/runtime.d.ts
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/frontend/wailsjs/runtime/runtime.d.ts
@@ -167,9 +167,9 @@ export function WindowMinimise(): void;
// Restores the window to the dimensions and position prior to minimising.
export function WindowUnminimise(): void;
-// [WindowSetRGBA](https://wails.io/docs/reference/runtime/window#windowsetrgba)
+// [WindowSetBackgroundColour](https://wails.io/docs/reference/runtime/window#windowsetbackgroundcolour)
// Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels.
-export function WindowSetRGBA(R: number, G: number, B: number, A: number): void;
+export function WindowSetBackgroundColour(R: number, G: number, B: number, A: number): void;
// [BrowserOpenURL](https://wails.io/docs/reference/runtime/browser#browseropenurl)
// Opens the given URL in the system browser.
@@ -177,7 +177,7 @@ export function BrowserOpenURL(url: string): void;
// [Environment](https://wails.io/docs/reference/runtime/intro#environment)
// Returns information about the environment
-export function Environment(): EnvironmentInfo;
+export function Environment(): Promise;
// [Quit](https://wails.io/docs/reference/runtime/intro#quit)
// Quits the application.
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/frontend/wailsjs/runtime/runtime.js b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/frontend/wailsjs/runtime/runtime.js
index 8f47e62f1..73f607ba7 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/frontend/wailsjs/runtime/runtime.js
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/frontend/wailsjs/runtime/runtime.js
@@ -41,7 +41,7 @@ export function EventsOnMultiple(eventName, callback, maxCallbacks) {
}
export function EventsOn(eventName, callback) {
- OnMultiple(eventName, callback, -1);
+ EventsOnMultiple(eventName, callback, -1);
}
export function EventsOff(eventName) {
@@ -49,7 +49,7 @@ export function EventsOff(eventName) {
}
export function EventsOnce(eventName, callback) {
- OnMultiple(eventName, callback, 1);
+ EventsOnMultiple(eventName, callback, 1);
}
export function EventsEmit(eventName) {
@@ -145,8 +145,8 @@ export function WindowUnminimise() {
window.runtime.WindowUnminimise();
}
-export function WindowSetRGBA(RGBA) {
- window.runtime.WindowSetRGBA(RGBA);
+export function WindowSetBackgroundColour(R, G, B, A) {
+ window.runtime.WindowSetBackgroundColour(R, G, B, A);
}
export function BrowserOpenURL(url) {
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/main.tmpl.go b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/main.tmpl.go
index c60affe67..feeeaa186 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/main.tmpl.go
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/main.tmpl.go
@@ -16,11 +16,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
- OnStartup: app.startup,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ Assets: assets,
+ BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
+ OnStartup: app.startup,
Bind: []interface{}{
app,
},
diff --git a/v2/cmd/wails/internal/commands/update/update.go b/v2/cmd/wails/internal/commands/update/update.go
index 5eef6af25..8539d1b19 100644
--- a/v2/cmd/wails/internal/commands/update/update.go
+++ b/v2/cmd/wails/internal/commands/update/update.go
@@ -55,6 +55,12 @@ func AddSubcommand(app *clir.Cli, w io.Writer, currentVersion string) error {
desiredVersion, err = github.GetLatestPreRelease()
} else {
desiredVersion, err = github.GetLatestStableRelease()
+ if err != nil {
+ println("")
+ println("No stable release found for this major version. To update to the latest pre-release (eg beta), run:")
+ println(" wails update -pre")
+ return nil
+ }
}
}
if err != nil {
diff --git a/v2/cmd/wails/internal/version.go b/v2/cmd/wails/internal/version.go
index f1c511852..cfc37182c 100644
--- a/v2/cmd/wails/internal/version.go
+++ b/v2/cmd/wails/internal/version.go
@@ -1,3 +1,6 @@
package internal
-var Version = "v2.0.0-beta.36"
+import _ "embed"
+
+//go:embed version.txt
+var Version string
diff --git a/v2/cmd/wails/internal/version.txt b/v2/cmd/wails/internal/version.txt
new file mode 100644
index 000000000..7bdae6b2a
--- /dev/null
+++ b/v2/cmd/wails/internal/version.txt
@@ -0,0 +1 @@
+v2.0.0-beta.38
\ No newline at end of file
diff --git a/v2/cmd/wails/main.go b/v2/cmd/wails/main.go
index e69db18d7..dd7219fb5 100644
--- a/v2/cmd/wails/main.go
+++ b/v2/cmd/wails/main.go
@@ -23,7 +23,7 @@ func fatal(message string) {
}
func banner(_ *clir.Cli) string {
- return fmt.Sprintf("%s %s\n",
+ return fmt.Sprintf("%s %s",
colour.Yellow("Wails CLI"),
colour.DarkRed(internal.Version))
}
diff --git a/v2/go.mod b/v2/go.mod
index 5e3f0c2a8..2d227c31f 100644
--- a/v2/go.mod
+++ b/v2/go.mod
@@ -9,7 +9,7 @@ require (
github.com/go-git/go-billy/v5 v5.2.0 // indirect
github.com/go-git/go-git/v5 v5.3.0
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
- github.com/google/uuid v1.1.2 // indirect
+ github.com/google/uuid v1.1.2
github.com/imdario/mergo v0.3.12
github.com/jackmordaunt/icns v1.0.0
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e
@@ -17,7 +17,6 @@ require (
github.com/leaanthony/clir v1.0.4
github.com/leaanthony/debme v1.2.1
github.com/leaanthony/go-ansi-parser v1.0.1
- github.com/leaanthony/go-common-file-dialog v1.0.3
github.com/leaanthony/gosod v1.0.3
github.com/leaanthony/idgen v1.0.0
github.com/leaanthony/slicer v1.5.0
@@ -38,14 +37,17 @@ require (
golang.org/x/tools v0.1.0
)
-require github.com/bitfield/script v0.19.0
+require (
+ github.com/bep/debounce v1.2.1
+ github.com/bitfield/script v0.19.0
+ github.com/go-ole/go-ole v1.2.6
+)
require (
bitbucket.org/creachadair/shell v0.0.7 // indirect
github.com/Microsoft/go-winio v0.4.16 // indirect
github.com/emirpasic/gods v1.12.0 // indirect
github.com/go-git/gcfg v1.5.0 // indirect
- github.com/go-ole/go-ole v1.2.6 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
github.com/kr/pretty v0.3.0 // indirect
diff --git a/v2/go.sum b/v2/go.sum
index 14ea32693..b9b91b1b8 100644
--- a/v2/go.sum
+++ b/v2/go.sum
@@ -11,6 +11,8 @@ 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/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY=
+github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0=
github.com/bitfield/script v0.19.0 h1:W24f+FQuPab9gXcW8bhcbo5qO8AtrXyu3XOnR4zhHN0=
github.com/bitfield/script v0.19.0/go.mod h1:ana6F8YOSZ3ImT8SauIzuYSqXgFVkSUJ6kgja+WMmIY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@@ -36,7 +38,6 @@ github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12 h1:PbK
github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
github.com/go-git/go-git/v5 v5.3.0 h1:8WKMtJR2j8RntEXR/uvTKagfEt4GYlwQ7mntE4+0GWc=
github.com/go-git/go-git/v5 v5.3.0/go.mod h1:xdX4bWJ48aOrdhnl2XqHYstHbbp6+LFS4r4X+lNVprw=
-github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
@@ -46,7 +47,6 @@ github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
-github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
@@ -79,8 +79,6 @@ github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oO
github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA=
github.com/leaanthony/go-ansi-parser v1.0.1 h1:97v6c5kYppVsbScf4r/VZdXyQ21KQIfeQOk2DgKxGG4=
github.com/leaanthony/go-ansi-parser v1.0.1/go.mod h1:7arTzgVI47srICYhvgUV4CGd063sGEeoSlych5yeSPM=
-github.com/leaanthony/go-common-file-dialog v1.0.3 h1:O0uGjKnWtdEADGrkg+TyAAbZylykMwwx/MNEXn9fp+Y=
-github.com/leaanthony/go-common-file-dialog v1.0.3/go.mod h1:TGhEc9eSJgRsupZ+iH1ZgAOnEo9zp05cRH2j08RPrF0=
github.com/leaanthony/gosod v1.0.3 h1:Fnt+/B6NjQOVuCWOKYRREZnjGyvg+mEhd1nkkA04aTQ=
github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4=
github.com/leaanthony/idgen v1.0.0 h1:IZreR+JGEzFV4yeVuBZA25gM0keUoFy+RDUldncQ+Jw=
diff --git a/v2/internal/appng/app_bindings.go b/v2/internal/appng/app_bindings.go
index 477e811c2..8a80da32b 100644
--- a/v2/internal/appng/app_bindings.go
+++ b/v2/internal/appng/app_bindings.go
@@ -35,6 +35,8 @@ func (a *App) Run() error {
return nil
}
+func (a *App) Shutdown() {}
+
// CreateApp creates the app!
func CreateApp(appoptions *options.App) (*App, error) {
// Set up logger
diff --git a/v2/internal/appng/app_default_darwin.go b/v2/internal/appng/app_default_darwin.go
index fb40af694..9976a2595 100644
--- a/v2/internal/appng/app_default_darwin.go
+++ b/v2/internal/appng/app_default_darwin.go
@@ -16,6 +16,8 @@ func (a *App) Run() error {
return nil
}
+func (a *App) Shutdown() {}
+
// CreateApp creates the app!
func CreateApp(_ *options.App) (*App, error) {
return nil, fmt.Errorf(`Wails applications will not build without the correct build tags.`)
diff --git a/v2/internal/appng/app_default_linux.go b/v2/internal/appng/app_default_linux.go
index 257230e11..cbd566337 100644
--- a/v2/internal/appng/app_default_linux.go
+++ b/v2/internal/appng/app_default_linux.go
@@ -16,6 +16,8 @@ func (a *App) Run() error {
return nil
}
+func (a *App) Shutdown() {}
+
// CreateApp creates the app!
func CreateApp(_ *options.App) (*App, error) {
return nil, fmt.Errorf(`Wails applications will not build without the correct build tags.`)
diff --git a/v2/internal/appng/app_default_windows.go b/v2/internal/appng/app_default_windows.go
index cf70cef90..e3388b91f 100644
--- a/v2/internal/appng/app_default_windows.go
+++ b/v2/internal/appng/app_default_windows.go
@@ -17,6 +17,8 @@ func (a *App) Run() error {
return nil
}
+func (a *App) Shutdown() {}
+
// CreateApp creates the app!
func CreateApp(_ *options.App) (*App, error) {
result := w32.MessageBox(0,
diff --git a/v2/internal/appng/app_dev.go b/v2/internal/appng/app_dev.go
index 71715635a..e71149180 100644
--- a/v2/internal/appng/app_dev.go
+++ b/v2/internal/appng/app_dev.go
@@ -44,11 +44,16 @@ type App struct {
ctx context.Context
}
-func (a *App) Run() error {
- err := a.frontend.Run(a.ctx)
+func (a *App) Shutdown() {
if a.shutdownCallback != nil {
a.shutdownCallback(a.ctx)
}
+ a.frontend.Quit()
+}
+
+func (a *App) Run() error {
+ err := a.frontend.Run(a.ctx)
+ a.Shutdown()
return err
}
@@ -63,6 +68,8 @@ func CreateApp(appoptions *options.App) (*App, error) {
myLogger.SetLogLevel(appoptions.LogLevel)
// Check for CLI Flags
+ devFlags := flag.NewFlagSet("dev", flag.ContinueOnError)
+
var assetdirFlag *string
var devServerFlag *string
var frontendDevServerURLFlag *string
@@ -70,25 +77,28 @@ func CreateApp(appoptions *options.App) (*App, error) {
assetdir := os.Getenv("assetdir")
if assetdir == "" {
- assetdirFlag = flag.String("assetdir", "", "Directory to serve assets")
+ assetdirFlag = devFlags.String("assetdir", "", "Directory to serve assets")
}
+
devServer := os.Getenv("devserver")
if devServer == "" {
- devServerFlag = flag.String("devserver", "", "Address to bind the wails dev server to")
+ devServerFlag = devFlags.String("devserver", "", "Address to bind the wails dev server to")
}
+
frontendDevServerURL := os.Getenv("frontenddevserverurl")
if frontendDevServerURL == "" {
- frontendDevServerURLFlag = flag.String("frontenddevserverurl", "", "URL of the external frontend dev server")
+ frontendDevServerURLFlag = devFlags.String("frontenddevserverurl", "", "URL of the external frontend dev server")
}
loglevel := os.Getenv("loglevel")
if loglevel == "" {
- loglevelFlag = flag.String("loglevel", "debug", "Loglevel to use - Trace, Debug, Info, Warning, Error")
+ loglevelFlag = devFlags.String("loglevel", "debug", "Loglevel to use - Trace, Debug, Info, Warning, Error")
}
// If we weren't given the assetdir in the environment variables
if assetdir == "" {
- flag.Parse()
+ // Parse args but ignore errors in case -appargs was used to pass in args for the app.
+ _ = devFlags.Parse(os.Args[1:])
if assetdirFlag != nil {
assetdir = *assetdirFlag
}
diff --git a/v2/internal/appng/app_production.go b/v2/internal/appng/app_production.go
index cbbb75d3e..05e205712 100644
--- a/v2/internal/appng/app_production.go
+++ b/v2/internal/appng/app_production.go
@@ -34,11 +34,16 @@ type App struct {
ctx context.Context
}
-func (a *App) Run() error {
- err := a.frontend.Run(a.ctx)
+func (a *App) Shutdown() {
if a.shutdownCallback != nil {
a.shutdownCallback(a.ctx)
}
+ a.frontend.Quit()
+}
+
+func (a *App) Run() error {
+ err := a.frontend.Run(a.ctx)
+ a.Shutdown()
return err
}
diff --git a/v2/internal/binding/binding.go b/v2/internal/binding/binding.go
index 05b450336..132f4c4a2 100755
--- a/v2/internal/binding/binding.go
+++ b/v2/internal/binding/binding.go
@@ -152,11 +152,13 @@ func (b *Bindings) AddStructToGenerateTS(packageName string, structName string,
for i := 0; i < structType.NumField(); i++ {
field := structType.Field(i)
if field.Anonymous {
- return
+ continue
}
-
kind := field.Type.Kind()
if kind == reflect.Struct {
+ if field.PkgPath == "" {
+ continue
+ }
fqname := field.Type.String()
sName := strings.Split(fqname, ".")[1]
pName := getPackageName(fqname)
@@ -166,6 +168,9 @@ func (b *Bindings) AddStructToGenerateTS(packageName string, structName string,
b.AddStructToGenerateTS(pName, sName, s)
}
} else if kind == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct {
+ if field.PkgPath == "" {
+ continue
+ }
fqname := field.Type.String()
sName := strings.Split(fqname, ".")[1]
pName := getPackageName(fqname)
diff --git a/v2/internal/binding/generate.go b/v2/internal/binding/generate.go
index c1912f3b4..43be5d40c 100644
--- a/v2/internal/binding/generate.go
+++ b/v2/internal/binding/generate.go
@@ -6,6 +6,7 @@ import (
"fmt"
"os"
"path/filepath"
+ "sort"
"strings"
"github.com/wailsapp/wails/v2/internal/fs"
@@ -32,8 +33,17 @@ func (b *Bindings) GenerateGoBindings(baseDir string) error {
tsContent.WriteString(`// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
`)
+ // Sort the method names alphabetically
+ methodNames := make([]string, 0, len(methods))
+ for methodName := range methods {
+ methodNames = append(methodNames, methodName)
+ }
+ sort.Strings(methodNames)
+
var importNamespaces slicer.StringSlicer
- for methodName, methodDetails := range methods {
+ for _, methodName := range methodNames {
+ // Get the method details
+ methodDetails := methods[methodName]
// Generate JS
var args slicer.StringSlicer
@@ -44,11 +54,7 @@ func (b *Bindings) GenerateGoBindings(baseDir string) error {
argsString := args.Join(", ")
jsoutput.WriteString(fmt.Sprintf("\nexport function %s(%s) {", methodName, argsString))
jsoutput.WriteString("\n")
- if methodDetails.OutputCount() == 0 {
- jsoutput.WriteString(fmt.Sprintf(" window['go']['%s']['%s']['%s'](%s);", packageName, structName, methodName, argsString))
- } else {
- jsoutput.WriteString(fmt.Sprintf(" return window['go']['%s']['%s']['%s'](%s);", packageName, structName, methodName, argsString))
- }
+ jsoutput.WriteString(fmt.Sprintf(" return window['go']['%s']['%s']['%s'](%s);", packageName, structName, methodName, argsString))
jsoutput.WriteString("\n")
jsoutput.WriteString(fmt.Sprintf("}"))
jsoutput.WriteString("\n")
@@ -104,7 +110,7 @@ func (b *Bindings) GenerateGoBindings(baseDir string) error {
func goTypeToJSDocType(input string, importNamespaces *slicer.StringSlicer) string {
switch true {
- case input == "interface{}":
+ case input == "interface {}":
return "any"
case input == "string":
return "string"
diff --git a/v2/internal/ffenestri/ffenestri_client_windows.go b/v2/internal/ffenestri/ffenestri_client_windows.go
index c00c13706..a9a6cf042 100644
--- a/v2/internal/ffenestri/ffenestri_client_windows.go
+++ b/v2/internal/ffenestri/ffenestri_client_windows.go
@@ -14,7 +14,7 @@ import (
"strconv"
"syscall"
- "github.com/leaanthony/go-common-file-dialog/cfd"
+ "github.com/wailsapp/wails/v2/internal/go-common-file-dialog/cfd"
"github.com/wailsapp/wails/v2/pkg/runtime"
"golang.org/x/sys/windows"
diff --git a/v2/internal/frontend/assetserver/assethandler.go b/v2/internal/frontend/assetserver/assethandler.go
index c7e4ac455..f30869c88 100644
--- a/v2/internal/frontend/assetserver/assethandler.go
+++ b/v2/internal/frontend/assetserver/assethandler.go
@@ -11,7 +11,6 @@ import (
"os"
"path"
"strings"
- "time"
"github.com/wailsapp/wails/v2/internal/fs"
"github.com/wailsapp/wails/v2/internal/logger"
@@ -31,10 +30,10 @@ type assetHandler struct {
logger *logger.Logger
- servingFromDisk bool
+ retryMissingFiles bool
}
-func NewAsssetHandler(ctx context.Context, options *options.App) (http.Handler, error) {
+func NewAssetHandler(ctx context.Context, options *options.App) (http.Handler, error) {
vfs := options.Assets
if vfs != nil {
if _, err := vfs.Open("."); err != nil {
@@ -55,12 +54,6 @@ func NewAsssetHandler(ctx context.Context, options *options.App) (http.Handler,
result := &assetHandler{
fs: vfs,
handler: options.AssetsHandler,
-
- // Check if we have been given a directory to serve assets from.
- // If so, this means we are in dev mode and are serving assets off disk.
- // We indicate this through the `servingFromDisk` flag to ensure requests
- // aren't cached in dev mode.
- servingFromDisk: ctx.Value("assetdir") != nil,
}
if _logger := ctx.Value("logger"); _logger != nil {
@@ -84,10 +77,16 @@ func (d *assetHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if handler != nil {
d.logDebug("[AssetHandler] File '%s' not found, serving '%s' by AssetHandler", filename, req.URL)
handler.ServeHTTP(rw, req)
+ err = nil
+ } else if filename == indexHTML {
+ err = serveFile(rw, filename, defaultHTML)
} else {
rw.WriteHeader(http.StatusNotFound)
+ err = nil
}
- } else {
+ }
+
+ if err != nil {
d.logError("[AssetHandler] Unable to load file '%s': %s", filename, err)
http.Error(rw, err.Error(), http.StatusInternalServerError)
}
@@ -107,19 +106,7 @@ func (d *assetHandler) serveFSFile(rw http.ResponseWriter, filename string) erro
}
file, err := d.fs.Open(filename)
- if err != nil && d.servingFromDisk {
- for tries := 0; tries < 50; tries++ {
- file, err = d.fs.Open(filename)
- if err != nil {
- time.Sleep(100 * time.Millisecond)
- }
- }
- }
-
if err != nil {
- if filename == indexHTML && os.IsNotExist(err) {
- return serveFile(rw, filename, defaultHTML)
- }
return err
}
defer file.Close()
diff --git a/v2/internal/frontend/assetserver/assetserver.go b/v2/internal/frontend/assetserver/assetserver.go
index 47aa6eb33..fa3f1ed99 100644
--- a/v2/internal/frontend/assetserver/assetserver.go
+++ b/v2/internal/frontend/assetserver/assetserver.go
@@ -32,7 +32,7 @@ type AssetServer struct {
}
func NewAssetServer(ctx context.Context, options *options.App, bindingsJSON string) (*AssetServer, error) {
- handler, err := NewAsssetHandler(ctx, options)
+ handler, err := NewAssetHandler(ctx, options)
if err != nil {
return nil, err
}
diff --git a/v2/internal/frontend/desktop/darwin/Application.h b/v2/internal/frontend/desktop/darwin/Application.h
index 10a3aa638..bebaf84f3 100644
--- a/v2/internal/frontend/desktop/darwin/Application.h
+++ b/v2/internal/frontend/desktop/darwin/Application.h
@@ -23,6 +23,7 @@ void Run(void *inctx, const char* url, int activationPolicy);
void SetTitle(void* ctx, const char *title);
void Center(void* ctx);
void SetSize(void* ctx, int width, int height);
+void SetAlwaysOnTop(void* ctx, int onTop);
void SetMinSize(void* ctx, int width, int height);
void SetMaxSize(void* ctx, int width, int height);
void SetPosition(void* ctx, int x, int y);
@@ -35,7 +36,7 @@ void Maximise(void* ctx);
void UnMaximise(void* ctx);
void Hide(void* ctx);
void Show(void* ctx);
-void SetRGBA(void* ctx, int r, int g, int b, int a);
+void SetBackgroundColour(void* ctx, int r, int g, int b, int a);
void ExecJS(void* ctx, const char*);
void Quit(void*);
diff --git a/v2/internal/frontend/desktop/darwin/Application.m b/v2/internal/frontend/desktop/darwin/Application.m
index cd67014c5..22095d23a 100644
--- a/v2/internal/frontend/desktop/darwin/Application.m
+++ b/v2/internal/frontend/desktop/darwin/Application.m
@@ -82,10 +82,10 @@ void SetTitle(void* inctx, const char *title) {
}
-void SetRGBA(void *inctx, int r, int g, int b, int a) {
+void SetBackgroundColour(void *inctx, int r, int g, int b, int a) {
WailsContext *ctx = (__bridge WailsContext*) inctx;
ON_MAIN_THREAD(
- [ctx SetRGBA:r :g :b :a];
+ [ctx SetBackgroundColour:r :g :b :a];
);
}
@@ -96,6 +96,13 @@ void SetSize(void* inctx, int width, int height) {
);
}
+void SetAlwaysOnTop(void* inctx, int onTop) {
+ WailsContext *ctx = (__bridge WailsContext*) inctx;
+ ON_MAIN_THREAD(
+ [ctx SetAlwaysOnTop:onTop];
+ );
+}
+
void SetMinSize(void* inctx, int width, int height) {
WailsContext *ctx = (__bridge WailsContext*) inctx;
ON_MAIN_THREAD(
diff --git a/v2/internal/frontend/desktop/darwin/WailsContext.h b/v2/internal/frontend/desktop/darwin/WailsContext.h
index f4b4ca848..9b9e6103b 100644
--- a/v2/internal/frontend/desktop/darwin/WailsContext.h
+++ b/v2/internal/frontend/desktop/darwin/WailsContext.h
@@ -62,6 +62,7 @@
- (void) SetMinSize:(int)minWidth :(int)minHeight;
- (void) SetMaxSize:(int)maxWidth :(int)maxHeight;
- (void) SetTitle:(NSString*)title;
+- (void) SetAlwaysOnTop:(int)onTop;
- (void) Center;
- (void) Fullscreen;
- (void) UnFullscreen;
@@ -70,7 +71,7 @@
- (void) Maximise;
- (void) ToggleMaximise;
- (void) UnMaximise;
-- (void) SetRGBA:(int)r :(int)g :(int)b :(int)a;
+- (void) SetBackgroundColour:(int)r :(int)g :(int)b :(int)a;
- (void) HideMouse;
- (void) ShowMouse;
- (void) Hide;
diff --git a/v2/internal/frontend/desktop/darwin/WailsContext.m b/v2/internal/frontend/desktop/darwin/WailsContext.m
index 8abc2ca30..cc92902e0 100644
--- a/v2/internal/frontend/desktop/darwin/WailsContext.m
+++ b/v2/internal/frontend/desktop/darwin/WailsContext.m
@@ -299,7 +299,7 @@
[self.webview loadRequest:wkRequest];
}
-- (void) SetRGBA:(int)r :(int)g :(int)b :(int)a {
+- (void) SetBackgroundColour:(int)r :(int)g :(int)b :(int)a {
float red = r/255.0;
float green = g/255.0;
float blue = b/255.0;
@@ -372,6 +372,14 @@
}
}
+- (void) SetAlwaysOnTop:(int)onTop {
+ if (onTop) {
+ [self.mainWindow setLevel:NSStatusWindowLevel];
+ } else {
+ [self.mainWindow setLevel:NSNormalWindowLevel];
+ }
+}
+
- (void) ExecJS:(NSString*)script {
[self.webview evaluateJavaScript:script completionHandler:nil];
}
diff --git a/v2/internal/frontend/desktop/darwin/frontend.go b/v2/internal/frontend/desktop/darwin/frontend.go
index 3024ac737..b37815b9e 100644
--- a/v2/internal/frontend/desktop/darwin/frontend.go
+++ b/v2/internal/frontend/desktop/darwin/frontend.go
@@ -189,6 +189,9 @@ func (f *Frontend) Run(ctx context.Context) error {
func (f *Frontend) WindowCenter() {
f.mainWindow.Center()
}
+func (f *Frontend) WindowSetAlwaysOnTop(onTop bool) {
+ f.mainWindow.SetAlwaysOnTop(onTop)
+}
func (f *Frontend) WindowSetPosition(x, y int) {
f.mainWindow.SetPosition(x, y)
@@ -247,11 +250,11 @@ func (f *Frontend) WindowSetMaxSize(width int, height int) {
f.mainWindow.SetMaxSize(width, height)
}
-func (f *Frontend) WindowSetRGBA(col *options.RGBA) {
+func (f *Frontend) WindowSetBackgroundColour(col *options.RGBA) {
if col == nil {
return
}
- f.mainWindow.SetRGBA(col.R, col.G, col.B, col.A)
+ f.mainWindow.SetBackgroundColour(col.R, col.G, col.B, col.A)
}
func (f *Frontend) Quit() {
diff --git a/v2/internal/frontend/desktop/darwin/main.m b/v2/internal/frontend/desktop/darwin/main.m
index f7b0f62f0..154c33065 100644
--- a/v2/internal/frontend/desktop/darwin/main.m
+++ b/v2/internal/frontend/desktop/darwin/main.m
@@ -220,7 +220,7 @@ int main(int argc, const char * argv[]) {
int startsHidden = 0;
WailsContext *result = Create("OI OI!",400,400, frameless, resizable, fullscreen, fullSizeContent, hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent, alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, debug, windowStartState,
startsHidden, 400, 400, 600, 600);
- SetRGBA(result, 255, 0, 0, 255);
+ SetBackgroundColour(result, 255, 0, 0, 255);
void *m = NewMenu("");
SetAbout(result, "Fake title", "I am a description", _Users_username_Pictures_SaltBae_png, _Users_username_Pictures_SaltBae_png_len);
// AddMenuByRole(result, 1);
diff --git a/v2/internal/frontend/desktop/darwin/window.go b/v2/internal/frontend/desktop/darwin/window.go
index 8a1769b44..0f14eab47 100644
--- a/v2/internal/frontend/desktop/darwin/window.go
+++ b/v2/internal/frontend/desktop/darwin/window.go
@@ -96,8 +96,8 @@ func NewWindow(frontendOptions *options.App, debugMode bool) *Window {
context: unsafe.Pointer(context),
}
- if frontendOptions.RGBA != nil {
- result.SetRGBA(frontendOptions.RGBA.R, frontendOptions.RGBA.G, frontendOptions.RGBA.B, frontendOptions.RGBA.A)
+ if frontendOptions.BackgroundColour != nil {
+ result.SetBackgroundColour(frontendOptions.BackgroundColour.R, frontendOptions.BackgroundColour.G, frontendOptions.BackgroundColour.B, frontendOptions.BackgroundColour.A)
}
if frontendOptions.Mac != nil && frontendOptions.Mac.About != nil {
@@ -133,8 +133,8 @@ func (w *Window) Quit() {
C.Quit(w.context)
}
-func (w *Window) SetRGBA(r uint8, g uint8, b uint8, a uint8) {
- C.SetRGBA(w.context, C.int(r), C.int(g), C.int(b), C.int(a))
+func (w *Window) SetBackgroundColour(r uint8, g uint8, b uint8, a uint8) {
+ C.SetBackgroundColour(w.context, C.int(r), C.int(g), C.int(b), C.int(a))
}
func (w *Window) ExecJS(js string) {
@@ -151,6 +151,10 @@ func (w *Window) SetSize(width int, height int) {
C.SetSize(w.context, C.int(width), C.int(height))
}
+func (w *Window) SetAlwaysOnTop(onTop bool) {
+ C.SetAlwaysOnTop(w.context, bool2Cint(onTop))
+}
+
func (w *Window) SetTitle(title string) {
t := C.CString(title)
C.SetTitle(w.context, t)
diff --git a/v2/internal/frontend/desktop/linux/frontend.go b/v2/internal/frontend/desktop/linux/frontend.go
index 4d045c00e..c3cb1cbb8 100644
--- a/v2/internal/frontend/desktop/linux/frontend.go
+++ b/v2/internal/frontend/desktop/linux/frontend.go
@@ -144,6 +144,10 @@ func (f *Frontend) WindowCenter() {
f.mainWindow.Center()
}
+func (f *Frontend) WindowSetAlwaysOnTop(b bool) {
+ f.mainWindow.SetKeepAbove(b)
+}
+
func (f *Frontend) WindowSetPosition(x, y int) {
f.mainWindow.SetPosition(x, y)
}
@@ -205,11 +209,11 @@ func (f *Frontend) WindowSetMaxSize(width int, height int) {
f.mainWindow.SetMaxSize(width, height)
}
-func (f *Frontend) WindowSetRGBA(col *options.RGBA) {
+func (f *Frontend) WindowSetBackgroundColour(col *options.RGBA) {
if col == nil {
return
}
- f.mainWindow.SetRGBA(col.R, col.G, col.B, col.A)
+ f.mainWindow.SetBackgroundColour(col.R, col.G, col.B, col.A)
}
func (f *Frontend) Quit() {
diff --git a/v2/internal/frontend/desktop/linux/gtk.go b/v2/internal/frontend/desktop/linux/gtk.go
index 1592ccdc7..ead303539 100644
--- a/v2/internal/frontend/desktop/linux/gtk.go
+++ b/v2/internal/frontend/desktop/linux/gtk.go
@@ -11,8 +11,11 @@ extern void blockClick(GtkWidget* menuItem, gulong handler_id);
extern void unblockClick(GtkWidget* menuItem, gulong handler_id);
*/
import "C"
-import "unsafe"
-import "github.com/wailsapp/wails/v2/pkg/menu"
+import (
+ "unsafe"
+
+ "github.com/wailsapp/wails/v2/pkg/menu"
+)
func GtkMenuItemWithLabel(label string) *C.GtkWidget {
cLabel := C.CString(label)
@@ -37,6 +40,10 @@ func GtkRadioMenuItemWithLabel(label string, group *C.GSList) *C.GtkWidget {
//export handleMenuItemClick
func handleMenuItemClick(gtkWidget unsafe.Pointer) {
+ // Make sure to execute the final callback on a new goroutine otherwise if the callback e.g. tries to open a dialog, the
+ // main thread will get blocked and so the message loop blocks. As a result the app will block and shows a
+ // "not responding" dialog.
+
item := gtkSignalToMenuItem[(*C.GtkWidget)(gtkWidget)]
switch item.Type {
case menu.CheckboxType:
@@ -51,7 +58,7 @@ func handleMenuItemClick(gtkWidget unsafe.Pointer) {
C.gtk_check_menu_item_set_active(C.toGtkCheckMenuItem(unsafe.Pointer(gtkCheckbox)), checked)
C.unblockClick(gtkCheckbox, handler)
}
- item.Click(&menu.CallbackData{MenuItem: item})
+ go item.Click(&menu.CallbackData{MenuItem: item})
case menu.RadioType:
gtkRadioItems := gtkRadioMenuCache[item]
active := C.gtk_check_menu_item_get_active(C.toGtkCheckMenuItem(gtkWidget))
@@ -63,11 +70,11 @@ func handleMenuItemClick(gtkWidget unsafe.Pointer) {
C.unblockClick(gtkRadioItem, handler)
}
item.Checked = true
- item.Click(&menu.CallbackData{MenuItem: item})
+ go item.Click(&menu.CallbackData{MenuItem: item})
} else {
item.Checked = false
}
default:
- item.Click(&menu.CallbackData{MenuItem: item})
+ go item.Click(&menu.CallbackData{MenuItem: item})
}
}
diff --git a/v2/internal/frontend/desktop/linux/invoke.go b/v2/internal/frontend/desktop/linux/invoke.go
new file mode 100644
index 000000000..16d5e73d2
--- /dev/null
+++ b/v2/internal/frontend/desktop/linux/invoke.go
@@ -0,0 +1,78 @@
+//go:build linux
+// +build linux
+
+package linux
+
+/*
+#cgo linux pkg-config: gtk+-3.0
+
+#include
+#include "gtk/gtk.h"
+
+extern gboolean invokeCallbacks(void *);
+
+static inline void triggerInvokesOnMainThread() {
+ g_idle_add((GSourceFunc)invokeCallbacks, NULL);
+}
+*/
+import "C"
+import (
+ "runtime"
+ "sync"
+ "unsafe"
+
+ "golang.org/x/sys/unix"
+)
+
+var (
+ m sync.Mutex
+ mainTid int
+ dispatchq []func()
+)
+
+func invokeOnMainThread(f func()) {
+ if tryInvokeOnCurrentGoRoutine(f) {
+ return
+ }
+
+ m.Lock()
+ dispatchq = append(dispatchq, f)
+ m.Unlock()
+
+ C.triggerInvokesOnMainThread()
+}
+
+func tryInvokeOnCurrentGoRoutine(f func()) bool {
+ m.Lock()
+ mainThreadID := mainTid
+ m.Unlock()
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ if mainThreadID != unix.Gettid() {
+ return false
+ }
+ f()
+ return true
+}
+
+//export invokeCallbacks
+func invokeCallbacks(_ unsafe.Pointer) C.gboolean {
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ m.Lock()
+ if mainTid == 0 {
+ mainTid = unix.Gettid()
+ }
+
+ q := append([]func(){}, dispatchq...)
+ dispatchq = []func(){}
+ m.Unlock()
+
+ for _, v := range q {
+ v()
+ }
+ return C.G_SOURCE_REMOVE
+}
diff --git a/v2/internal/frontend/desktop/linux/responsewriter.go b/v2/internal/frontend/desktop/linux/responsewriter.go
index 12ebadae7..3b08a3845 100644
--- a/v2/internal/frontend/desktop/linux/responsewriter.go
+++ b/v2/internal/frontend/desktop/linux/responsewriter.go
@@ -84,7 +84,7 @@ func (rw *webKitResponseWriter) WriteHeader(code int) {
}
stream := C.g_unix_input_stream_new(C.int(rFD), gtkBool(true))
- C.webkit_uri_scheme_request_finish(rw.req, stream, C.long(contentLength), cMimeType)
+ C.webkit_uri_scheme_request_finish(rw.req, stream, C.gint64(contentLength), cMimeType)
C.g_object_unref(C.gpointer(stream))
}
diff --git a/v2/internal/frontend/desktop/linux/window.go b/v2/internal/frontend/desktop/linux/window.go
index 7c6b6f363..374450a92 100644
--- a/v2/internal/frontend/desktop/linux/window.go
+++ b/v2/internal/frontend/desktop/linux/window.go
@@ -249,11 +249,10 @@ typedef struct JSCallback {
char* script;
} JSCallback;
-gboolean executeJS(gpointer data) {
+void executeJS(void *data) {
struct JSCallback *js = data;
webkit_web_view_run_javascript(js->webview, js->script, NULL, NULL, NULL);
free(js->script);
- return G_SOURCE_REMOVE;
}
void extern processMessageDialogResult(char*);
@@ -265,8 +264,7 @@ typedef struct MessageDialogOptions {
int messageType;
} MessageDialogOptions;
-gboolean messageDialog(gpointer data) {
-
+void messageDialog(void *data) {
GtkDialogFlags flags;
GtkMessageType messageType;
MessageDialogOptions *options = (MessageDialogOptions*) data;
@@ -307,14 +305,12 @@ gboolean messageDialog(gpointer data) {
gtk_widget_destroy(dialog);
free(options->title);
free(options->message);
-
- return G_SOURCE_REMOVE;
}
void extern processOpenFileResult(void*);
typedef struct OpenFileDialogOptions {
- void* webview;
+ GtkWindow* window;
char* title;
char* defaultFilename;
char* defaultDirectory;
@@ -333,13 +329,13 @@ void freeFileFilterArray(GtkFileFilter** filters) {
free(filters);
}
-gboolean opendialog(gpointer data) {
+void opendialog(void *data) {
struct OpenFileDialogOptions *options = data;
char *label = "_Open";
if (options->action == GTK_FILE_CHOOSER_ACTION_SAVE) {
label = "_Save";
}
- GtkWidget *dlgWidget = gtk_file_chooser_dialog_new(options->title, options->webview, options->action,
+ GtkWidget *dlgWidget = gtk_file_chooser_dialog_new(options->title, options->window, options->action,
"_Cancel", GTK_RESPONSE_CANCEL,
label, GTK_RESPONSE_ACCEPT,
NULL);
@@ -421,7 +417,6 @@ gboolean opendialog(gpointer data) {
}
gtk_widget_destroy(dlgWidget);
free(options->title);
- return G_SOURCE_REMOVE;
}
GtkFileFilter* newFileFilter() {
@@ -436,14 +431,20 @@ typedef struct RGBAOptions {
uint8_t b;
uint8_t a;
void *webview;
+ void *window;
} RGBAOptions;
-gboolean setRGBA(gpointer* data) {
+void setBackgroundColour(void* data) {
RGBAOptions* options = (RGBAOptions*)data;
GdkRGBA colour = {options->r / 255.0, options->g / 255.0, options->b / 255.0, options->a / 255.0};
webkit_web_view_set_background_color(WEBKIT_WEB_VIEW(options->webview), &colour);
-
- return G_SOURCE_REMOVE;
+ GtkCssProvider *provider = gtk_css_provider_new();
+ char buffer[60];
+ sprintf((void*)&buffer[0], "* { background-color: rgba(%d,%d,%d,%d); }", options->r, options->g, options->b, options->a);
+ gtk_css_provider_load_from_data (provider, &buffer[0], -1, NULL);
+ gtk_style_context_add_provider(gtk_widget_get_style_context(GTK_WIDGET(options->window)),
+ GTK_STYLE_PROVIDER(provider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER);
}
typedef struct SetTitleArgs {
@@ -572,6 +573,7 @@ void SetWindowIcon(GtkWindow* window, const guchar* buf, gsize len) {
import "C"
import (
"strings"
+ "sync"
"unsafe"
"github.com/wailsapp/wails/v2/internal/frontend"
@@ -643,8 +645,8 @@ func NewWindow(appoptions *options.App, debug bool) *Window {
}
// Set background colour
- RGBA := appoptions.RGBA
- result.SetRGBA(RGBA.R, RGBA.G, RGBA.B, RGBA.A)
+ RGBA := appoptions.BackgroundColour
+ result.SetBackgroundColour(RGBA.R, RGBA.G, RGBA.B, RGBA.A)
// Setup window
result.SetKeepAbove(appoptions.AlwaysOnTop)
@@ -714,13 +716,25 @@ func (w *Window) SetPosition(x int, y int) {
func (w *Window) Size() (int, int) {
var width, height C.int
- C.gtk_window_get_size(w.asGTKWindow(), &width, &height)
+ var wg sync.WaitGroup
+ wg.Add(1)
+ invokeOnMainThread(func() {
+ C.gtk_window_get_size(w.asGTKWindow(), &width, &height)
+ wg.Done()
+ })
+ wg.Wait()
return int(width), int(height)
}
func (w *Window) GetPosition() (int, int) {
var width, height C.int
- C.gtk_window_get_position(w.asGTKWindow(), &width, &height)
+ var wg sync.WaitGroup
+ wg.Add(1)
+ invokeOnMainThread(func() {
+ C.gtk_window_get_position(w.asGTKWindow(), &width, &height)
+ wg.Done()
+ })
+ wg.Wait()
return int(width), int(height)
}
@@ -773,15 +787,16 @@ func (w *Window) IsMaximised() bool {
return result > 0
}
-func (w *Window) SetRGBA(r uint8, g uint8, b uint8, a uint8) {
+func (w *Window) SetBackgroundColour(r uint8, g uint8, b uint8, a uint8) {
data := C.RGBAOptions{
r: C.uchar(r),
g: C.uchar(g),
b: C.uchar(b),
a: C.uchar(a),
webview: w.webview,
+ window: w.gtkWindow,
}
- C.ExecuteOnMainThread(C.setRGBA, C.gpointer(&data))
+ invokeOnMainThread(func() { C.setBackgroundColour(unsafe.Pointer(&data)) })
}
@@ -840,7 +855,7 @@ func (w *Window) ExecJS(js string) {
webview: w.webview,
script: C.CString(js),
}
- C.ExecuteOnMainThread(C.executeJS, C.gpointer(&jscallback))
+ invokeOnMainThread(func() { C.executeJS(unsafe.Pointer(&jscallback)) })
}
func (w *Window) StartDrag() {
@@ -854,7 +869,7 @@ func (w *Window) Quit() {
func (w *Window) OpenFileDialog(dialogOptions frontend.OpenDialogOptions, multipleFiles int, action C.GtkFileChooserAction) {
data := C.OpenFileDialogOptions{
- webview: w.webview,
+ window: w.asGTKWindow(),
title: C.CString(dialogOptions.Title),
multipleFiles: C.int(multipleFiles),
action: action,
@@ -864,8 +879,8 @@ func (w *Window) OpenFileDialog(dialogOptions frontend.OpenDialogOptions, multip
// Create filter array
mem := NewCalloc()
arraySize := len(dialogOptions.Filters) + 1
- data.filters = C.allocFileFilterArray((C.ulong)(arraySize))
- filters := (*[1 << 30]*C.struct__GtkFileFilter)(unsafe.Pointer(data.filters))
+ data.filters = C.allocFileFilterArray((C.size_t)(arraySize))
+ filters := unsafe.Slice((**C.struct__GtkFileFilter)(unsafe.Pointer(data.filters)), arraySize)
for index, filter := range dialogOptions.Filters {
thisFilter := C.gtk_file_filter_new()
C.g_object_ref(C.gpointer(thisFilter))
@@ -902,7 +917,7 @@ func (w *Window) OpenFileDialog(dialogOptions frontend.OpenDialogOptions, multip
data.defaultDirectory = C.CString(dialogOptions.DefaultDirectory)
}
- C.ExecuteOnMainThread(C.opendialog, C.gpointer(&data))
+ invokeOnMainThread(func() { C.opendialog(unsafe.Pointer(&data)) })
}
func (w *Window) MessageDialog(dialogOptions frontend.MessageDialogOptions) {
@@ -922,7 +937,7 @@ func (w *Window) MessageDialog(dialogOptions frontend.MessageDialogOptions) {
case frontend.WarningDialog:
data.messageType = C.int(3)
}
- C.ExecuteOnMainThread(C.messageDialog, C.gpointer(&data))
+ invokeOnMainThread(func() { C.messageDialog(unsafe.Pointer(&data)) })
}
func (w *Window) ToggleMaximise() {
diff --git a/v2/internal/frontend/desktop/windows/dialog.go b/v2/internal/frontend/desktop/windows/dialog.go
index f2bb7bf1d..a8fa5b8a3 100644
--- a/v2/internal/frontend/desktop/windows/dialog.go
+++ b/v2/internal/frontend/desktop/windows/dialog.go
@@ -4,8 +4,8 @@
package windows
import (
- "github.com/leaanthony/go-common-file-dialog/cfd"
"github.com/wailsapp/wails/v2/internal/frontend"
+ "github.com/wailsapp/wails/v2/internal/go-common-file-dialog/cfd"
"golang.org/x/sys/windows"
"syscall"
)
diff --git a/v2/internal/frontend/desktop/windows/frontend.go b/v2/internal/frontend/desktop/windows/frontend.go
index c2a5716cf..276db118d 100644
--- a/v2/internal/frontend/desktop/windows/frontend.go
+++ b/v2/internal/frontend/desktop/windows/frontend.go
@@ -7,6 +7,18 @@ import (
"context"
"encoding/json"
"fmt"
+ "github.com/bep/debounce"
+ "github.com/wailsapp/wails/v2/internal/binding"
+ "github.com/wailsapp/wails/v2/internal/frontend"
+ "github.com/wailsapp/wails/v2/internal/frontend/assetserver"
+ "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge"
+ "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/win32"
+ "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc"
+ "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
+ "github.com/wailsapp/wails/v2/internal/logger"
+ "github.com/wailsapp/wails/v2/internal/system/operatingsystem"
+ "github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/windows"
"io"
"log"
"net/http"
@@ -16,17 +28,7 @@ import (
"strconv"
"strings"
"text/template"
-
- "github.com/wailsapp/wails/v2/internal/binding"
- "github.com/wailsapp/wails/v2/internal/frontend"
- "github.com/wailsapp/wails/v2/internal/frontend/assetserver"
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge"
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc"
- "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
- "github.com/wailsapp/wails/v2/internal/logger"
- "github.com/wailsapp/wails/v2/internal/system/operatingsystem"
- "github.com/wailsapp/wails/v2/pkg/options"
- "github.com/wailsapp/wails/v2/pkg/options/windows"
+ "time"
)
const startURL = "http://wails.localhost/"
@@ -53,7 +55,8 @@ type Frontend struct {
hasStarted bool
// Windows build number
- versionInfo *operatingsystem.WindowsVersionInfo
+ versionInfo *operatingsystem.WindowsVersionInfo
+ resizeDebouncer func(f func())
}
func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher) *Frontend {
@@ -70,6 +73,12 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
versionInfo: versionInfo,
}
+ if appoptions.Windows != nil {
+ if appoptions.Windows.ResizeDebounceMS > 0 {
+ result.resizeDebouncer = debounce.New(time.Duration(appoptions.Windows.ResizeDebounceMS) * time.Millisecond)
+ }
+ }
+
// We currently can't use wails://wails/ as other platforms do, therefore we map the assets sever onto the following url.
result.startURL, _ = url.Parse(startURL)
@@ -97,31 +106,15 @@ func (f *Frontend) WindowReload() {
}
func (f *Frontend) WindowSetSystemDefaultTheme() {
- runtime.LockOSThread()
- f.mainWindow.frontendOptions.Windows.Theme = windows.SystemDefault
- f.mainWindow.Invoke(func() {
- f.mainWindow.updateTheme()
- })
+ f.mainWindow.SetTheme(windows.SystemDefault)
}
func (f *Frontend) WindowSetLightTheme() {
- runtime.LockOSThread()
- if f.mainWindow.frontendOptions != nil && f.mainWindow.frontendOptions.Windows != nil {
- f.mainWindow.frontendOptions.Windows.Theme = windows.Light
- f.mainWindow.Invoke(func() {
- f.mainWindow.updateTheme()
- })
- }
+ f.mainWindow.SetTheme(windows.Light)
}
func (f *Frontend) WindowSetDarkTheme() {
- runtime.LockOSThread()
- if f.mainWindow.frontendOptions != nil && f.mainWindow.frontendOptions.Windows != nil {
- f.mainWindow.frontendOptions.Windows.Theme = windows.Dark
- f.mainWindow.Invoke(func() {
- f.mainWindow.updateTheme()
- })
- }
+ f.mainWindow.SetTheme(windows.Dark)
}
func (f *Frontend) Run(ctx context.Context) error {
@@ -153,7 +146,15 @@ func (f *Frontend) Run(ctx context.Context) error {
}
}
- f.chromium.Resize()
+ if f.resizeDebouncer != nil {
+ f.resizeDebouncer(func() {
+ f.mainWindow.Invoke(func() {
+ f.chromium.Resize()
+ })
+ })
+ } else {
+ f.chromium.Resize()
+ }
})
mainWindow.OnClose().Bind(func(arg *winc.Event) {
@@ -176,35 +177,47 @@ func (f *Frontend) Run(ctx context.Context) error {
func (f *Frontend) WindowCenter() {
runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
f.mainWindow.Center()
}
+func (f *Frontend) WindowSetAlwaysOnTop(b bool) {
+ runtime.LockOSThread()
+ f.mainWindow.SetAlwaysOnTop(b)
+}
+
func (f *Frontend) WindowSetPosition(x, y int) {
runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
f.mainWindow.SetPos(x, y)
}
func (f *Frontend) WindowGetPosition() (int, int) {
runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
return f.mainWindow.Pos()
}
func (f *Frontend) WindowSetSize(width, height int) {
runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
f.mainWindow.SetSize(width, height)
}
func (f *Frontend) WindowGetSize() (int, int) {
runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
return f.mainWindow.Size()
}
func (f *Frontend) WindowSetTitle(title string) {
runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
f.mainWindow.SetText(title)
}
func (f *Frontend) WindowFullscreen() {
runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
if f.frontendOptions.Frameless && f.frontendOptions.DisableResize == false {
f.ExecJS("window.wails.flags.enableResize = false;")
}
@@ -217,6 +230,7 @@ func (f *Frontend) WindowReloadApp() {
func (f *Frontend) WindowUnfullscreen() {
runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
if f.frontendOptions.Frameless && f.frontendOptions.DisableResize == false {
f.ExecJS("window.wails.flags.enableResize = true;")
}
@@ -225,15 +239,19 @@ func (f *Frontend) WindowUnfullscreen() {
func (f *Frontend) WindowShow() {
runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
f.ShowWindow()
}
func (f *Frontend) WindowHide() {
runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
f.mainWindow.Hide()
}
+
func (f *Frontend) WindowMaximise() {
runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
if f.hasStarted {
if !f.frontendOptions.DisableResize {
f.mainWindow.Maximise()
@@ -242,8 +260,10 @@ func (f *Frontend) WindowMaximise() {
f.frontendOptions.WindowStartState = options.Maximised
}
}
+
func (f *Frontend) WindowToggleMaximise() {
runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
if !f.hasStarted {
return
}
@@ -256,32 +276,38 @@ func (f *Frontend) WindowToggleMaximise() {
func (f *Frontend) WindowUnmaximise() {
runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
f.mainWindow.Restore()
}
+
func (f *Frontend) WindowMinimise() {
runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
if f.hasStarted {
f.mainWindow.Minimise()
} else {
f.frontendOptions.WindowStartState = options.Minimised
}
}
+
func (f *Frontend) WindowUnminimise() {
runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
f.mainWindow.Restore()
}
func (f *Frontend) WindowSetMinSize(width int, height int) {
runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
f.mainWindow.SetMinSize(width, height)
}
func (f *Frontend) WindowSetMaxSize(width int, height int) {
runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
f.mainWindow.SetMaxSize(width, height)
}
-func (f *Frontend) WindowSetRGBA(col *options.RGBA) {
- runtime.LockOSThread()
+func (f *Frontend) WindowSetBackgroundColour(col *options.RGBA) {
if col == nil {
return
}
@@ -311,6 +337,7 @@ func (f *Frontend) WindowSetRGBA(col *options.RGBA) {
log.Fatal(err)
}
})
+
}
func (f *Frontend) Quit() {
@@ -325,8 +352,9 @@ func (f *Frontend) Quit() {
func (f *Frontend) setupChromium() {
chromium := edge.NewChromium()
f.chromium = chromium
- if opts := f.frontendOptions.Windows; opts != nil && opts.WebviewUserDataPath != "" {
+ if opts := f.frontendOptions.Windows; opts != nil {
chromium.DataPath = opts.WebviewUserDataPath
+ chromium.BrowserPath = opts.WebviewBrowserPath
}
chromium.MessageCallback = f.processMessage
chromium.WebResourceRequestedCallback = f.processRequest
@@ -371,7 +399,7 @@ func (f *Frontend) setupChromium() {
onFocus.Bind(f.onFocus)
// Set background colour
- f.WindowSetRGBA(f.frontendOptions.RGBA)
+ f.WindowSetBackgroundColour(f.frontendOptions.BackgroundColour)
chromium.SetGlobalPermission(edge.CoreWebView2PermissionStateAllow)
chromium.AddWebResourceRequestedFilter("*", edge.COREWEBVIEW2_WEB_RESOURCE_CONTEXT_ALL)
@@ -572,29 +600,55 @@ func (f *Frontend) navigationCompleted(sender *edge.ICoreWebView2, args *edge.IC
switch f.frontendOptions.WindowStartState {
case options.Maximised:
if !f.frontendOptions.DisableResize {
- f.mainWindow.Maximise()
+ win32.ShowWindowMaximised(f.mainWindow.Handle())
} else {
- f.mainWindow.Show()
+ win32.ShowWindow(f.mainWindow.Handle())
}
- f.ShowWindow()
-
case options.Minimised:
- f.mainWindow.Minimise()
+ win32.ShowWindowMinimised(f.mainWindow.Handle())
case options.Fullscreen:
f.mainWindow.Fullscreen()
- f.ShowWindow()
+ win32.ShowWindow(f.mainWindow.Handle())
default:
if f.frontendOptions.Fullscreen {
f.mainWindow.Fullscreen()
}
- f.ShowWindow()
+ win32.ShowWindow(f.mainWindow.Handle())
}
+ f.mainWindow.hasBeenShown = true
+
}
func (f *Frontend) ShowWindow() {
f.mainWindow.Invoke(func() {
- f.mainWindow.Restore()
+ if !f.mainWindow.hasBeenShown {
+ f.mainWindow.hasBeenShown = true
+ switch f.frontendOptions.WindowStartState {
+ case options.Maximised:
+ if !f.frontendOptions.DisableResize {
+ win32.ShowWindowMaximised(f.mainWindow.Handle())
+ } else {
+ win32.ShowWindow(f.mainWindow.Handle())
+ }
+ case options.Minimised:
+ win32.RestoreWindow(f.mainWindow.Handle())
+ case options.Fullscreen:
+ f.mainWindow.Fullscreen()
+ win32.ShowWindow(f.mainWindow.Handle())
+ default:
+ if f.frontendOptions.Fullscreen {
+ f.mainWindow.Fullscreen()
+ }
+ win32.ShowWindow(f.mainWindow.Handle())
+ }
+ } else {
+ if win32.IsWindowMinimised(f.mainWindow.Handle()) {
+ win32.RestoreWindow(f.mainWindow.Handle())
+ } else {
+ win32.ShowWindow(f.mainWindow.Handle())
+ }
+ }
w32.SetForegroundWindow(f.mainWindow.Handle())
w32.SetFocus(f.mainWindow.Handle())
})
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebViewSettings.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebViewSettings.go
index 701601bc0..a4cf31a32 100644
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebViewSettings.go
+++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/ICoreWebViewSettings.go
@@ -1,8 +1,9 @@
package edge
import (
- "golang.org/x/sys/windows"
"unsafe"
+
+ "golang.org/x/sys/windows"
)
// ICoreWebviewSettings is the merged settings class
@@ -27,17 +28,17 @@ type _ICoreWebViewSettingsVtbl struct {
PutIsZoomControlEnabled ComProc
GetIsBuiltInErrorPageEnabled ComProc
PutIsBuiltInErrorPageEnabled ComProc
- GetUserAgent ComProc
+ GetUserAgent ComProc // ICoreWebView2Settings2: SDK 1.0.864.35
PutUserAgent ComProc
- GetAreBrowserAcceleratorKeysEnabled ComProc
+ GetAreBrowserAcceleratorKeysEnabled ComProc // ICoreWebView2Settings3: SDK 1.0.864.35
PutAreBrowserAcceleratorKeysEnabled ComProc
- GetIsPasswordAutosaveEnabled ComProc
+ GetIsPasswordAutosaveEnabled ComProc // ICoreWebView2Settings4: SDK 1.0.902.49
PutIsPasswordAutosaveEnabled ComProc
GetIsGeneralAutofillEnabled ComProc
PutIsGeneralAutofillEnabled ComProc
- GetIsPinchZoomEnabled ComProc
+ GetIsPinchZoomEnabled ComProc // ICoreWebView2Settings5: SDK 1.0.902.49
PutIsPinchZoomEnabled ComProc
- GetIsSwipeNavigationEnabled ComProc
+ GetIsSwipeNavigationEnabled ComProc // ICoreWebView2Settings6: SDK 1.0.992.28
PutIsSwipeNavigationEnabled ComProc
}
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium.go b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium.go
index ad046a5c5..785140917 100644
--- a/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium.go
+++ b/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge/chromium.go
@@ -4,6 +4,7 @@
package edge
import (
+ "errors"
"log"
"os"
"path/filepath"
@@ -30,8 +31,9 @@ type Chromium struct {
environment *ICoreWebView2Environment
// Settings
- Debug bool
- DataPath string
+ Debug bool
+ DataPath string
+ BrowserPath string
// permissions
permissions map[CoreWebView2PermissionKind]CoreWebView2PermissionState
@@ -84,7 +86,27 @@ func (e *Chromium) Embed(hwnd uintptr) bool {
dataPath = filepath.Join(os.Getenv("AppData"), currentExeName)
}
- res, err := createCoreWebView2EnvironmentWithOptions(nil, windows.StringToUTF16Ptr(dataPath), 0, e.envCompleted)
+ var browserPathPtr *uint16 = nil
+ if e.BrowserPath != "" {
+ if _, err := os.Stat(e.BrowserPath); !errors.Is(err, os.ErrNotExist) {
+ browserPathPtr, err = windows.UTF16PtrFromString(e.BrowserPath)
+ if err != nil {
+ log.Printf("Error calling UTF16PtrFromString for %s: %v", e.BrowserPath, err)
+ return false
+ }
+ } else {
+ log.Printf("Browser path %s does not exist", e.BrowserPath)
+ return false
+ }
+ }
+
+ dataPathPtr, err := windows.UTF16PtrFromString(dataPath)
+ if err != nil {
+ log.Printf("Error calling UTF16PtrFromString for %s: %v", dataPath, err)
+ return false
+ }
+
+ res, err := createCoreWebView2EnvironmentWithOptions(browserPathPtr, dataPathPtr, 0, e.envCompleted)
if err != nil {
log.Printf("Error calling Webview2Loader: %v", err)
return false
diff --git a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/module.go b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/module.go
index 7566c2894..e8ae8fab5 100644
--- a/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/module.go
+++ b/v2/internal/frontend/desktop/windows/go-webview2/webviewloader/module.go
@@ -10,11 +10,6 @@ import (
)
var (
- nativeModule = windows.NewLazyDLL("WebView2Loader")
- nativeCreate = nativeModule.NewProc("CreateCoreWebView2EnvironmentWithOptions")
- nativeCompareBrowserVersions = nativeModule.NewProc("CompareBrowserVersions")
- nativeGetAvailableCoreWebView2BrowserVersionString = nativeModule.NewProc("GetAvailableCoreWebView2BrowserVersionString")
-
memOnce sync.Once
memModule winloader.Module
memCreate winloader.Proc
@@ -23,12 +18,16 @@ var (
memErr error
)
-// CompareBrowserVersions will compare the 2 given versions and return:
-// -1 = v1 < v2
-// 0 = v1 == v2
-// 1 = v1 > v2
-func CompareBrowserVersions(v1 string, v2 string) (int, error) {
+const (
+ // https://referencesource.microsoft.com/#system.web/Util/hresults.cs,20
+ E_FILENOTFOUND = 0x80070002
+)
+// CompareBrowserVersions will compare the 2 given versions and return:
+// Less than zero: v1 < v2
+// zero: v1 == v2
+// Greater than zero: v1 > v2
+func CompareBrowserVersions(v1 string, v2 string) (int, error) {
_v1, err := windows.UTF16PtrFromString(v1)
if err != nil {
return 0, err
@@ -38,57 +37,54 @@ func CompareBrowserVersions(v1 string, v2 string) (int, error) {
return 0, err
}
- nativeErr := nativeModule.Load()
- if nativeErr == nil {
- nativeErr = nativeCompareBrowserVersions.Find()
- }
- var result int
- if nativeErr != nil {
- err := loadFromMemory(nativeErr)
- if err != nil {
- return 0, fmt.Errorf("Unable to load WebView2Loader.dll from disk: %v -- or from memory: %w", nativeErr, memErr)
- }
- _, _, err = memCompareBrowserVersions.Call(
- uint64(uintptr(unsafe.Pointer(_v1))),
- uint64(uintptr(unsafe.Pointer(_v2))),
- uint64(uintptr(unsafe.Pointer(&result))))
- } else {
- _, _, err = nativeCompareBrowserVersions.Call(
- uintptr(unsafe.Pointer(_v1)),
- uintptr(unsafe.Pointer(_v2)),
- uintptr(unsafe.Pointer(&result)))
+ err = loadFromMemory()
+ if err != nil {
+ return 0, err
}
+
+ var result int32
+ _, _, err = memCompareBrowserVersions.Call(
+ uint64(uintptr(unsafe.Pointer(_v1))),
+ uint64(uintptr(unsafe.Pointer(_v2))),
+ uint64(uintptr(unsafe.Pointer(&result))))
+
if err != windows.ERROR_SUCCESS {
- return result, err
+ return 0, err
}
- return result, nil
+ return int(result), nil
}
-// GetInstalledVersion returns the installed version of the webview2 runtime.
+// GetWebviewVersion returns version of the webview2 runtime.
+// If path is empty, it will try to find installed webview2 is the system.
// If there is no version installed, a blank string is returned.
-func GetInstalledVersion() (string, error) {
- nativeErr := nativeModule.Load()
- if nativeErr == nil {
- nativeErr = nativeGetAvailableCoreWebView2BrowserVersionString.Find()
- }
- var err error
- var result *uint16
- if nativeErr != nil {
- err := loadFromMemory(nativeErr)
- if err != nil {
- return "", fmt.Errorf("Unable to load WebView2Loader.dll from disk: %v -- or from memory: %w", nativeErr, memErr)
- }
- _, _, err = memGetAvailableCoreWebView2BrowserVersionString.Call(
- uint64(uintptr(unsafe.Pointer(nil))),
- uint64(uintptr(unsafe.Pointer(&result))))
- } else {
- _, _, err = nativeCompareBrowserVersions.Call(
- uintptr(unsafe.Pointer(nil)),
- uintptr(unsafe.Pointer(&result)))
- }
+func GetWebviewVersion(path string) (string, error) {
+ err := loadFromMemory()
if err != nil {
return "", err
}
+
+ var browserPath *uint16 = nil
+ if path != "" {
+ browserPath, err = windows.UTF16PtrFromString(path)
+ if err != nil {
+ return "", fmt.Errorf("error calling UTF16PtrFromString for %s: %v", path, err)
+ }
+ }
+
+ var result *uint16
+ res, _, err := memGetAvailableCoreWebView2BrowserVersionString.Call(
+ uint64(uintptr(unsafe.Pointer(browserPath))),
+ uint64(uintptr(unsafe.Pointer(&result))))
+
+ if res != 0 {
+ if res == E_FILENOTFOUND {
+ // Webview2 is not installed
+ return "", nil
+ }
+
+ return "", fmt.Errorf("Unable to call GetAvailableCoreWebView2BrowserVersionString (%x): %w", res, err)
+ }
+
version := windows.UTF16PtrToString(result)
windows.CoTaskMemFree(unsafe.Pointer(result))
return version, nil
@@ -97,39 +93,26 @@ func GetInstalledVersion() (string, error) {
// CreateCoreWebView2EnvironmentWithOptions tries to load WebviewLoader2 and
// call the CreateCoreWebView2EnvironmentWithOptions routine.
func CreateCoreWebView2EnvironmentWithOptions(browserExecutableFolder, userDataFolder *uint16, environmentOptions uintptr, environmentCompletedHandle uintptr) (uintptr, error) {
- nativeErr := nativeModule.Load()
- if nativeErr == nil {
- nativeErr = nativeCreate.Find()
+ err := loadFromMemory()
+ if err != nil {
+ return 0, err
}
- if nativeErr != nil {
- err := loadFromMemory(nativeErr)
- if err != nil {
- return 0, err
- }
- res, _, _ := memCreate.Call(
- uint64(uintptr(unsafe.Pointer(browserExecutableFolder))),
- uint64(uintptr(unsafe.Pointer(userDataFolder))),
- uint64(environmentOptions),
- uint64(environmentCompletedHandle),
- )
- return uintptr(res), nil
- }
- res, _, _ := nativeCreate.Call(
- uintptr(unsafe.Pointer(browserExecutableFolder)),
- uintptr(unsafe.Pointer(userDataFolder)),
- environmentOptions,
- environmentCompletedHandle,
+ res, _, _ := memCreate.Call(
+ uint64(uintptr(unsafe.Pointer(browserExecutableFolder))),
+ uint64(uintptr(unsafe.Pointer(userDataFolder))),
+ uint64(environmentOptions),
+ uint64(environmentCompletedHandle),
)
- return res, nil
+ return uintptr(res), nil
}
-func loadFromMemory(nativeErr error) error {
+func loadFromMemory() error {
var err error
// DLL is not available natively. Try loading embedded copy.
memOnce.Do(func() {
memModule, memErr = winloader.LoadFromMemory(WebView2Loader)
if memErr != nil {
- err = fmt.Errorf("Unable to load WebView2Loader.dll from disk: %v -- or from memory: %w", nativeErr, memErr)
+ err = fmt.Errorf("Unable to load WebView2Loader.dll from memory: %w", memErr)
return
}
memCreate = memModule.Proc("CreateCoreWebView2EnvironmentWithOptions")
diff --git a/v2/internal/frontend/desktop/windows/theme.go b/v2/internal/frontend/desktop/windows/theme.go
index 842d7480d..897133026 100644
--- a/v2/internal/frontend/desktop/windows/theme.go
+++ b/v2/internal/frontend/desktop/windows/theme.go
@@ -7,6 +7,12 @@ import (
func (w *Window) updateTheme() {
+ // Don't redraw theme if nothing has changed
+ if !w.themeChanged {
+ return
+ }
+ w.themeChanged = false
+
if win32.IsCurrentlyHighContrastMode() {
return
}
@@ -14,25 +20,24 @@ func (w *Window) updateTheme() {
if !win32.SupportsThemes() {
return
}
- // Only process if there's a theme change
- isDarkMode := win32.IsCurrentlyDarkMode()
- w.isDarkMode = isDarkMode
- // Default use system theme
+ var isDarkMode bool
+ switch w.theme {
+ case windows.SystemDefault:
+ isDarkMode = win32.IsCurrentlyDarkMode()
+ case windows.Dark:
+ isDarkMode = true
+ case windows.Light:
+ isDarkMode = false
+ }
+ win32.SetTheme(w.Handle(), isDarkMode)
+
+ // Custom theme processing
winOptions := w.frontendOptions.Windows
var customTheme *windows.ThemeSettings
if winOptions != nil {
customTheme = winOptions.CustomTheme
- if winOptions.Theme == windows.Dark {
- isDarkMode = true
- }
- if winOptions.Theme == windows.Light {
- isDarkMode = false
- }
}
-
- win32.SetTheme(w.Handle(), isDarkMode)
-
// Custom theme
if win32.SupportsCustomThemes() && customTheme != nil {
if w.isActive {
diff --git a/v2/internal/frontend/desktop/windows/win32/consts.go b/v2/internal/frontend/desktop/windows/win32/consts.go
index a35465422..66f648021 100644
--- a/v2/internal/frontend/desktop/windows/win32/consts.go
+++ b/v2/internal/frontend/desktop/windows/win32/consts.go
@@ -12,9 +12,12 @@ type HRESULT int32
type HANDLE uintptr
var (
- moduser32 = syscall.NewLazyDLL("user32.dll")
- procSystemParametersInfo = moduser32.NewProc("SystemParametersInfoW")
- procGetWindowLong = moduser32.NewProc("GetWindowLongW")
+ moduser32 = syscall.NewLazyDLL("user32.dll")
+ procSystemParametersInfo = moduser32.NewProc("SystemParametersInfoW")
+ procGetWindowLong = moduser32.NewProc("GetWindowLongW")
+ procSetClassLong = moduser32.NewProc("SetClassLongW")
+ procSetClassLongPtr = moduser32.NewProc("SetClassLongPtrW")
+ procShowWindow = moduser32.NewProc("ShowWindow")
procLookupIconIdFromDirectoryEx = moduser32.NewProc("LookupIconIdFromDirectoryEx")
procCreateIconFromResourceEx = moduser32.NewProc("CreateIconFromResourceEx")
procCreateIconIndirect = moduser32.NewProc("CreateIconIndirect")
@@ -30,6 +33,11 @@ var (
procDwmSetWindowAttribute = moddwmapi.NewProc("DwmSetWindowAttribute")
procDwmExtendFrameIntoClientArea = moddwmapi.NewProc("DwmExtendFrameIntoClientArea")
)
+var (
+ modwingdi = syscall.NewLazyDLL("gdi32.dll")
+ procCreateSolidBrush = modwingdi.NewProc("CreateSolidBrush")
+)
+
var windowsVersion, _ = operatingsystem.GetWindowsVersionInfo()
func IsWindowsVersionAtLeast(major, minor, buildNumber int) bool {
diff --git a/v2/internal/frontend/desktop/windows/win32/theme.go b/v2/internal/frontend/desktop/windows/win32/theme.go
index aefa73813..89aa9fc74 100644
--- a/v2/internal/frontend/desktop/windows/win32/theme.go
+++ b/v2/internal/frontend/desktop/windows/win32/theme.go
@@ -1,11 +1,8 @@
-//go:build windows
-
package win32
import (
- "unsafe"
-
"golang.org/x/sys/windows/registry"
+ "unsafe"
)
type DWMWINDOWATTRIBUTE int32
@@ -15,10 +12,19 @@ const DwmwaUseImmersiveDarkMode DWMWINDOWATTRIBUTE = 20
const DwmwaBorderColor DWMWINDOWATTRIBUTE = 34
const DwmwaCaptionColor DWMWINDOWATTRIBUTE = 35
const DwmwaTextColor DWMWINDOWATTRIBUTE = 36
+const DwmwaSystemBackdropType DWMWINDOWATTRIBUTE = 38
const SPI_GETHIGHCONTRAST = 0x0042
const HCF_HIGHCONTRASTON = 0x00000001
+type BackdropType int32
+
+const DwmsbtAuto BackdropType = 0
+const DwmsbtDisable = 1 // None
+const DwmsbtMainWindow = 2 // Mica
+const DwmsbtTransientWindow = 3 // Acrylic
+const DwmsbtTabbedWindow = 4 // Tabbed
+
func dwmSetWindowAttribute(hwnd uintptr, dwAttribute DWMWINDOWATTRIBUTE, pvAttribute unsafe.Pointer, cbAttribute uintptr) {
ret, _, err := procDwmSetWindowAttribute.Call(
hwnd,
@@ -46,7 +52,19 @@ func SetTheme(hwnd uintptr, useDarkMode bool) {
if IsWindowsVersionAtLeast(10, 0, 18985) {
attr = DwmwaUseImmersiveDarkMode
}
- dwmSetWindowAttribute(hwnd, attr, unsafe.Pointer(&useDarkMode), unsafe.Sizeof(&useDarkMode))
+ var winDark int32
+ if useDarkMode {
+ winDark = 1
+ }
+ dwmSetWindowAttribute(hwnd, attr, unsafe.Pointer(&winDark), unsafe.Sizeof(winDark))
+ }
+}
+
+func EnableTranslucency(hwnd uintptr, backdrop BackdropType) {
+ if IsWindowsVersionAtLeast(10, 0, 22579) {
+ dwmSetWindowAttribute(hwnd, DwmwaSystemBackdropType, unsafe.Pointer(&backdrop), unsafe.Sizeof(backdrop))
+ } else {
+ println("Warning: Translucency unavailable on Windows < 22579")
}
}
@@ -73,7 +91,6 @@ func IsCurrentlyDarkMode() bool {
if err != nil {
return false
}
-
return AppsUseLightTheme == 0
}
@@ -91,5 +108,6 @@ func IsCurrentlyHighContrastMode() bool {
_ = err
return false
}
- return result.DwFlags&HCF_HIGHCONTRASTON == HCF_HIGHCONTRASTON
+ r := result.DwFlags&HCF_HIGHCONTRASTON == HCF_HIGHCONTRASTON
+ return r
}
diff --git a/v2/internal/frontend/desktop/windows/win32/window.go b/v2/internal/frontend/desktop/windows/win32/window.go
index 48263aaf2..1ddcf4c98 100644
--- a/v2/internal/frontend/desktop/windows/win32/window.go
+++ b/v2/internal/frontend/desktop/windows/win32/window.go
@@ -5,16 +5,62 @@ package win32
import (
"fmt"
"log"
+ "strconv"
"syscall"
"unsafe"
+
+ "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc"
)
const (
WS_MAXIMIZE = 0x01000000
+ WS_MINIMIZE = 0x20000000
GWL_STYLE = -16
)
+const (
+ SW_HIDE = 0
+ SW_NORMAL = 1
+ SW_SHOWNORMAL = 1
+ SW_SHOWMINIMIZED = 2
+ SW_MAXIMIZE = 3
+ SW_SHOWMAXIMIZED = 3
+ SW_SHOWNOACTIVATE = 4
+ SW_SHOW = 5
+ SW_MINIMIZE = 6
+ SW_SHOWMINNOACTIVE = 7
+ SW_SHOWNA = 8
+ SW_RESTORE = 9
+ SW_SHOWDEFAULT = 10
+ SW_FORCEMINIMIZE = 11
+)
+
+const (
+ GCLP_HBRBACKGROUND int32 = -10
+)
+
+// Power
+const (
+ // WM_POWERBROADCAST - Notifies applications that a power-management event has occurred.
+ WM_POWERBROADCAST = 536
+
+ // PBT_APMPOWERSTATUSCHANGE - Power status has changed.
+ PBT_APMPOWERSTATUSCHANGE = 10
+
+ // PBT_APMRESUMEAUTOMATIC -Operation is resuming automatically from a low-power state. This message is sent every time the system resumes.
+ PBT_APMRESUMEAUTOMATIC = 18
+
+ // PBT_APMRESUMESUSPEND - Operation is resuming from a low-power state. This message is sent after PBT_APMRESUMEAUTOMATIC if the resume is triggered by user input, such as pressing a key.
+ PBT_APMRESUMESUSPEND = 7
+
+ // PBT_APMSUSPEND - System is suspending operation.
+ PBT_APMSUSPEND = 4
+
+ // PBT_POWERSETTINGCHANGE - A power setting change event has been received.
+ PBT_POWERSETTINGCHANGE = 32787
+)
+
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb773244.aspx
type MARGINS struct {
CxLeftWidth, CxRightWidth, CyTopHeight, CyBottomHeight int32
@@ -36,6 +82,31 @@ func IsWindowMaximised(hwnd uintptr) bool {
style := uint32(getWindowLong(hwnd, GWL_STYLE))
return style&WS_MAXIMIZE != 0
}
+func IsWindowMinimised(hwnd uintptr) bool {
+ style := uint32(getWindowLong(hwnd, GWL_STYLE))
+ return style&WS_MINIMIZE != 0
+}
+
+func RestoreWindow(hwnd uintptr) {
+ showWindow(hwnd, SW_RESTORE)
+}
+
+func ShowWindow(hwnd uintptr) {
+ showWindow(hwnd, SW_SHOW)
+}
+
+func ShowWindowMaximised(hwnd uintptr) {
+ showWindow(hwnd, SW_MAXIMIZE)
+}
+func ShowWindowMinimised(hwnd uintptr) {
+ showWindow(hwnd, SW_MINIMIZE)
+}
+
+func SetBackgroundColour(hwnd uintptr, r, g, b uint8) {
+ col := winc.RGB(r, g, b)
+ hbrush, _, _ := procCreateSolidBrush.Call(uintptr(col))
+ setClassLongPtr(hwnd, GCLP_HBRBACKGROUND, hbrush)
+}
func dwmExtendFrameIntoClientArea(hwnd uintptr, margins *MARGINS) error {
ret, _, _ := procDwmExtendFrameIntoClientArea.Call(
@@ -49,6 +120,27 @@ func dwmExtendFrameIntoClientArea(hwnd uintptr, margins *MARGINS) error {
return nil
}
+func setClassLongPtr(hwnd uintptr, param int32, val uintptr) bool {
+ proc := procSetClassLongPtr
+ if strconv.IntSize == 32 {
+ /*
+ https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setclasslongptrw
+ Note: To write code that is compatible with both 32-bit and 64-bit Windows, use SetClassLongPtr.
+ When compiling for 32-bit Windows, SetClassLongPtr is defined as a call to the SetClassLong function
+
+ => We have to do this dynamically when directly calling the DLL procedures
+ */
+ proc = procSetClassLong
+ }
+
+ ret, _, _ := proc.Call(
+ hwnd,
+ uintptr(param),
+ val,
+ )
+ return ret != 0
+}
+
func getWindowLong(hwnd uintptr, index int) int32 {
ret, _, _ := procGetWindowLong.Call(
hwnd,
@@ -56,3 +148,11 @@ func getWindowLong(hwnd uintptr, index int) int32 {
return int32(ret)
}
+
+func showWindow(hwnd uintptr, cmdshow int) bool {
+ ret, _, _ := procShowWindow.Call(
+ hwnd,
+ uintptr(cmdshow))
+
+ return ret != 0
+}
diff --git a/v2/internal/frontend/desktop/windows/winc/controlbase.go b/v2/internal/frontend/desktop/windows/winc/controlbase.go
index 1f7cb66ff..610e67e3b 100644
--- a/v2/internal/frontend/desktop/windows/winc/controlbase.go
+++ b/v2/internal/frontend/desktop/windows/winc/controlbase.go
@@ -267,6 +267,13 @@ func (cba *ControlBase) SetPos(x, y int) {
w32.SetWindowPos(cba.hwnd, w32.HWND_TOP, int(workRect.Left)+x, int(workRect.Top)+y, 0, 0, w32.SWP_NOSIZE)
}
+func (cba *ControlBase) SetAlwaysOnTop(b bool) {
+ if b {
+ w32.SetWindowPos(cba.hwnd, w32.HWND_TOPMOST, 0, 0, 0, 0, w32.SWP_NOSIZE|w32.SWP_NOMOVE)
+ } else {
+ w32.SetWindowPos(cba.hwnd, w32.HWND_NOTOPMOST, 0, 0, 0, 0, w32.SWP_NOSIZE|w32.SWP_NOMOVE)
+ }
+}
func (cba *ControlBase) Pos() (x, y int) {
rect := w32.GetWindowRect(cba.hwnd)
diff --git a/v2/internal/frontend/desktop/windows/window.go b/v2/internal/frontend/desktop/windows/window.go
index 21170bfe7..5bbada150 100644
--- a/v2/internal/frontend/desktop/windows/window.go
+++ b/v2/internal/frontend/desktop/windows/window.go
@@ -3,14 +3,16 @@
package windows
import (
+ "unsafe"
+
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/win32"
"github.com/wailsapp/wails/v2/internal/system/operatingsystem"
- "unsafe"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
"github.com/wailsapp/wails/v2/pkg/menu"
"github.com/wailsapp/wails/v2/pkg/options"
+ winoptions "github.com/wailsapp/wails/v2/pkg/options/windows"
)
type Window struct {
@@ -22,6 +24,14 @@ type Window struct {
versionInfo *operatingsystem.WindowsVersionInfo
isDarkMode bool
isActive bool
+ hasBeenShown bool
+
+ // Theme
+ theme winoptions.Theme
+ themeChanged bool
+
+ OnSuspend func()
+ OnResume func()
}
func NewWindow(parent winc.Controller, appoptions *options.App, versionInfo *operatingsystem.WindowsVersionInfo) *Window {
@@ -33,6 +43,7 @@ func NewWindow(parent winc.Controller, appoptions *options.App, versionInfo *ope
maxWidth: appoptions.MaxWidth,
versionInfo: versionInfo,
isActive: true,
+ themeChanged: true,
}
result.SetIsForm(true)
@@ -65,6 +76,16 @@ func NewWindow(parent winc.Controller, appoptions *options.App, versionInfo *ope
}
}
+ if appoptions.BackgroundColour != nil {
+ win32.SetBackgroundColour(result.Handle(), appoptions.BackgroundColour.R, appoptions.BackgroundColour.G, appoptions.BackgroundColour.B)
+ }
+
+ if appoptions.Windows != nil {
+ result.theme = appoptions.Windows.Theme
+ } else {
+ result.theme = winoptions.SystemDefault
+ }
+
result.SetSize(appoptions.Width, appoptions.Height)
result.SetText(appoptions.Title)
result.EnableSizable(!appoptions.DisableResize)
@@ -77,8 +98,15 @@ func NewWindow(parent winc.Controller, appoptions *options.App, versionInfo *ope
result.updateTheme()
if appoptions.Windows != nil {
+ result.OnSuspend = appoptions.Windows.OnSuspend
+ result.OnResume = appoptions.Windows.OnResume
if appoptions.Windows.WindowIsTranslucent {
- result.SetTranslucentBackground()
+ // TODO: Migrate to win32 package
+ if !win32.IsWindowsVersionAtLeast(10, 0, 22579) {
+ result.SetTranslucentBackground()
+ } else {
+ win32.EnableTranslucency(result.Handle(), win32.BackdropType(appoptions.Windows.TranslucencyType))
+ }
}
if appoptions.Windows.DisableWindowIcon {
@@ -133,9 +161,22 @@ func (w *Window) SetMaxSize(maxWidth int, maxHeight int) {
func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
switch msg {
+ case win32.WM_POWERBROADCAST:
+ switch wparam {
+ case win32.PBT_APMSUSPEND:
+ if w.OnSuspend != nil {
+ w.OnSuspend()
+ }
+ case win32.PBT_APMRESUMEAUTOMATIC:
+ if w.OnResume != nil {
+ w.OnResume()
+ }
+ }
+
case w32.WM_SETTINGCHANGE:
settingChanged := w32.UTF16PtrToString((*uint16)(unsafe.Pointer(lparam)))
if settingChanged == "ImmersiveColorSet" {
+ w.themeChanged = true
w.updateTheme()
}
return 0
@@ -143,10 +184,11 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
w32.SetFocus(w.Handle())
case w32.WM_MOVE, w32.WM_MOVING:
if w.notifyParentWindowPositionChanged != nil {
- w.notifyParentWindowPositionChanged()
+ _ = w.notifyParentWindowPositionChanged()
}
case w32.WM_ACTIVATE:
//if !w.frontendOptions.Frameless {
+ w.themeChanged = true
if int(wparam) == w32.WA_INACTIVE {
w.isActive = false
w.updateTheme()
@@ -185,6 +227,8 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
// This hides the titlebar and also disables the resizing from user interaction because the standard frame is not
// shown. We still need the WS_THICKFRAME style to enable resizing from the frontend.
if wparam != 0 {
+ rgrc := (*w32.RECT)(unsafe.Pointer(lparam))
+
style := uint32(w32.GetWindowLong(w.Handle(), w32.GWL_STYLE))
if style&w32.WS_MAXIMIZE != 0 {
// If the window is maximized we must adjust the client area to the work area of the monitor. Otherwise
@@ -194,7 +238,6 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
var monitorInfo w32.MONITORINFO
monitorInfo.CbSize = uint32(unsafe.Sizeof(monitorInfo))
if w32.GetMonitorInfo(monitor, &monitorInfo) {
- rgrc := (*w32.RECT)(unsafe.Pointer(lparam))
*rgrc = monitorInfo.RcWork
maxWidth := w.frontendOptions.MaxWidth
@@ -214,6 +257,10 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
}
}
}
+ } else {
+ // This is needed to workaround the resize flickering in frameless mode with WindowDecorations
+ // See: https://stackoverflow.com/a/6558508
+ rgrc.Bottom -= 1
}
return 0
@@ -225,5 +272,16 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
func (w *Window) IsMaximised() bool {
return win32.IsWindowMaximised(w.Handle())
-
+}
+
+func (w *Window) IsMinimised() bool {
+ return win32.IsWindowMinimised(w.Handle())
+}
+
+func (w *Window) SetTheme(theme winoptions.Theme) {
+ w.theme = theme
+ w.themeChanged = true
+ w.Invoke(func() {
+ w.updateTheme()
+ })
}
diff --git a/v2/internal/frontend/devserver/devserver.go b/v2/internal/frontend/devserver/devserver.go
index 356272119..784f3e203 100644
--- a/v2/internal/frontend/devserver/devserver.go
+++ b/v2/internal/frontend/devserver/devserver.go
@@ -77,7 +77,7 @@ func (d *DevWebServer) Run(ctx context.Context) error {
})
var err error
- assetHandler, err = assetserver.NewAsssetHandler(ctx, d.appoptions)
+ assetHandler, err = assetserver.NewAssetHandler(ctx, d.appoptions)
if err != nil {
log.Fatal(err)
}
@@ -211,6 +211,9 @@ func (d *DevWebServer) WindowMinimise() {
func (d *DevWebServer) WindowUnminimise() {
d.desktopFrontend.WindowUnminimise()
}
+func (d *DevWebServer) WindowSetAlwaysOnTop(b bool) {
+ d.desktopFrontend.WindowSetAlwaysOnTop(b)
+}
func (d *DevWebServer) WindowSetPosition(x int, y int) {
d.desktopFrontend.WindowSetPosition(x, y)
@@ -244,8 +247,8 @@ func (d *DevWebServer) WindowUnfullscreen() {
d.desktopFrontend.WindowUnfullscreen()
}
-func (d *DevWebServer) WindowSetRGBA(col *options.RGBA) {
- d.desktopFrontend.WindowSetRGBA(col)
+func (d *DevWebServer) WindowSetBackgroundColour(col *options.RGBA) {
+ d.desktopFrontend.WindowSetBackgroundColour(col)
}
func (d *DevWebServer) MenuSetApplicationMenu(menu *menu.Menu) {
diff --git a/v2/internal/frontend/dispatcher/window.go b/v2/internal/frontend/dispatcher/window.go
index 78da341f7..7e136e069 100644
--- a/v2/internal/frontend/dispatcher/window.go
+++ b/v2/internal/frontend/dispatcher/window.go
@@ -32,6 +32,12 @@ func (d *Dispatcher) processWindowMessage(message string, sender frontend.Fronte
go sender.WindowSetLightTheme()
case "DT":
go sender.WindowSetDarkTheme()
+ case "TP:0", "TP:1":
+ if message[2:] == "TP:0" {
+ go sender.WindowSetAlwaysOnTop(false)
+ } else if message[2:] == "TP:1" {
+ go sender.WindowSetAlwaysOnTop(true)
+ }
}
case 'c':
go sender.WindowCenter()
@@ -64,7 +70,7 @@ func (d *Dispatcher) processWindowMessage(message string, sender frontend.Fronte
if err != nil {
return "", err
}
- go sender.WindowSetRGBA(&rgba)
+ go sender.WindowSetBackgroundColour(&rgba)
case 'M':
go sender.WindowMaximise()
case 't':
diff --git a/v2/internal/frontend/frontend.go b/v2/internal/frontend/frontend.go
index 6cf14855f..fa5da491c 100644
--- a/v2/internal/frontend/frontend.go
+++ b/v2/internal/frontend/frontend.go
@@ -77,6 +77,7 @@ type Frontend interface {
WindowUnmaximise()
WindowMinimise()
WindowUnminimise()
+ WindowSetAlwaysOnTop(b bool)
WindowSetPosition(x int, y int)
WindowGetPosition() (int, int)
WindowSetSize(width int, height int)
@@ -85,7 +86,7 @@ type Frontend interface {
WindowSetMaxSize(width int, height int)
WindowFullscreen()
WindowUnfullscreen()
- WindowSetRGBA(col *options.RGBA)
+ WindowSetBackgroundColour(col *options.RGBA)
WindowReload()
WindowReloadApp()
WindowSetSystemDefaultTheme()
diff --git a/v2/internal/frontend/runtime/desktop/window.js b/v2/internal/frontend/runtime/desktop/window.js
index de1c512cd..41e4d6704 100644
--- a/v2/internal/frontend/runtime/desktop/window.js
+++ b/v2/internal/frontend/runtime/desktop/window.js
@@ -114,6 +114,21 @@ export function WindowSetMinSize(width, height) {
window.WailsInvoke('Wz:' + width + ':' + height);
}
+
+
+/**
+ * Set the window AlwaysOnTop or not on top
+ *
+ * @export
+ */
+export function WindowSetAlwaysOnTop(b) {
+
+ window.WailsInvoke('WATP:' + (b ? '1' : '0'));
+}
+
+
+
+
/**
* Set the Position of the window
*
@@ -198,7 +213,6 @@ export function WindowUnminimise() {
window.WailsInvoke('Wu');
}
-
/**
* Sets the background colour of the window
*
@@ -208,7 +222,7 @@ export function WindowUnminimise() {
* @param {number} B Blue
* @param {number} A Alpha
*/
-export function WindowSetRGBA(R, G, B, A) {
+export function WindowSetBackgroundColour(R, G, B, A) {
let rgba = JSON.stringify({r: R || 0, g: G || 0, b: B || 0, a: A || 255});
window.WailsInvoke('Wr:' + rgba);
}
diff --git a/v2/internal/frontend/runtime/dev/package-lock.json b/v2/internal/frontend/runtime/dev/package-lock.json
index 4413e7f6b..ee4166ac2 100644
--- a/v2/internal/frontend/runtime/dev/package-lock.json
+++ b/v2/internal/frontend/runtime/dev/package-lock.json
@@ -519,9 +519,9 @@
"dev": true
},
"shell-quote": {
- "version": "1.7.2",
- "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz",
- "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==",
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz",
+ "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==",
"dev": true
},
"side-channel": {
diff --git a/v2/internal/frontend/runtime/ipc_websocket.js b/v2/internal/frontend/runtime/ipc_websocket.js
index d14009671..1e4c330b6 100644
--- a/v2/internal/frontend/runtime/ipc_websocket.js
+++ b/v2/internal/frontend/runtime/ipc_websocket.js
@@ -1,9 +1,9 @@
(()=>{function j(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 _(){}var O=t=>t;function G(t){return t()}function nt(){return Object.create(null)}function b(t){t.forEach(G)}function S(t){return typeof t=="function"}function D(t,e){return t!=t?e==e:t!==e||t&&typeof t=="object"||typeof t=="function"}function it(t){return Object.keys(t).length===0}function rt(t,...e){if(t==null)return _;let n=t.subscribe(...e);return n.unsubscribe?()=>n.unsubscribe():n}function ot(t,e,n){t.$$.on_destroy.push(rt(e,n))}var st=typeof window!="undefined",Ot=st?()=>window.performance.now():()=>Date.now(),K=st?t=>requestAnimationFrame(t):_;var F=new Set;function ct(t){F.forEach(e=>{e.c(t)||(F.delete(e),e.f())}),F.size!==0&&K(ct)}function Dt(t){let e;return F.size===0&&K(ct),{promise:new Promise(n=>{F.add(e={c:t,f:n})}),abort(){F.delete(e)}}}var lt=!1;function At(){lt=!0}function Lt(){lt=!1}function Bt(t,e){t.appendChild(e)}function ut(t,e,n){let i=P(t);if(!i.getElementById(e)){let r=L("style");r.id=e,r.textContent=n,at(i,r)}}function P(t){if(!t)return document;let e=t.getRootNode?t.getRootNode():t.ownerDocument;return e.host?e:document}function Jt(t){let e=L("style");return at(P(t),e),e}function at(t,e){Bt(t.head||t,e)}function R(t,e,n){t.insertBefore(e,n||null)}function A(t){t.parentNode.removeChild(t)}function L(t){return document.createElement(t)}function zt(t){return document.createTextNode(t)}function ft(){return zt("")}function dt(t,e,n){n==null?t.removeAttribute(e):t.getAttribute(e)!==n&&t.setAttribute(e,n)}function Tt(t){return Array.from(t.childNodes)}function Ht(t,e,n=!1){let i=document.createEvent("CustomEvent");return i.initCustomEvent(t,n,!1,e),i}var N=new Set,B=0;function qt(t){let e=5381,n=t.length;for(;n--;)e=(e<<5)-e^t.charCodeAt(n);return e>>>0}function ht(t,e,n,i,r,c,s,l=0){let a=16.666/i,o=`{
`;for(let g=0;g<=1;g+=a){let v=e+(n-e)*c(g);o+=g*100+`%{${s(v,1-v)}}
`}let y=o+`100% {${s(n,1-n)}}
-}`,f=`__svelte_${qt(y)}_${l}`,u=P(t);N.add(u);let h=u.__svelte_stylesheet||(u.__svelte_stylesheet=Jt(t).sheet),p=u.__svelte_rules||(u.__svelte_rules={});p[f]||(p[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 Gt(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||Kt())}function Kt(){K(()=>{B||(N.forEach(t=>{let e=t.__svelte_stylesheet,n=e.cssRules.length;for(;n--;)e.deleteRule(n);t.__svelte_rules={}}),N.clear())})}var pt;function J(t){pt=t}var $=[];var _t=[],z=[],mt=[],Pt=Promise.resolve(),W=!1;function Rt(){W||(W=!0,Pt.then(yt))}function x(t){z.push(t)}var V=!1,U=new Set;function yt(){if(!V){V=!0;do{for(let t=0;t<$.length;t+=1){let e=$[t];J(e),Nt(e.$$)}for(J(null),$.length=0;_t.length;)_t.pop()();for(let t=0;t{k=null})),k}function X(t,e,n){t.dispatchEvent(Ht(`${e?"intro":"outro"}${n}`))}var T=new Set,m;function gt(){m={r:0,c:[],p:m}}function bt(){m.r||b(m.c),m=m.p}function C(t,e){t&&t.i&&(T.delete(t),t.i(e))}function Z(t,e,n,i){if(t&&t.o){if(T.has(t))return;T.add(t),m.c.push(()=>{T.delete(t),i&&(n&&t.d(1),i())}),t.o(e)}}var Vt={duration:0};function Q(t,e,n,i){let r=e(t,n),c=i?0:1,s=null,l=null,a=null;function o(){a&&Gt(t,a)}function y(u,h){let p=u.b-c;return h*=Math.abs(p),{a:c,b:u.b,d:p,duration:h,start:u.start,end:u.start+h,group:u.group}}function f(u){let{delay:h=0,duration:p=300,easing:w=O,tick:g=_,css:v}=r||Vt,q={start:Ot()+h,b:u};u||(q.group=m,m.r+=1),s||l?l=q:(v&&(o(),a=ht(t,c,u,p,h,w,v)),u&&g(0,1),s=y(q,p),x(()=>X(t,u,"start")),Dt(E=>{if(l&&E>l.start&&(s=y(l,p),l=null,X(t,s.b,"start"),v&&(o(),a=ht(t,c,s.b,s.duration,0,w,r.css))),s){if(E>=s.end)g(c=s.b,1-c),X(t,s.b,"end"),l||(s.b?o():--s.group.r||b(s.group.c)),s=null;else if(E>=s.start){let jt=E-s.start;c=s.a+s.d*w(jt/s.duration),g(c,1-c)}}return!!(s||l)}))}return{run(u){S(r)?Wt().then(()=>{r=r(),f(u)}):f(u)},end(){o(),s=l=null}}}var ce=typeof window!="undefined"?window:typeof globalThis!="undefined"?globalThis:global;var le=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 Ut(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 wt(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 Xt(t,e){t.$$.dirty[0]===-1&&($.push(t),Rt(),t.$$.dirty.fill(0)),t.$$.dirty[e/31|0]|=1<{let p=h.length?h[0]:u;return o.ctx&&r(o.ctx[f],o.ctx[f]=p)&&(!o.skip_bound&&o.bound[f]&&o.bound[f](p),y&&Xt(t,f)),u}):[],o.update(),y=!0,b(o.before_update),o.fragment=i?i(o.ctx):!1,e.target){if(e.hydrate){At();let f=Tt(e.target);o.fragment&&o.fragment.l(f),f.forEach(A)}else o.fragment&&o.fragment.c();e.intro&&C(t.$$.fragment),Ut(t,e.target,e.anchor,e.customElement),Lt(),yt()}J(a)}var Zt;typeof HTMLElement=="function"&&(Zt=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(){wt(this,1),this.$destroy=_}$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&&!it(t)&&(this.$$.skip_bound=!0,this.$$set(t),this.$$.skip_bound=!1)}});var Y=class{$destroy(){wt(this,1),this.$destroy=_}$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&&!it(e)&&(this.$$.skip_bound=!0,this.$$set(e),this.$$.skip_bound=!1)}};var M=[];function Ft(t,e=_){let n,i=new Set;function r(l){if(D(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 H=Ft(!1);function xt(){H.set(!0)}function Mt(){H.set(!1)}function tt(t,{delay:e=0,duration:n=400,easing:i=O}={}){let r=+getComputedStyle(t).opacity;return{delay:e,duration:n,easing:i,css:c=>`opacity: ${c*r}`}}function Qt(t){ut(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
- }.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
- }.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
+}`,f=`__svelte_${qt(y)}_${l}`,u=P(t);N.add(u);let h=u.__svelte_stylesheet||(u.__svelte_stylesheet=Jt(t).sheet),p=u.__svelte_rules||(u.__svelte_rules={});p[f]||(p[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 Gt(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||Kt())}function Kt(){K(()=>{B||(N.forEach(t=>{let e=t.__svelte_stylesheet,n=e.cssRules.length;for(;n--;)e.deleteRule(n);t.__svelte_rules={}}),N.clear())})}var pt;function J(t){pt=t}var $=[];var _t=[],z=[],mt=[],Pt=Promise.resolve(),W=!1;function Rt(){W||(W=!0,Pt.then(yt))}function x(t){z.push(t)}var V=!1,U=new Set;function yt(){if(!V){V=!0;do{for(let t=0;t<$.length;t+=1){let e=$[t];J(e),Nt(e.$$)}for(J(null),$.length=0;_t.length;)_t.pop()();for(let t=0;t{k=null})),k}function X(t,e,n){t.dispatchEvent(Ht(`${e?"intro":"outro"}${n}`))}var T=new Set,m;function gt(){m={r:0,c:[],p:m}}function bt(){m.r||b(m.c),m=m.p}function C(t,e){t&&t.i&&(T.delete(t),t.i(e))}function Z(t,e,n,i){if(t&&t.o){if(T.has(t))return;T.add(t),m.c.push(()=>{T.delete(t),i&&(n&&t.d(1),i())}),t.o(e)}}var Vt={duration:0};function Q(t,e,n,i){let r=e(t,n),c=i?0:1,s=null,l=null,a=null;function o(){a&&Gt(t,a)}function y(u,h){let p=u.b-c;return h*=Math.abs(p),{a:c,b:u.b,d:p,duration:h,start:u.start,end:u.start+h,group:u.group}}function f(u){let{delay:h=0,duration:p=300,easing:w=O,tick:g=_,css:v}=r||Vt,q={start:Ot()+h,b:u};u||(q.group=m,m.r+=1),s||l?l=q:(v&&(o(),a=ht(t,c,u,p,h,w,v)),u&&g(0,1),s=y(q,p),x(()=>X(t,u,"start")),Dt(E=>{if(l&&E>l.start&&(s=y(l,p),l=null,X(t,s.b,"start"),v&&(o(),a=ht(t,c,s.b,s.duration,0,w,r.css))),s){if(E>=s.end)g(c=s.b,1-c),X(t,s.b,"end"),l||(s.b?o():--s.group.r||b(s.group.c)),s=null;else if(E>=s.start){let jt=E-s.start;c=s.a+s.d*w(jt/s.duration),g(c,1-c)}}return!!(s||l)}))}return{run(u){S(r)?Wt().then(()=>{r=r(),f(u)}):f(u)},end(){o(),s=l=null}}}var ce=typeof window!="undefined"?window:typeof globalThis!="undefined"?globalThis:global;var le=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 Ut(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 wt(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 Xt(t,e){t.$$.dirty[0]===-1&&($.push(t),Rt(),t.$$.dirty.fill(0)),t.$$.dirty[e/31|0]|=1<{let p=h.length?h[0]:u;return o.ctx&&r(o.ctx[f],o.ctx[f]=p)&&(!o.skip_bound&&o.bound[f]&&o.bound[f](p),y&&Xt(t,f)),u}):[],o.update(),y=!0,b(o.before_update),o.fragment=i?i(o.ctx):!1,e.target){if(e.hydrate){At();let f=Tt(e.target);o.fragment&&o.fragment.l(f),f.forEach(A)}else o.fragment&&o.fragment.c();e.intro&&C(t.$$.fragment),Ut(t,e.target,e.anchor,e.customElement),Lt(),yt()}J(a)}var Zt;typeof HTMLElement=="function"&&(Zt=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(){wt(this,1),this.$destroy=_}$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&&!it(t)&&(this.$$.skip_bound=!0,this.$$set(t),this.$$.skip_bound=!1)}});var Y=class{$destroy(){wt(this,1),this.$destroy=_}$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&&!it(e)&&(this.$$.skip_bound=!0,this.$$set(e),this.$$.skip_bound=!1)}};var M=[];function Ft(t,e=_){let n,i=new Set;function r(l){if(D(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 H=Ft(!1);function xt(){H.set(!0)}function Mt(){H.set(!1)}function tt(t,{delay:e=0,duration:n=400,easing:i=O}={}){let r=+getComputedStyle(t).opacity;return{delay:e,duration:n,easing:i,css:c=>`opacity: ${c*r}`}}function Qt(t){ut(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,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);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 St(t){let e,n,i;return{c(){e=L("div"),e.innerHTML='
',dt(e,"class","wails-reconnect-overlay svelte-181h7z")},m(r,c){R(r,e,c),i=!0},i(r){i||(x(()=>{n||(n=Q(e,tt,{duration:300},!0)),n.run(1)}),i=!0)},o(r){n||(n=Q(e,tt,{duration:300},!1)),n.run(0),i=!1},d(r){r&&A(e),r&&n&&n.end()}}}function Yt(t){let e,n,i=t[0]&&St(t);return{c(){i&&i.c(),e=ft()},m(r,c){i&&i.m(r,c),R(r,e,c),n=!0},p(r,[c]){r[0]?i?c&1&&C(i,1):(i=St(r),i.c(),C(i,1),i.m(e.parentNode,e)):i&&(gt(),Z(i,1,1,()=>{i=null}),bt())},i(r){n||(C(i),n=!0)},o(r){Z(i),n=!1},d(r){i&&i.d(r),r&&A(e)}}}function te(t,e,n){let i;return ot(t,H,r=>n(0,i=r)),[i]}var $t=class extends Y{constructor(e){super();vt(this,e,te,Yt,D,{},Qt)}},kt=$t;var ee={},et=null,I=[];window.WailsInvoke=t=>{if(!et){console.log("Queueing: "+t),I.push(t);return}et(t)};window.addEventListener("DOMContentLoaded",()=>{ee.overlay=new kt({target:document.body,anchor:document.querySelector("#wails-spinner")})});var d=null,Ct;window.onbeforeunload=function(){d&&(d.onclose=function(){},d.close(),d=null)};Et();function ne(){et=t=>{d.send(t)};for(let t=0;t WindowMinimise,
WindowReload: () => WindowReload,
WindowReloadApp: () => WindowReloadApp,
+ WindowSetAlwaysOnTop: () => WindowSetAlwaysOnTop,
+ WindowSetBackgroundColour: () => WindowSetBackgroundColour,
WindowSetDarkTheme: () => WindowSetDarkTheme,
WindowSetLightTheme: () => WindowSetLightTheme,
WindowSetMaxSize: () => WindowSetMaxSize,
WindowSetMinSize: () => WindowSetMinSize,
WindowSetPosition: () => WindowSetPosition,
- WindowSetRGBA: () => WindowSetRGBA,
WindowSetSize: () => WindowSetSize,
WindowSetSystemDefaultTheme: () => WindowSetSystemDefaultTheme,
WindowSetTitle: () => WindowSetTitle,
@@ -290,6 +291,9 @@
function WindowSetMinSize(width, height) {
window.WailsInvoke("Wz:" + width + ":" + height);
}
+ function WindowSetAlwaysOnTop(b) {
+ window.WailsInvoke("WATP:" + (b ? "1" : "0"));
+ }
function WindowSetPosition(x, y) {
window.WailsInvoke("Wp:" + x + ":" + y);
}
@@ -305,20 +309,25 @@
function WindowMaximise() {
window.WailsInvoke("WM");
}
+
function WindowToggleMaximise() {
window.WailsInvoke("Wt");
}
+
function WindowUnmaximise() {
window.WailsInvoke("WU");
}
+
function WindowMinimise() {
window.WailsInvoke("Wm");
}
+
function WindowUnminimise() {
window.WailsInvoke("Wu");
}
- function WindowSetRGBA(R, G, B, A) {
- let rgba = JSON.stringify({ r: R || 0, g: G || 0, b: B || 0, a: A || 255 });
+
+ function WindowSetBackgroundColour(R, G, B, A) {
+ let rgba = JSON.stringify({r: R || 0, g: G || 0, b: B || 0, a: A || 255});
window.WailsInvoke("Wr:" + rgba);
}
@@ -327,6 +336,7 @@
__export(browser_exports, {
BrowserOpenURL: () => BrowserOpenURL
});
+
function BrowserOpenURL(url) {
window.WailsInvoke("BO:" + url);
}
@@ -446,4 +456,4 @@
}
});
})();
-//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiZGVza3RvcC9sb2cuanMiLCAiZGVza3RvcC9ldmVudHMuanMiLCAiZGVza3RvcC9jYWxscy5qcyIsICJkZXNrdG9wL2JpbmRpbmdzLmpzIiwgImRlc2t0b3Avd2luZG93LmpzIiwgImRlc2t0b3AvYnJvd3Nlci5qcyIsICJkZXNrdG9wL21haW4uanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qXG4gXyAgICAgICBfXyAgICAgIF8gX19cbnwgfCAgICAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA2ICovXG5cbi8qKlxuICogU2VuZHMgYSBsb2cgbWVzc2FnZSB0byB0aGUgYmFja2VuZCB3aXRoIHRoZSBnaXZlbiBsZXZlbCArIG1lc3NhZ2VcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbGV2ZWxcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmZ1bmN0aW9uIHNlbmRMb2dNZXNzYWdlKGxldmVsLCBtZXNzYWdlKSB7XG5cblx0Ly8gTG9nIE1lc3NhZ2UgZm9ybWF0OlxuXHQvLyBsW3R5cGVdW21lc3NhZ2VdXG5cdHdpbmRvdy5XYWlsc0ludm9rZSgnTCcgKyBsZXZlbCArIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIExvZyB0aGUgZ2l2ZW4gdHJhY2UgbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIExvZ1RyYWNlKG1lc3NhZ2UpIHtcblx0c2VuZExvZ01lc3NhZ2UoJ1QnLCBtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBMb2cgdGhlIGdpdmVuIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dQcmludChtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdQJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiBkZWJ1ZyBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nRGVidWcobWVzc2FnZSkge1xuXHRzZW5kTG9nTWVzc2FnZSgnRCcsIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIExvZyB0aGUgZ2l2ZW4gaW5mbyBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nSW5mbyhtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdJJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiB3YXJuaW5nIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dXYXJuaW5nKG1lc3NhZ2UpIHtcblx0c2VuZExvZ01lc3NhZ2UoJ1cnLCBtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBMb2cgdGhlIGdpdmVuIGVycm9yIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dFcnJvcihtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdFJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiBmYXRhbCBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nRmF0YWwobWVzc2FnZSkge1xuXHRzZW5kTG9nTWVzc2FnZSgnRicsIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIExvZyBsZXZlbCB0byB0aGUgZ2l2ZW4gbG9nIGxldmVsXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtudW1iZXJ9IGxvZ2xldmVsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRMb2dMZXZlbChsb2dsZXZlbCkge1xuXHRzZW5kTG9nTWVzc2FnZSgnUycsIGxvZ2xldmVsKTtcbn1cblxuLy8gTG9nIGxldmVsc1xuZXhwb3J0IGNvbnN0IExvZ0xldmVsID0ge1xuXHRUUkFDRTogMSxcblx0REVCVUc6IDIsXG5cdElORk86IDMsXG5cdFdBUk5JTkc6IDQsXG5cdEVSUk9SOiA1LFxufTtcbiIsICIvKlxuIF8gICAgICAgX18gICAgICBfIF9fXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cbi8qIGpzaGludCBlc3ZlcnNpb246IDYgKi9cblxuLy8gRGVmaW5lcyBhIHNpbmdsZSBsaXN0ZW5lciB3aXRoIGEgbWF4aW11bSBudW1iZXIgb2YgdGltZXMgdG8gY2FsbGJhY2tcblxuLyoqXG4gKiBUaGUgTGlzdGVuZXIgY2xhc3MgZGVmaW5lcyBhIGxpc3RlbmVyISA6LSlcbiAqXG4gKiBAY2xhc3MgTGlzdGVuZXJcbiAqL1xuY2xhc3MgTGlzdGVuZXIge1xuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgTGlzdGVuZXIuXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbWF4Q2FsbGJhY2tzXG4gICAgICogQG1lbWJlcm9mIExpc3RlbmVyXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoY2FsbGJhY2ssIG1heENhbGxiYWNrcykge1xuICAgICAgICAvLyBEZWZhdWx0IG9mIC0xIG1lYW5zIGluZmluaXRlXG4gICAgICAgIG1heENhbGxiYWNrcyA9IG1heENhbGxiYWNrcyB8fCAtMTtcbiAgICAgICAgLy8gQ2FsbGJhY2sgaW52b2tlcyB0aGUgY2FsbGJhY2sgd2l0aCB0aGUgZ2l2ZW4gZGF0YVxuICAgICAgICAvLyBSZXR1cm5zIHRydWUgaWYgdGhpcyBsaXN0ZW5lciBzaG91bGQgYmUgZGVzdHJveWVkXG4gICAgICAgIHRoaXMuQ2FsbGJhY2sgPSAoZGF0YSkgPT4ge1xuICAgICAgICAgICAgY2FsbGJhY2suYXBwbHkobnVsbCwgZGF0YSk7XG4gICAgICAgICAgICAvLyBJZiBtYXhDYWxsYmFja3MgaXMgaW5maW5pdGUsIHJldHVybiBmYWxzZSAoZG8gbm90IGRlc3Ryb3kpXG4gICAgICAgICAgICBpZiAobWF4Q2FsbGJhY2tzID09PSAtMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIERlY3JlbWVudCBtYXhDYWxsYmFja3MuIFJldHVybiB0cnVlIGlmIG5vdyAwLCBvdGhlcndpc2UgZmFsc2VcbiAgICAgICAgICAgIG1heENhbGxiYWNrcyAtPSAxO1xuICAgICAgICAgICAgcmV0dXJuIG1heENhbGxiYWNrcyA9PT0gMDtcbiAgICAgICAgfTtcbiAgICB9XG59XG5cbmV4cG9ydCBjb25zdCBldmVudExpc3RlbmVycyA9IHt9O1xuXG4vKipcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBgbWF4Q2FsbGJhY2tzYCB0aW1lcyBiZWZvcmUgYmVpbmcgZGVzdHJveWVkXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhDYWxsYmFja3NcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEV2ZW50c09uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgbWF4Q2FsbGJhY2tzKSB7XG4gICAgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0gfHwgW107XG4gICAgY29uc3QgdGhpc0xpc3RlbmVyID0gbmV3IExpc3RlbmVyKGNhbGxiYWNrLCBtYXhDYWxsYmFja3MpO1xuICAgIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0ucHVzaCh0aGlzTGlzdGVuZXIpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBldmVyeSB0aW1lIHRoZSBldmVudCBpcyBlbWl0dGVkXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEV2ZW50c09uKGV2ZW50TmFtZSwgY2FsbGJhY2spIHtcbiAgICBFdmVudHNPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIC0xKTtcbn1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYW4gZXZlbnQgbGlzdGVuZXIgdGhhdCB3aWxsIGJlIGludm9rZWQgb25jZSB0aGVuIGRlc3Ryb3llZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbmNlKGV2ZW50TmFtZSwgY2FsbGJhY2spIHtcbiAgICBFdmVudHNPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIDEpO1xufVxuXG5mdW5jdGlvbiBub3RpZnlMaXN0ZW5lcnMoZXZlbnREYXRhKSB7XG5cbiAgICAvLyBHZXQgdGhlIGV2ZW50IG5hbWVcbiAgICBsZXQgZXZlbnROYW1lID0gZXZlbnREYXRhLm5hbWU7XG5cbiAgICAvLyBDaGVjayBpZiB3ZSBoYXZlIGFueSBsaXN0ZW5lcnMgZm9yIHRoaXMgZXZlbnRcbiAgICBpZiAoZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSkge1xuXG4gICAgICAgIC8vIEtlZXAgYSBsaXN0IG9mIGxpc3RlbmVyIGluZGV4ZXMgdG8gZGVzdHJveVxuICAgICAgICBjb25zdCBuZXdFdmVudExpc3RlbmVyTGlzdCA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0uc2xpY2UoKTtcblxuICAgICAgICAvLyBJdGVyYXRlIGxpc3RlbmVyc1xuICAgICAgICBmb3IgKGxldCBjb3VudCA9IDA7IGNvdW50IDwgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXS5sZW5ndGg7IGNvdW50ICs9IDEpIHtcblxuICAgICAgICAgICAgLy8gR2V0IG5leHQgbGlzdGVuZXJcbiAgICAgICAgICAgIGNvbnN0IGxpc3RlbmVyID0gZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXVtjb3VudF07XG5cbiAgICAgICAgICAgIGxldCBkYXRhID0gZXZlbnREYXRhLmRhdGE7XG5cbiAgICAgICAgICAgIC8vIERvIHRoZSBjYWxsYmFja1xuICAgICAgICAgICAgY29uc3QgZGVzdHJveSA9IGxpc3RlbmVyLkNhbGxiYWNrKGRhdGEpO1xuICAgICAgICAgICAgaWYgKGRlc3Ryb3kpIHtcbiAgICAgICAgICAgICAgICAvLyBpZiB0aGUgbGlzdGVuZXIgaW5kaWNhdGVkIHRvIGRlc3Ryb3kgaXRzZWxmLCBhZGQgaXQgdG8gdGhlIGRlc3Ryb3kgbGlzdFxuICAgICAgICAgICAgICAgIG5ld0V2ZW50TGlzdGVuZXJMaXN0LnNwbGljZShjb3VudCwgMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBVcGRhdGUgY2FsbGJhY2tzIHdpdGggbmV3IGxpc3Qgb2YgbGlzdGVuZXJzXG4gICAgICAgIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0gPSBuZXdFdmVudExpc3RlbmVyTGlzdDtcbiAgICB9XG59XG5cbi8qKlxuICogTm90aWZ5IGluZm9ybXMgZnJvbnRlbmQgbGlzdGVuZXJzIHRoYXQgYW4gZXZlbnQgd2FzIGVtaXR0ZWQgd2l0aCB0aGUgZ2l2ZW4gZGF0YVxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBub3RpZnlNZXNzYWdlIC0gZW5jb2RlZCBub3RpZmljYXRpb24gbWVzc2FnZVxuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNOb3RpZnkobm90aWZ5TWVzc2FnZSkge1xuICAgIC8vIFBhcnNlIHRoZSBtZXNzYWdlXG4gICAgbGV0IG1lc3NhZ2U7XG4gICAgdHJ5IHtcbiAgICAgICAgbWVzc2FnZSA9IEpTT04ucGFyc2Uobm90aWZ5TWVzc2FnZSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zdCBlcnJvciA9ICdJbnZhbGlkIEpTT04gcGFzc2VkIHRvIE5vdGlmeTogJyArIG5vdGlmeU1lc3NhZ2U7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvcik7XG4gICAgfVxuICAgIG5vdGlmeUxpc3RlbmVycyhtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBFbWl0IGFuIGV2ZW50IHdpdGggdGhlIGdpdmVuIG5hbWUgYW5kIGRhdGFcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNFbWl0KGV2ZW50TmFtZSkge1xuXG4gICAgY29uc3QgcGF5bG9hZCA9IHtcbiAgICAgICAgbmFtZTogZXZlbnROYW1lLFxuICAgICAgICBkYXRhOiBbXS5zbGljZS5hcHBseShhcmd1bWVudHMpLnNsaWNlKDEpLFxuICAgIH07XG5cbiAgICAvLyBOb3RpZnkgSlMgbGlzdGVuZXJzXG4gICAgbm90aWZ5TGlzdGVuZXJzKHBheWxvYWQpO1xuXG4gICAgLy8gTm90aWZ5IEdvIGxpc3RlbmVyc1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnRUUnICsgSlNPTi5zdHJpbmdpZnkocGF5bG9hZCkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzT2ZmKGV2ZW50TmFtZSkge1xuICAgIC8vIFJlbW92ZSBsb2NhbCBsaXN0ZW5lcnNcbiAgICBkZWxldGUgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXTtcblxuICAgIC8vIE5vdGlmeSBHbyBsaXN0ZW5lcnNcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ0VYJyArIGV2ZW50TmFtZSk7XG59IiwgIi8qXG4gXyAgICAgICBfXyAgICAgIF8gX19cbnwgfCAgICAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuLyoganNoaW50IGVzdmVyc2lvbjogNiAqL1xuXG5leHBvcnQgY29uc3QgY2FsbGJhY2tzID0ge307XG5cbi8qKlxuICogUmV0dXJucyBhIG51bWJlciBmcm9tIHRoZSBuYXRpdmUgYnJvd3NlciByYW5kb20gZnVuY3Rpb25cbiAqXG4gKiBAcmV0dXJucyBudW1iZXJcbiAqL1xuZnVuY3Rpb24gY3J5cHRvUmFuZG9tKCkge1xuXHR2YXIgYXJyYXkgPSBuZXcgVWludDMyQXJyYXkoMSk7XG5cdHJldHVybiB3aW5kb3cuY3J5cHRvLmdldFJhbmRvbVZhbHVlcyhhcnJheSlbMF07XG59XG5cbi8qKlxuICogUmV0dXJucyBhIG51bWJlciB1c2luZyBkYSBvbGQtc2tvb2wgTWF0aC5SYW5kb21cbiAqIEkgbGlrZXMgdG8gY2FsbCBpdCBMT0xSYW5kb21cbiAqXG4gKiBAcmV0dXJucyBudW1iZXJcbiAqL1xuZnVuY3Rpb24gYmFzaWNSYW5kb20oKSB7XG5cdHJldHVybiBNYXRoLnJhbmRvbSgpICogOTAwNzE5OTI1NDc0MDk5MTtcbn1cblxuLy8gUGljayBhIHJhbmRvbSBudW1iZXIgZnVuY3Rpb24gYmFzZWQgb24gYnJvd3NlciBjYXBhYmlsaXR5XG52YXIgcmFuZG9tRnVuYztcbmlmICh3aW5kb3cuY3J5cHRvKSB7XG5cdHJhbmRvbUZ1bmMgPSBjcnlwdG9SYW5kb207XG59IGVsc2Uge1xuXHRyYW5kb21GdW5jID0gYmFzaWNSYW5kb207XG59XG5cblxuLyoqXG4gKiBDYWxsIHNlbmRzIGEgbWVzc2FnZSB0byB0aGUgYmFja2VuZCB0byBjYWxsIHRoZSBiaW5kaW5nIHdpdGggdGhlXG4gKiBnaXZlbiBkYXRhLiBBIHByb21pc2UgaXMgcmV0dXJuZWQgYW5kIHdpbGwgYmUgY29tcGxldGVkIHdoZW4gdGhlXG4gKiBiYWNrZW5kIHJlc3BvbmRzLiBUaGlzIHdpbGwgYmUgcmVzb2x2ZWQgd2hlbiB0aGUgY2FsbCB3YXMgc3VjY2Vzc2Z1bFxuICogb3IgcmVqZWN0ZWQgaWYgYW4gZXJyb3IgaXMgcGFzc2VkIGJhY2suXG4gKiBUaGVyZSBpcyBhIHRpbWVvdXQgbWVjaGFuaXNtLiBJZiB0aGUgY2FsbCBkb2Vzbid0IHJlc3BvbmQgaW4gdGhlIGdpdmVuXG4gKiB0aW1lIChpbiBtaWxsaXNlY29uZHMpIHRoZW4gdGhlIHByb21pc2UgaXMgcmVqZWN0ZWQuXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqIEBwYXJhbSB7YW55PX0gYXJnc1xuICogQHBhcmFtIHtudW1iZXI9fSB0aW1lb3V0XG4gKiBAcmV0dXJuc1xuICovXG5leHBvcnQgZnVuY3Rpb24gQ2FsbChuYW1lLCBhcmdzLCB0aW1lb3V0KSB7XG5cblx0Ly8gVGltZW91dCBpbmZpbml0ZSBieSBkZWZhdWx0XG5cdGlmICh0aW1lb3V0ID09IG51bGwpIHtcblx0XHR0aW1lb3V0ID0gMDtcblx0fVxuXG5cdC8vIENyZWF0ZSBhIHByb21pc2Vcblx0cmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcblxuXHRcdC8vIENyZWF0ZSBhIHVuaXF1ZSBjYWxsYmFja0lEXG5cdFx0dmFyIGNhbGxiYWNrSUQ7XG5cdFx0ZG8ge1xuXHRcdFx0Y2FsbGJhY2tJRCA9IG5hbWUgKyAnLScgKyByYW5kb21GdW5jKCk7XG5cdFx0fSB3aGlsZSAoY2FsbGJhY2tzW2NhbGxiYWNrSURdKTtcblxuXHRcdHZhciB0aW1lb3V0SGFuZGxlO1xuXHRcdC8vIFNldCB0aW1lb3V0XG5cdFx0aWYgKHRpbWVvdXQgPiAwKSB7XG5cdFx0XHR0aW1lb3V0SGFuZGxlID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdHJlamVjdChFcnJvcignQ2FsbCB0byAnICsgbmFtZSArICcgdGltZWQgb3V0LiBSZXF1ZXN0IElEOiAnICsgY2FsbGJhY2tJRCkpO1xuXHRcdFx0fSwgdGltZW91dCk7XG5cdFx0fVxuXG5cdFx0Ly8gU3RvcmUgY2FsbGJhY2tcblx0XHRjYWxsYmFja3NbY2FsbGJhY2tJRF0gPSB7XG5cdFx0XHR0aW1lb3V0SGFuZGxlOiB0aW1lb3V0SGFuZGxlLFxuXHRcdFx0cmVqZWN0OiByZWplY3QsXG5cdFx0XHRyZXNvbHZlOiByZXNvbHZlXG5cdFx0fTtcblxuXHRcdHRyeSB7XG5cdFx0XHRjb25zdCBwYXlsb2FkID0ge1xuXHRcdFx0XHRuYW1lLFxuXHRcdFx0XHRhcmdzLFxuXHRcdFx0XHRjYWxsYmFja0lELFxuXHRcdFx0fTtcblxuXHRcdFx0Ly8gTWFrZSB0aGUgY2FsbFxuXHRcdFx0d2luZG93LldhaWxzSW52b2tlKCdDJyArIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcblx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcblx0XHRcdGNvbnNvbGUuZXJyb3IoZSk7XG5cdFx0fVxuXHR9KTtcbn1cblxuXG5cbi8qKlxuICogQ2FsbGVkIGJ5IHRoZSBiYWNrZW5kIHRvIHJldHVybiBkYXRhIHRvIGEgcHJldmlvdXNseSBjYWxsZWRcbiAqIGJpbmRpbmcgaW52b2NhdGlvblxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBpbmNvbWluZ01lc3NhZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENhbGxiYWNrKGluY29taW5nTWVzc2FnZSkge1xuXHQvLyBQYXJzZSB0aGUgbWVzc2FnZVxuXHRsZXQgbWVzc2FnZTtcblx0dHJ5IHtcblx0XHRtZXNzYWdlID0gSlNPTi5wYXJzZShpbmNvbWluZ01lc3NhZ2UpO1xuXHR9IGNhdGNoIChlKSB7XG5cdFx0Y29uc3QgZXJyb3IgPSBgSW52YWxpZCBKU09OIHBhc3NlZCB0byBjYWxsYmFjazogJHtlLm1lc3NhZ2V9LiBNZXNzYWdlOiAke2luY29taW5nTWVzc2FnZX1gO1xuXHRcdHJ1bnRpbWUuTG9nRGVidWcoZXJyb3IpO1xuXHRcdHRocm93IG5ldyBFcnJvcihlcnJvcik7XG5cdH1cblx0bGV0IGNhbGxiYWNrSUQgPSBtZXNzYWdlLmNhbGxiYWNraWQ7XG5cdGxldCBjYWxsYmFja0RhdGEgPSBjYWxsYmFja3NbY2FsbGJhY2tJRF07XG5cdGlmICghY2FsbGJhY2tEYXRhKSB7XG5cdFx0Y29uc3QgZXJyb3IgPSBgQ2FsbGJhY2sgJyR7Y2FsbGJhY2tJRH0nIG5vdCByZWdpc3RlcmVkISEhYDtcblx0XHRjb25zb2xlLmVycm9yKGVycm9yKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHRcdHRocm93IG5ldyBFcnJvcihlcnJvcik7XG5cdH1cblx0Y2xlYXJUaW1lb3V0KGNhbGxiYWNrRGF0YS50aW1lb3V0SGFuZGxlKTtcblxuXHRkZWxldGUgY2FsbGJhY2tzW2NhbGxiYWNrSURdO1xuXG5cdGlmIChtZXNzYWdlLmVycm9yKSB7XG5cdFx0Y2FsbGJhY2tEYXRhLnJlamVjdChtZXNzYWdlLmVycm9yKTtcblx0fSBlbHNlIHtcblx0XHRjYWxsYmFja0RhdGEucmVzb2x2ZShtZXNzYWdlLnJlc3VsdCk7XG5cdH1cbn1cbiIsICIvKlxuIF8gICAgICAgX18gICAgICBfIF9fICAgIFxufCB8ICAgICAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApIFxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vICBcblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA2ICovXG5cbmltcG9ydCB7Q2FsbH0gZnJvbSAnLi9jYWxscyc7XG5cbi8vIFRoaXMgaXMgd2hlcmUgd2UgYmluZCBnbyBtZXRob2Qgd3JhcHBlcnNcbndpbmRvdy5nbyA9IHt9O1xuXG5leHBvcnQgZnVuY3Rpb24gU2V0QmluZGluZ3MoYmluZGluZ3NNYXApIHtcblx0dHJ5IHtcblx0XHRiaW5kaW5nc01hcCA9IEpTT04ucGFyc2UoYmluZGluZ3NNYXApO1xuXHR9IGNhdGNoIChlKSB7XG5cdFx0Y29uc29sZS5lcnJvcihlKTtcblx0fVxuXG5cdC8vIEluaXRpYWxpc2UgdGhlIGJpbmRpbmdzIG1hcFxuXHR3aW5kb3cuZ28gPSB3aW5kb3cuZ28gfHwge307XG5cblx0Ly8gSXRlcmF0ZSBwYWNrYWdlIG5hbWVzXG5cdE9iamVjdC5rZXlzKGJpbmRpbmdzTWFwKS5mb3JFYWNoKChwYWNrYWdlTmFtZSkgPT4ge1xuXG5cdFx0Ly8gQ3JlYXRlIGlubmVyIG1hcCBpZiBpdCBkb2Vzbid0IGV4aXN0XG5cdFx0d2luZG93LmdvW3BhY2thZ2VOYW1lXSA9IHdpbmRvdy5nb1twYWNrYWdlTmFtZV0gfHwge307XG5cblx0XHQvLyBJdGVyYXRlIHN0cnVjdCBuYW1lc1xuXHRcdE9iamVjdC5rZXlzKGJpbmRpbmdzTWFwW3BhY2thZ2VOYW1lXSkuZm9yRWFjaCgoc3RydWN0TmFtZSkgPT4ge1xuXG5cdFx0XHQvLyBDcmVhdGUgaW5uZXIgbWFwIGlmIGl0IGRvZXNuJ3QgZXhpc3Rcblx0XHRcdHdpbmRvdy5nb1twYWNrYWdlTmFtZV1bc3RydWN0TmFtZV0gPSB3aW5kb3cuZ29bcGFja2FnZU5hbWVdW3N0cnVjdE5hbWVdIHx8IHt9O1xuXG5cdFx0XHRPYmplY3Qua2V5cyhiaW5kaW5nc01hcFtwYWNrYWdlTmFtZV1bc3RydWN0TmFtZV0pLmZvckVhY2goKG1ldGhvZE5hbWUpID0+IHtcblxuXHRcdFx0XHR3aW5kb3cuZ29bcGFja2FnZU5hbWVdW3N0cnVjdE5hbWVdW21ldGhvZE5hbWVdID0gZnVuY3Rpb24gKCkge1xuXG5cdFx0XHRcdFx0Ly8gTm8gdGltZW91dCBieSBkZWZhdWx0XG5cdFx0XHRcdFx0bGV0IHRpbWVvdXQgPSAwO1xuXG5cdFx0XHRcdFx0Ly8gQWN0dWFsIGZ1bmN0aW9uXG5cdFx0XHRcdFx0ZnVuY3Rpb24gZHluYW1pYygpIHtcblx0XHRcdFx0XHRcdGNvbnN0IGFyZ3MgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cyk7XG5cdFx0XHRcdFx0XHRyZXR1cm4gQ2FsbChbcGFja2FnZU5hbWUsIHN0cnVjdE5hbWUsIG1ldGhvZE5hbWVdLmpvaW4oJy4nKSwgYXJncywgdGltZW91dCk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gQWxsb3cgc2V0dGluZyB0aW1lb3V0IHRvIGZ1bmN0aW9uXG5cdFx0XHRcdFx0ZHluYW1pYy5zZXRUaW1lb3V0ID0gZnVuY3Rpb24gKG5ld1RpbWVvdXQpIHtcblx0XHRcdFx0XHRcdHRpbWVvdXQgPSBuZXdUaW1lb3V0O1xuXHRcdFx0XHRcdH07XG5cblx0XHRcdFx0XHQvLyBBbGxvdyBnZXR0aW5nIHRpbWVvdXQgdG8gZnVuY3Rpb25cblx0XHRcdFx0XHRkeW5hbWljLmdldFRpbWVvdXQgPSBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gdGltZW91dDtcblx0XHRcdFx0XHR9O1xuXG5cdFx0XHRcdFx0cmV0dXJuIGR5bmFtaWM7XG5cdFx0XHRcdH0oKTtcblx0XHRcdH0pO1xuXHRcdH0pO1xuXHR9KTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG5cbmltcG9ydCB7Q2FsbH0gZnJvbSBcIi4vY2FsbHNcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1JlbG9hZCgpIHtcbiAgICB3aW5kb3cubG9jYXRpb24ucmVsb2FkKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dSZWxvYWRBcHAoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXUicpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0U3lzdGVtRGVmYXVsdFRoZW1lKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0FTRFQnKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldExpZ2h0VGhlbWUoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXQUxUJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXREYXJrVGhlbWUoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXQURUJyk7XG59XG5cbi8qKlxuICogUGxhY2UgdGhlIHdpbmRvdyBpbiB0aGUgY2VudGVyIG9mIHRoZSBzY3JlZW5cbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dDZW50ZXIoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXYycpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIHdpbmRvdyB0aXRsZVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB0aXRsZVxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0VGl0bGUodGl0bGUpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dUJyArIHRpdGxlKTtcbn1cblxuLyoqXG4gKiBNYWtlcyB0aGUgd2luZG93IGdvIGZ1bGxzY3JlZW5cbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dGdWxsc2NyZWVuKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0YnKTtcbn1cblxuLyoqXG4gKiBSZXZlcnRzIHRoZSB3aW5kb3cgZnJvbSBmdWxsc2NyZWVuXG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93VW5mdWxsc2NyZWVuKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV2YnKTtcbn1cblxuLyoqXG4gKiBTZXQgdGhlIFNpemUgb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aFxuICogQHBhcmFtIHtudW1iZXJ9IGhlaWdodFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0U2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXczonICsgd2lkdGggKyAnOicgKyBoZWlnaHQpO1xufVxuXG4vKipcbiAqIEdldCB0aGUgU2l6ZSBvZiB0aGUgd2luZG93XG4gKlxuICogQGV4cG9ydFxuICogQHJldHVybiB7UHJvbWlzZTx7dzogbnVtYmVyLCBoOiBudW1iZXJ9Pn0gVGhlIHNpemUgb2YgdGhlIHdpbmRvd1xuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dHZXRTaXplKCkge1xuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOldpbmRvd0dldFNpemVcIik7XG59XG5cbi8qKlxuICogU2V0IHRoZSBtYXhpbXVtIHNpemUgb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aFxuICogQHBhcmFtIHtudW1iZXJ9IGhlaWdodFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0TWF4U2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXWjonICsgd2lkdGggKyAnOicgKyBoZWlnaHQpO1xufVxuXG4vKipcbiAqIFNldCB0aGUgbWluaW11bSBzaXplIG9mIHRoZSB3aW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge251bWJlcn0gd2lkdGhcbiAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldE1pblNpemUod2lkdGgsIGhlaWdodCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3o6JyArIHdpZHRoICsgJzonICsgaGVpZ2h0KTtcbn1cblxuLyoqXG4gKiBTZXQgdGhlIFBvc2l0aW9uIG9mIHRoZSB3aW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge251bWJlcn0geFxuICogQHBhcmFtIHtudW1iZXJ9IHlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldFBvc2l0aW9uKHgsIHkpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dwOicgKyB4ICsgJzonICsgeSk7XG59XG5cbi8qKlxuICogR2V0IHRoZSBQb3NpdGlvbiBvZiB0aGUgd2luZG93XG4gKlxuICogQGV4cG9ydFxuICogQHJldHVybiB7UHJvbWlzZTx7eDogbnVtYmVyLCB5OiBudW1iZXJ9Pn0gVGhlIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3dcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0dldFBvc2l0aW9uKCkge1xuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOldpbmRvd0dldFBvc1wiKTtcbn1cblxuLyoqXG4gKiBIaWRlIHRoZSBXaW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dIaWRlKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0gnKTtcbn1cblxuLyoqXG4gKiBTaG93IHRoZSBXaW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTaG93KCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV1MnKTtcbn1cblxuLyoqXG4gKiBNYXhpbWlzZSB0aGUgV2luZG93XG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93TWF4aW1pc2UoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXTScpO1xufVxuXG4vKipcbiAqIFRvZ2dsZSB0aGUgTWF4aW1pc2Ugb2YgdGhlIFdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1RvZ2dsZU1heGltaXNlKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3QnKTtcbn1cblxuLyoqXG4gKiBVbm1heGltaXNlIHRoZSBXaW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dVbm1heGltaXNlKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV1UnKTtcbn1cblxuLyoqXG4gKiBNaW5pbWlzZSB0aGUgV2luZG93XG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93TWluaW1pc2UoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXbScpO1xufVxuXG4vKipcbiAqIFVubWluaW1pc2UgdGhlIFdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1VubWluaW1pc2UoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXdScpO1xufVxuXG5cbi8qKlxuICogU2V0cyB0aGUgYmFja2dyb3VuZCBjb2xvdXIgb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7bnVtYmVyfSBSIFJlZFxuICogQHBhcmFtIHtudW1iZXJ9IEcgR3JlZW5cbiAqIEBwYXJhbSB7bnVtYmVyfSBCIEJsdWVcbiAqIEBwYXJhbSB7bnVtYmVyfSBBIEFscGhhXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRSR0JBKFIsIEcsIEIsIEEpIHtcbiAgICBsZXQgcmdiYSA9IEpTT04uc3RyaW5naWZ5KHtyOiBSIHx8IDAsIGc6IEcgfHwgMCwgYjogQiB8fCAwLCBhOiBBIHx8IDI1NX0pO1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3I6JyArIHJnYmEpO1xufVxuXG4iLCAiLyoqXG4gKiBAZGVzY3JpcHRpb246IFVzZSB0aGUgc3lzdGVtIGRlZmF1bHQgYnJvd3NlciB0byBvcGVuIHRoZSB1cmxcbiAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gQnJvd3Nlck9wZW5VUkwodXJsKSB7XG4gIHdpbmRvdy5XYWlsc0ludm9rZSgnQk86JyArIHVybCk7XG59IiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuaW1wb3J0ICogYXMgTG9nIGZyb20gJy4vbG9nJztcbmltcG9ydCB7ZXZlbnRMaXN0ZW5lcnMsIEV2ZW50c0VtaXQsIEV2ZW50c05vdGlmeSwgRXZlbnRzT2ZmLCBFdmVudHNPbiwgRXZlbnRzT25jZSwgRXZlbnRzT25NdWx0aXBsZX0gZnJvbSAnLi9ldmVudHMnO1xuaW1wb3J0IHtDYWxsLCBDYWxsYmFjaywgY2FsbGJhY2tzfSBmcm9tICcuL2NhbGxzJztcbmltcG9ydCB7U2V0QmluZGluZ3N9IGZyb20gXCIuL2JpbmRpbmdzXCI7XG5pbXBvcnQgKiBhcyBXaW5kb3cgZnJvbSBcIi4vd2luZG93XCI7XG5pbXBvcnQgKiBhcyBCcm93c2VyIGZyb20gXCIuL2Jyb3dzZXJcIjtcblxuXG5leHBvcnQgZnVuY3Rpb24gUXVpdCgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1EnKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIEVudmlyb25tZW50KCkge1xuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOkVudmlyb25tZW50XCIpO1xufVxuXG4vLyBUaGUgSlMgcnVudGltZVxud2luZG93LnJ1bnRpbWUgPSB7XG4gICAgLi4uTG9nLFxuICAgIC4uLldpbmRvdyxcbiAgICAuLi5Ccm93c2VyLFxuICAgIEV2ZW50c09uLFxuICAgIEV2ZW50c09uY2UsXG4gICAgRXZlbnRzT25NdWx0aXBsZSxcbiAgICBFdmVudHNFbWl0LFxuICAgIEV2ZW50c09mZixcbiAgICBFbnZpcm9ubWVudCxcbiAgICBRdWl0XG59O1xuXG4vLyBJbnRlcm5hbCB3YWlscyBlbmRwb2ludHNcbndpbmRvdy53YWlscyA9IHtcbiAgICBDYWxsYmFjayxcbiAgICBFdmVudHNOb3RpZnksXG4gICAgU2V0QmluZGluZ3MsXG4gICAgZXZlbnRMaXN0ZW5lcnMsXG4gICAgY2FsbGJhY2tzLFxuICAgIGZsYWdzOiB7XG4gICAgICAgIGRpc2FibGVTY3JvbGxiYXJEcmFnOiBmYWxzZSxcbiAgICAgICAgZGlzYWJsZVdhaWxzRGVmYXVsdENvbnRleHRNZW51OiBmYWxzZSxcbiAgICAgICAgZW5hYmxlUmVzaXplOiBmYWxzZSxcbiAgICAgICAgZGVmYXVsdEN1cnNvcjogbnVsbCxcbiAgICAgICAgYm9yZGVyVGhpY2tuZXNzOiA2LFxuICAgICAgICBkYkNsaWNrSW50ZXJ2YWw6IDEwMCxcbiAgICB9XG59O1xuXG4vLyBTZXQgdGhlIGJpbmRpbmdzXG53aW5kb3cud2FpbHMuU2V0QmluZGluZ3Mod2luZG93LndhaWxzYmluZGluZ3MpO1xuZGVsZXRlIHdpbmRvdy53YWlscy5TZXRCaW5kaW5ncztcblxuLy8gVGhpcyBpcyBldmFsdWF0ZWQgYXQgYnVpbGQgdGltZSBpbiBwYWNrYWdlLmpzb25cbi8vIGNvbnN0IGRldiA9IDA7XG4vLyBjb25zdCBwcm9kdWN0aW9uID0gMTtcbmlmIChFTlYgPT09IDApIHtcbiAgICBkZWxldGUgd2luZG93LndhaWxzYmluZGluZ3M7XG59XG5cbnZhciBkcmFnVGltZU91dDtcbnZhciBkcmFnTGFzdFRpbWUgPSAwO1xuXG5mdW5jdGlvbiBkcmFnKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZShcImRyYWdcIik7XG59XG5cbi8vIFNldHVwIGRyYWcgaGFuZGxlclxuLy8gQmFzZWQgb24gY29kZSBmcm9tOiBodHRwczovL2dpdGh1Yi5jb20vcGF0cjBudXMvRGVza0dhcFxud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIChlKSA9PiB7XG5cbiAgICAvLyBDaGVjayBmb3IgcmVzaXppbmdcbiAgICBpZiAod2luZG93LndhaWxzLmZsYWdzLnJlc2l6ZUVkZ2UpIHtcbiAgICAgICAgd2luZG93LldhaWxzSW52b2tlKFwicmVzaXplOlwiICsgd2luZG93LndhaWxzLmZsYWdzLnJlc2l6ZUVkZ2UpO1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBDaGVjayBmb3IgZHJhZ2dpbmdcbiAgICBsZXQgY3VycmVudEVsZW1lbnQgPSBlLnRhcmdldDtcbiAgICB3aGlsZSAoY3VycmVudEVsZW1lbnQgIT0gbnVsbCkge1xuICAgICAgICBpZiAoY3VycmVudEVsZW1lbnQuaGFzQXR0cmlidXRlKCdkYXRhLXdhaWxzLW5vLWRyYWcnKSkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEVsZW1lbnQuaGFzQXR0cmlidXRlKCdkYXRhLXdhaWxzLWRyYWcnKSkge1xuICAgICAgICAgICAgaWYgKHdpbmRvdy53YWlscy5mbGFncy5kaXNhYmxlU2Nyb2xsYmFyRHJhZykge1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgY2hlY2tzIGZvciBjbGlja3Mgb24gdGhlIHNjcm9sbCBiYXJcbiAgICAgICAgICAgICAgICBpZiAoZS5vZmZzZXRYID4gZS50YXJnZXQuY2xpZW50V2lkdGggfHwgZS5vZmZzZXRZID4gZS50YXJnZXQuY2xpZW50SGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChuZXcgRGF0ZSgpLmdldFRpbWUoKSAtIGRyYWdMYXN0VGltZSA8IHdpbmRvdy53YWlscy5mbGFncy5kYkNsaWNrSW50ZXJ2YWwpIHtcbiAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQoZHJhZ1RpbWVPdXQpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZHJhZ1RpbWVPdXQgPSBzZXRUaW1lb3V0KGRyYWcsIHdpbmRvdy53YWlscy5mbGFncy5kYkNsaWNrSW50ZXJ2YWwpO1xuICAgICAgICAgICAgZHJhZ0xhc3RUaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBjdXJyZW50RWxlbWVudCA9IGN1cnJlbnRFbGVtZW50LnBhcmVudEVsZW1lbnQ7XG4gICAgfVxufSk7XG5cbmZ1bmN0aW9uIHNldFJlc2l6ZShjdXJzb3IpIHtcbiAgICBkb2N1bWVudC5ib2R5LnN0eWxlLmN1cnNvciA9IGN1cnNvciB8fCB3aW5kb3cud2FpbHMuZmxhZ3MuZGVmYXVsdEN1cnNvcjtcbiAgICB3aW5kb3cud2FpbHMuZmxhZ3MucmVzaXplRWRnZSA9IGN1cnNvcjtcbn1cblxud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIGZ1bmN0aW9uIChlKSB7XG4gICAgaWYgKCF3aW5kb3cud2FpbHMuZmxhZ3MuZW5hYmxlUmVzaXplKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHdpbmRvdy53YWlscy5mbGFncy5kZWZhdWx0Q3Vyc29yID09IG51bGwpIHtcbiAgICAgICAgd2luZG93LndhaWxzLmZsYWdzLmRlZmF1bHRDdXJzb3IgPSBkb2N1bWVudC5ib2R5LnN0eWxlLmN1cnNvcjtcbiAgICB9XG4gICAgaWYgKHdpbmRvdy5vdXRlcldpZHRoIC0gZS5jbGllbnRYIDwgd2luZG93LndhaWxzLmZsYWdzLmJvcmRlclRoaWNrbmVzcyAmJiB3aW5kb3cub3V0ZXJIZWlnaHQgLSBlLmNsaWVudFkgPCB3aW5kb3cud2FpbHMuZmxhZ3MuYm9yZGVyVGhpY2tuZXNzKSB7XG4gICAgICAgIGRvY3VtZW50LmJvZHkuc3R5bGUuY3Vyc29yID0gXCJzZS1yZXNpemVcIjtcbiAgICB9XG4gICAgbGV0IHJpZ2h0Qm9yZGVyID0gd2luZG93Lm91dGVyV2lkdGggLSBlLmNsaWVudFggPCB3aW5kb3cud2FpbHMuZmxhZ3MuYm9yZGVyVGhpY2tuZXNzO1xuICAgIGxldCBsZWZ0Qm9yZGVyID0gZS5jbGllbnRYIDwgd2luZG93LndhaWxzLmZsYWdzLmJvcmRlclRoaWNrbmVzcztcbiAgICBsZXQgdG9wQm9yZGVyID0gZS5jbGllbnRZIDwgd2luZG93LndhaWxzLmZsYWdzLmJvcmRlclRoaWNrbmVzcztcbiAgICBsZXQgYm90dG9tQm9yZGVyID0gd2luZG93Lm91dGVySGVpZ2h0IC0gZS5jbGllbnRZIDwgd2luZG93LndhaWxzLmZsYWdzLmJvcmRlclRoaWNrbmVzcztcblxuICAgIC8vIElmIHdlIGFyZW4ndCBvbiBhbiBlZGdlLCBidXQgd2VyZSwgcmVzZXQgdGhlIGN1cnNvciB0byBkZWZhdWx0XG4gICAgaWYgKCFsZWZ0Qm9yZGVyICYmICFyaWdodEJvcmRlciAmJiAhdG9wQm9yZGVyICYmICFib3R0b21Cb3JkZXIgJiYgd2luZG93LndhaWxzLmZsYWdzLnJlc2l6ZUVkZ2UgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBzZXRSZXNpemUoKTtcbiAgICB9IGVsc2UgaWYgKHJpZ2h0Qm9yZGVyICYmIGJvdHRvbUJvcmRlcikgc2V0UmVzaXplKFwic2UtcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKGxlZnRCb3JkZXIgJiYgYm90dG9tQm9yZGVyKSBzZXRSZXNpemUoXCJzdy1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAobGVmdEJvcmRlciAmJiB0b3BCb3JkZXIpIHNldFJlc2l6ZShcIm53LXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmICh0b3BCb3JkZXIgJiYgcmlnaHRCb3JkZXIpIHNldFJlc2l6ZShcIm5lLXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmIChsZWZ0Qm9yZGVyKSBzZXRSZXNpemUoXCJ3LXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmICh0b3BCb3JkZXIpIHNldFJlc2l6ZShcIm4tcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKGJvdHRvbUJvcmRlcikgc2V0UmVzaXplKFwicy1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAocmlnaHRCb3JkZXIpIHNldFJlc2l6ZShcImUtcmVzaXplXCIpO1xuXG59KTtcblxuLy8gU2V0dXAgY29udGV4dCBtZW51IGhvb2tcbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdjb250ZXh0bWVudScsIGZ1bmN0aW9uIChlKSB7XG4gICAgaWYgKHdpbmRvdy53YWlscy5mbGFncy5kaXNhYmxlV2FpbHNEZWZhdWx0Q29udGV4dE1lbnUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbn0pOyJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFrQkEsMEJBQXdCLE9BQU8sU0FBUztBQUl2QyxXQUFPLFlBQVksTUFBTSxRQUFRO0FBQUE7QUFTM0Isb0JBQWtCLFNBQVM7QUFDakMsbUJBQWUsS0FBSztBQUFBO0FBU2Qsb0JBQWtCLFNBQVM7QUFDakMsbUJBQWUsS0FBSztBQUFBO0FBU2Qsb0JBQWtCLFNBQVM7QUFDakMsbUJBQWUsS0FBSztBQUFBO0FB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
+//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiZGVza3RvcC9sb2cuanMiLCAiZGVza3RvcC9ldmVudHMuanMiLCAiZGVza3RvcC9jYWxscy5qcyIsICJkZXNrdG9wL2JpbmRpbmdzLmpzIiwgImRlc2t0b3Avd2luZG93LmpzIiwgImRlc2t0b3AvYnJvd3Nlci5qcyIsICJkZXNrdG9wL21haW4uanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qXHJcbiBfICAgICAgIF9fICAgICAgXyBfX1xyXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDYgKi9cclxuXHJcbi8qKlxyXG4gKiBTZW5kcyBhIGxvZyBtZXNzYWdlIHRvIHRoZSBiYWNrZW5kIHdpdGggdGhlIGdpdmVuIGxldmVsICsgbWVzc2FnZVxyXG4gKlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbGV2ZWxcclxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcclxuICovXHJcbmZ1bmN0aW9uIHNlbmRMb2dNZXNzYWdlKGxldmVsLCBtZXNzYWdlKSB7XHJcblxyXG5cdC8vIExvZyBNZXNzYWdlIGZvcm1hdDpcclxuXHQvLyBsW3R5cGVdW21lc3NhZ2VdXHJcblx0d2luZG93LldhaWxzSW52b2tlKCdMJyArIGxldmVsICsgbWVzc2FnZSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBMb2cgdGhlIGdpdmVuIHRyYWNlIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gTG9nVHJhY2UobWVzc2FnZSkge1xyXG5cdHNlbmRMb2dNZXNzYWdlKCdUJywgbWVzc2FnZSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBMb2cgdGhlIGdpdmVuIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gTG9nUHJpbnQobWVzc2FnZSkge1xyXG5cdHNlbmRMb2dNZXNzYWdlKCdQJywgbWVzc2FnZSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBMb2cgdGhlIGdpdmVuIGRlYnVnIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gTG9nRGVidWcobWVzc2FnZSkge1xyXG5cdHNlbmRMb2dNZXNzYWdlKCdEJywgbWVzc2FnZSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBMb2cgdGhlIGdpdmVuIGluZm8gbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBMb2dJbmZvKG1lc3NhZ2UpIHtcclxuXHRzZW5kTG9nTWVzc2FnZSgnSScsIG1lc3NhZ2UpO1xyXG59XHJcblxyXG4vKipcclxuICogTG9nIHRoZSBnaXZlbiB3YXJuaW5nIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gTG9nV2FybmluZyhtZXNzYWdlKSB7XHJcblx0c2VuZExvZ01lc3NhZ2UoJ1cnLCBtZXNzYWdlKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIExvZyB0aGUgZ2l2ZW4gZXJyb3IgbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBMb2dFcnJvcihtZXNzYWdlKSB7XHJcblx0c2VuZExvZ01lc3NhZ2UoJ0UnLCBtZXNzYWdlKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIExvZyB0aGUgZ2l2ZW4gZmF0YWwgbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBMb2dGYXRhbChtZXNzYWdlKSB7XHJcblx0c2VuZExvZ01lc3NhZ2UoJ0YnLCBtZXNzYWdlKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNldHMgdGhlIExvZyBsZXZlbCB0byB0aGUgZ2l2ZW4gbG9nIGxldmVsXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtudW1iZXJ9IGxvZ2xldmVsXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gU2V0TG9nTGV2ZWwobG9nbGV2ZWwpIHtcclxuXHRzZW5kTG9nTWVzc2FnZSgnUycsIGxvZ2xldmVsKTtcclxufVxyXG5cclxuLy8gTG9nIGxldmVsc1xyXG5leHBvcnQgY29uc3QgTG9nTGV2ZWwgPSB7XHJcblx0VFJBQ0U6IDEsXHJcblx0REVCVUc6IDIsXHJcblx0SU5GTzogMyxcclxuXHRXQVJOSU5HOiA0LFxyXG5cdEVSUk9SOiA1LFxyXG59O1xyXG4iLCAiLypcclxuIF8gICAgICAgX18gICAgICBfIF9fXHJcbnwgfCAgICAgLyAvX19fIF8oXykgL19fX19cclxufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xyXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcclxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXHJcblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cclxuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxyXG4qL1xyXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA2ICovXHJcblxyXG4vLyBEZWZpbmVzIGEgc2luZ2xlIGxpc3RlbmVyIHdpdGggYSBtYXhpbXVtIG51bWJlciBvZiB0aW1lcyB0byBjYWxsYmFja1xyXG5cclxuLyoqXHJcbiAqIFRoZSBMaXN0ZW5lciBjbGFzcyBkZWZpbmVzIGEgbGlzdGVuZXIhIDotKVxyXG4gKlxyXG4gKiBAY2xhc3MgTGlzdGVuZXJcclxuICovXHJcbmNsYXNzIExpc3RlbmVyIHtcclxuICAgIC8qKlxyXG4gICAgICogQ3JlYXRlcyBhbiBpbnN0YW5jZSBvZiBMaXN0ZW5lci5cclxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbWF4Q2FsbGJhY2tzXHJcbiAgICAgKiBAbWVtYmVyb2YgTGlzdGVuZXJcclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IoY2FsbGJhY2ssIG1heENhbGxiYWNrcykge1xyXG4gICAgICAgIC8vIERlZmF1bHQgb2YgLTEgbWVhbnMgaW5maW5pdGVcclxuICAgICAgICBtYXhDYWxsYmFja3MgPSBtYXhDYWxsYmFja3MgfHwgLTE7XHJcbiAgICAgICAgLy8gQ2FsbGJhY2sgaW52b2tlcyB0aGUgY2FsbGJhY2sgd2l0aCB0aGUgZ2l2ZW4gZGF0YVxyXG4gICAgICAgIC8vIFJldHVybnMgdHJ1ZSBpZiB0aGlzIGxpc3RlbmVyIHNob3VsZCBiZSBkZXN0cm95ZWRcclxuICAgICAgICB0aGlzLkNhbGxiYWNrID0gKGRhdGEpID0+IHtcclxuICAgICAgICAgICAgY2FsbGJhY2suYXBwbHkobnVsbCwgZGF0YSk7XHJcbiAgICAgICAgICAgIC8vIElmIG1heENhbGxiYWNrcyBpcyBpbmZpbml0ZSwgcmV0dXJuIGZhbHNlIChkbyBub3QgZGVzdHJveSlcclxuICAgICAgICAgICAgaWYgKG1heENhbGxiYWNrcyA9PT0gLTEpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAvLyBEZWNyZW1lbnQgbWF4Q2FsbGJhY2tzLiBSZXR1cm4gdHJ1ZSBpZiBub3cgMCwgb3RoZXJ3aXNlIGZhbHNlXHJcbiAgICAgICAgICAgIG1heENhbGxiYWNrcyAtPSAxO1xyXG4gICAgICAgICAgICByZXR1cm4gbWF4Q2FsbGJhY2tzID09PSAwO1xyXG4gICAgICAgIH07XHJcbiAgICB9XHJcbn1cclxuXHJcbmV4cG9ydCBjb25zdCBldmVudExpc3RlbmVycyA9IHt9O1xyXG5cclxuLyoqXHJcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBgbWF4Q2FsbGJhY2tzYCB0aW1lcyBiZWZvcmUgYmVpbmcgZGVzdHJveWVkXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxyXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFja1xyXG4gKiBAcGFyYW0ge251bWJlcn0gbWF4Q2FsbGJhY2tzXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzT25NdWx0aXBsZShldmVudE5hbWUsIGNhbGxiYWNrLCBtYXhDYWxsYmFja3MpIHtcclxuICAgIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0gPSBldmVudExpc3RlbmVyc1tldmVudE5hbWVdIHx8IFtdO1xyXG4gICAgY29uc3QgdGhpc0xpc3RlbmVyID0gbmV3IExpc3RlbmVyKGNhbGxiYWNrLCBtYXhDYWxsYmFja3MpO1xyXG4gICAgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXS5wdXNoKHRoaXNMaXN0ZW5lcik7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZWdpc3RlcnMgYW4gZXZlbnQgbGlzdGVuZXIgdGhhdCB3aWxsIGJlIGludm9rZWQgZXZlcnkgdGltZSB0aGUgZXZlbnQgaXMgZW1pdHRlZFxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcclxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbihldmVudE5hbWUsIGNhbGxiYWNrKSB7XHJcbiAgICBFdmVudHNPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIC0xKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBvbmNlIHRoZW4gZGVzdHJveWVkXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxyXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFja1xyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEV2ZW50c09uY2UoZXZlbnROYW1lLCBjYWxsYmFjaykge1xyXG4gICAgRXZlbnRzT25NdWx0aXBsZShldmVudE5hbWUsIGNhbGxiYWNrLCAxKTtcclxufVxyXG5cclxuZnVuY3Rpb24gbm90aWZ5TGlzdGVuZXJzKGV2ZW50RGF0YSkge1xyXG5cclxuICAgIC8vIEdldCB0aGUgZXZlbnQgbmFtZVxyXG4gICAgbGV0IGV2ZW50TmFtZSA9IGV2ZW50RGF0YS5uYW1lO1xyXG5cclxuICAgIC8vIENoZWNrIGlmIHdlIGhhdmUgYW55IGxpc3RlbmVycyBmb3IgdGhpcyBldmVudFxyXG4gICAgaWYgKGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0pIHtcclxuXHJcbiAgICAgICAgLy8gS2VlcCBhIGxpc3Qgb2YgbGlzdGVuZXIgaW5kZXhlcyB0byBkZXN0cm95XHJcbiAgICAgICAgY29uc3QgbmV3RXZlbnRMaXN0ZW5lckxpc3QgPSBldmVudExpc3RlbmVyc1tldmVudE5hbWVdLnNsaWNlKCk7XHJcblxyXG4gICAgICAgIC8vIEl0ZXJhdGUgbGlzdGVuZXJzXHJcbiAgICAgICAgZm9yIChsZXQgY291bnQgPSAwOyBjb3VudCA8IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0ubGVuZ3RoOyBjb3VudCArPSAxKSB7XHJcblxyXG4gICAgICAgICAgICAvLyBHZXQgbmV4dCBsaXN0ZW5lclxyXG4gICAgICAgICAgICBjb25zdCBsaXN0ZW5lciA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV1bY291bnRdO1xyXG5cclxuICAgICAgICAgICAgbGV0IGRhdGEgPSBldmVudERhdGEuZGF0YTtcclxuXHJcbiAgICAgICAgICAgIC8vIERvIHRoZSBjYWxsYmFja1xyXG4gICAgICAgICAgICBjb25zdCBkZXN0cm95ID0gbGlzdGVuZXIuQ2FsbGJhY2soZGF0YSk7XHJcbiAgICAgICAgICAgIGlmIChkZXN0cm95KSB7XHJcbiAgICAgICAgICAgICAgICAvLyBpZiB0aGUgbGlzdGVuZXIgaW5kaWNhdGVkIHRvIGRlc3Ryb3kgaXRzZWxmLCBhZGQgaXQgdG8gdGhlIGRlc3Ryb3kgbGlzdFxyXG4gICAgICAgICAgICAgICAgbmV3RXZlbnRMaXN0ZW5lckxpc3Quc3BsaWNlKGNvdW50LCAxKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gVXBkYXRlIGNhbGxiYWNrcyB3aXRoIG5ldyBsaXN0IG9mIGxpc3RlbmVyc1xyXG4gICAgICAgIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0gPSBuZXdFdmVudExpc3RlbmVyTGlzdDtcclxuICAgIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIE5vdGlmeSBpbmZvcm1zIGZyb250ZW5kIGxpc3RlbmVycyB0aGF0IGFuIGV2ZW50IHdhcyBlbWl0dGVkIHdpdGggdGhlIGdpdmVuIGRhdGFcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbm90aWZ5TWVzc2FnZSAtIGVuY29kZWQgbm90aWZpY2F0aW9uIG1lc3NhZ2VcclxuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzTm90aWZ5KG5vdGlmeU1lc3NhZ2UpIHtcclxuICAgIC8vIFBhcnNlIHRoZSBtZXNzYWdlXHJcbiAgICBsZXQgbWVzc2FnZTtcclxuICAgIHRyeSB7XHJcbiAgICAgICAgbWVzc2FnZSA9IEpTT04ucGFyc2Uobm90aWZ5TWVzc2FnZSk7XHJcbiAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgY29uc3QgZXJyb3IgPSAnSW52YWxpZCBKU09OIHBhc3NlZCB0byBOb3RpZnk6ICcgKyBub3RpZnlNZXNzYWdlO1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvcik7XHJcbiAgICB9XHJcbiAgICBub3RpZnlMaXN0ZW5lcnMobWVzc2FnZSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBFbWl0IGFuIGV2ZW50IHdpdGggdGhlIGdpdmVuIG5hbWUgYW5kIGRhdGFcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzRW1pdChldmVudE5hbWUpIHtcclxuXHJcbiAgICBjb25zdCBwYXlsb2FkID0ge1xyXG4gICAgICAgIG5hbWU6IGV2ZW50TmFtZSxcclxuICAgICAgICBkYXRhOiBbXS5zbGljZS5hcHBseShhcmd1bWVudHMpLnNsaWNlKDEpLFxyXG4gICAgfTtcclxuXHJcbiAgICAvLyBOb3RpZnkgSlMgbGlzdGVuZXJzXHJcbiAgICBub3RpZnlMaXN0ZW5lcnMocGF5bG9hZCk7XHJcblxyXG4gICAgLy8gTm90aWZ5IEdvIGxpc3RlbmVyc1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdFRScgKyBKU09OLnN0cmluZ2lmeShwYXlsb2FkKSk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPZmYoZXZlbnROYW1lKSB7XHJcbiAgICAvLyBSZW1vdmUgbG9jYWwgbGlzdGVuZXJzXHJcbiAgICBkZWxldGUgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXTtcclxuXHJcbiAgICAvLyBOb3RpZnkgR28gbGlzdGVuZXJzXHJcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ0VYJyArIGV2ZW50TmFtZSk7XHJcbn0iLCAiLypcclxuIF8gICAgICAgX18gICAgICBfIF9fXHJcbnwgfCAgICAgLyAvX19fIF8oXykgL19fX19cclxufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xyXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcclxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXHJcblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cclxuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxyXG4qL1xyXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA2ICovXHJcblxyXG5leHBvcnQgY29uc3QgY2FsbGJhY2tzID0ge307XHJcblxyXG4vKipcclxuICogUmV0dXJucyBhIG51bWJlciBmcm9tIHRoZSBuYXRpdmUgYnJvd3NlciByYW5kb20gZnVuY3Rpb25cclxuICpcclxuICogQHJldHVybnMgbnVtYmVyXHJcbiAqL1xyXG5mdW5jdGlvbiBjcnlwdG9SYW5kb20oKSB7XHJcblx0dmFyIGFycmF5ID0gbmV3IFVpbnQzMkFycmF5KDEpO1xyXG5cdHJldHVybiB3aW5kb3cuY3J5cHRvLmdldFJhbmRvbVZhbHVlcyhhcnJheSlbMF07XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIGEgbnVtYmVyIHVzaW5nIGRhIG9sZC1za29vbCBNYXRoLlJhbmRvbVxyXG4gKiBJIGxpa2VzIHRvIGNhbGwgaXQgTE9MUmFuZG9tXHJcbiAqXHJcbiAqIEByZXR1cm5zIG51bWJlclxyXG4gKi9cclxuZnVuY3Rpb24gYmFzaWNSYW5kb20oKSB7XHJcblx0cmV0dXJuIE1hdGgucmFuZG9tKCkgKiA5MDA3MTk5MjU0NzQwOTkxO1xyXG59XHJcblxyXG4vLyBQaWNrIGEgcmFuZG9tIG51bWJlciBmdW5jdGlvbiBiYXNlZCBvbiBicm93c2VyIGNhcGFiaWxpdHlcclxudmFyIHJhbmRvbUZ1bmM7XHJcbmlmICh3aW5kb3cuY3J5cHRvKSB7XHJcblx0cmFuZG9tRnVuYyA9IGNyeXB0b1JhbmRvbTtcclxufSBlbHNlIHtcclxuXHRyYW5kb21GdW5jID0gYmFzaWNSYW5kb207XHJcbn1cclxuXHJcblxyXG4vKipcclxuICogQ2FsbCBzZW5kcyBhIG1lc3NhZ2UgdG8gdGhlIGJhY2tlbmQgdG8gY2FsbCB0aGUgYmluZGluZyB3aXRoIHRoZVxyXG4gKiBnaXZlbiBkYXRhLiBBIHByb21pc2UgaXMgcmV0dXJuZWQgYW5kIHdpbGwgYmUgY29tcGxldGVkIHdoZW4gdGhlXHJcbiAqIGJhY2tlbmQgcmVzcG9uZHMuIFRoaXMgd2lsbCBiZSByZXNvbHZlZCB3aGVuIHRoZSBjYWxsIHdhcyBzdWNjZXNzZnVsXHJcbiAqIG9yIHJlamVjdGVkIGlmIGFuIGVycm9yIGlzIHBhc3NlZCBiYWNrLlxyXG4gKiBUaGVyZSBpcyBhIHRpbWVvdXQgbWVjaGFuaXNtLiBJZiB0aGUgY2FsbCBkb2Vzbid0IHJlc3BvbmQgaW4gdGhlIGdpdmVuXHJcbiAqIHRpbWUgKGluIG1pbGxpc2Vjb25kcykgdGhlbiB0aGUgcHJvbWlzZSBpcyByZWplY3RlZC5cclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxyXG4gKiBAcGFyYW0ge2FueT19IGFyZ3NcclxuICogQHBhcmFtIHtudW1iZXI9fSB0aW1lb3V0XHJcbiAqIEByZXR1cm5zXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gQ2FsbChuYW1lLCBhcmdzLCB0aW1lb3V0KSB7XHJcblxyXG5cdC8vIFRpbWVvdXQgaW5maW5pdGUgYnkgZGVmYXVsdFxyXG5cdGlmICh0aW1lb3V0ID09IG51bGwpIHtcclxuXHRcdHRpbWVvdXQgPSAwO1xyXG5cdH1cclxuXHJcblx0Ly8gQ3JlYXRlIGEgcHJvbWlzZVxyXG5cdHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XHJcblxyXG5cdFx0Ly8gQ3JlYXRlIGEgdW5pcXVlIGNhbGxiYWNrSURcclxuXHRcdHZhciBjYWxsYmFja0lEO1xyXG5cdFx0ZG8ge1xyXG5cdFx0XHRjYWxsYmFja0lEID0gbmFtZSArICctJyArIHJhbmRvbUZ1bmMoKTtcclxuXHRcdH0gd2hpbGUgKGNhbGxiYWNrc1tjYWxsYmFja0lEXSk7XHJcblxyXG5cdFx0dmFyIHRpbWVvdXRIYW5kbGU7XHJcblx0XHQvLyBTZXQgdGltZW91dFxyXG5cdFx0aWYgKHRpbWVvdXQgPiAwKSB7XHJcblx0XHRcdHRpbWVvdXRIYW5kbGUgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0XHRyZWplY3QoRXJyb3IoJ0NhbGwgdG8gJyArIG5hbWUgKyAnIHRpbWVkIG91dC4gUmVxdWVzdCBJRDogJyArIGNhbGxiYWNrSUQpKTtcclxuXHRcdFx0fSwgdGltZW91dCk7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gU3RvcmUgY2FsbGJhY2tcclxuXHRcdGNhbGxiYWNrc1tjYWxsYmFja0lEXSA9IHtcclxuXHRcdFx0dGltZW91dEhhbmRsZTogdGltZW91dEhhbmRsZSxcclxuXHRcdFx0cmVqZWN0OiByZWplY3QsXHJcblx0XHRcdHJlc29sdmU6IHJlc29sdmVcclxuXHRcdH07XHJcblxyXG5cdFx0dHJ5IHtcclxuXHRcdFx0Y29uc3QgcGF5bG9hZCA9IHtcclxuXHRcdFx0XHRuYW1lLFxyXG5cdFx0XHRcdGFyZ3MsXHJcblx0XHRcdFx0Y2FsbGJhY2tJRCxcclxuXHRcdFx0fTtcclxuXHJcblx0XHRcdC8vIE1ha2UgdGhlIGNhbGxcclxuXHRcdFx0d2luZG93LldhaWxzSW52b2tlKCdDJyArIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcclxuXHRcdH0gY2F0Y2ggKGUpIHtcclxuXHRcdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXHJcblx0XHRcdGNvbnNvbGUuZXJyb3IoZSk7XHJcblx0XHR9XHJcblx0fSk7XHJcbn1cclxuXHJcblxyXG5cclxuLyoqXHJcbiAqIENhbGxlZCBieSB0aGUgYmFja2VuZCB0byByZXR1cm4gZGF0YSB0byBhIHByZXZpb3VzbHkgY2FsbGVkXHJcbiAqIGJpbmRpbmcgaW52b2NhdGlvblxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBpbmNvbWluZ01lc3NhZ2VcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBDYWxsYmFjayhpbmNvbWluZ01lc3NhZ2UpIHtcclxuXHQvLyBQYXJzZSB0aGUgbWVzc2FnZVxyXG5cdGxldCBtZXNzYWdlO1xyXG5cdHRyeSB7XHJcblx0XHRtZXNzYWdlID0gSlNPTi5wYXJzZShpbmNvbWluZ01lc3NhZ2UpO1xyXG5cdH0gY2F0Y2ggKGUpIHtcclxuXHRcdGNvbnN0IGVycm9yID0gYEludmFsaWQgSlNPTiBwYXNzZWQgdG8gY2FsbGJhY2s6ICR7ZS5tZXNzYWdlfS4gTWVzc2FnZTogJHtpbmNvbWluZ01lc3NhZ2V9YDtcclxuXHRcdHJ1bnRpbWUuTG9nRGVidWcoZXJyb3IpO1xyXG5cdFx0dGhyb3cgbmV3IEVycm9yKGVycm9yKTtcclxuXHR9XHJcblx0bGV0IGNhbGxiYWNrSUQgPSBtZXNzYWdlLmNhbGxiYWNraWQ7XHJcblx0bGV0IGNhbGxiYWNrRGF0YSA9IGNhbGxiYWNrc1tjYWxsYmFja0lEXTtcclxuXHRpZiAoIWNhbGxiYWNrRGF0YSkge1xyXG5cdFx0Y29uc3QgZXJyb3IgPSBgQ2FsbGJhY2sgJyR7Y2FsbGJhY2tJRH0nIG5vdCByZWdpc3RlcmVkISEhYDtcclxuXHRcdGNvbnNvbGUuZXJyb3IoZXJyb3IpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXHJcblx0XHR0aHJvdyBuZXcgRXJyb3IoZXJyb3IpO1xyXG5cdH1cclxuXHRjbGVhclRpbWVvdXQoY2FsbGJhY2tEYXRhLnRpbWVvdXRIYW5kbGUpO1xyXG5cclxuXHRkZWxldGUgY2FsbGJhY2tzW2NhbGxiYWNrSURdO1xyXG5cclxuXHRpZiAobWVzc2FnZS5lcnJvcikge1xyXG5cdFx0Y2FsbGJhY2tEYXRhLnJlamVjdChtZXNzYWdlLmVycm9yKTtcclxuXHR9IGVsc2Uge1xyXG5cdFx0Y2FsbGJhY2tEYXRhLnJlc29sdmUobWVzc2FnZS5yZXN1bHQpO1xyXG5cdH1cclxufVxyXG4iLCAiLypcclxuIF8gICAgICAgX18gICAgICBfIF9fICAgIFxyXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApIFxyXG58X18vfF9fL1xcX18sXy9fL18vX19fXy8gIFxyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuLyoganNoaW50IGVzdmVyc2lvbjogNiAqL1xyXG5cclxuaW1wb3J0IHtDYWxsfSBmcm9tICcuL2NhbGxzJztcclxuXHJcbi8vIFRoaXMgaXMgd2hlcmUgd2UgYmluZCBnbyBtZXRob2Qgd3JhcHBlcnNcclxud2luZG93LmdvID0ge307XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gU2V0QmluZGluZ3MoYmluZGluZ3NNYXApIHtcclxuXHR0cnkge1xyXG5cdFx0YmluZGluZ3NNYXAgPSBKU09OLnBhcnNlKGJpbmRpbmdzTWFwKTtcclxuXHR9IGNhdGNoIChlKSB7XHJcblx0XHRjb25zb2xlLmVycm9yKGUpO1xyXG5cdH1cclxuXHJcblx0Ly8gSW5pdGlhbGlzZSB0aGUgYmluZGluZ3MgbWFwXHJcblx0d2luZG93LmdvID0gd2luZG93LmdvIHx8IHt9O1xyXG5cclxuXHQvLyBJdGVyYXRlIHBhY2thZ2UgbmFtZXNcclxuXHRPYmplY3Qua2V5cyhiaW5kaW5nc01hcCkuZm9yRWFjaCgocGFja2FnZU5hbWUpID0+IHtcclxuXHJcblx0XHQvLyBDcmVhdGUgaW5uZXIgbWFwIGlmIGl0IGRvZXNuJ3QgZXhpc3RcclxuXHRcdHdpbmRvdy5nb1twYWNrYWdlTmFtZV0gPSB3aW5kb3cuZ29bcGFja2FnZU5hbWVdIHx8IHt9O1xyXG5cclxuXHRcdC8vIEl0ZXJhdGUgc3RydWN0IG5hbWVzXHJcblx0XHRPYmplY3Qua2V5cyhiaW5kaW5nc01hcFtwYWNrYWdlTmFtZV0pLmZvckVhY2goKHN0cnVjdE5hbWUpID0+IHtcclxuXHJcblx0XHRcdC8vIENyZWF0ZSBpbm5lciBtYXAgaWYgaXQgZG9lc24ndCBleGlzdFxyXG5cdFx0XHR3aW5kb3cuZ29bcGFja2FnZU5hbWVdW3N0cnVjdE5hbWVdID0gd2luZG93LmdvW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXSB8fCB7fTtcclxuXHJcblx0XHRcdE9iamVjdC5rZXlzKGJpbmRpbmdzTWFwW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXSkuZm9yRWFjaCgobWV0aG9kTmFtZSkgPT4ge1xyXG5cclxuXHRcdFx0XHR3aW5kb3cuZ29bcGFja2FnZU5hbWVdW3N0cnVjdE5hbWVdW21ldGhvZE5hbWVdID0gZnVuY3Rpb24gKCkge1xyXG5cclxuXHRcdFx0XHRcdC8vIE5vIHRpbWVvdXQgYnkgZGVmYXVsdFxyXG5cdFx0XHRcdFx0bGV0IHRpbWVvdXQgPSAwO1xyXG5cclxuXHRcdFx0XHRcdC8vIEFjdHVhbCBmdW5jdGlvblxyXG5cdFx0XHRcdFx0ZnVuY3Rpb24gZHluYW1pYygpIHtcclxuXHRcdFx0XHRcdFx0Y29uc3QgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcclxuXHRcdFx0XHRcdFx0cmV0dXJuIENhbGwoW3BhY2thZ2VOYW1lLCBzdHJ1Y3ROYW1lLCBtZXRob2ROYW1lXS5qb2luKCcuJyksIGFyZ3MsIHRpbWVvdXQpO1xyXG5cdFx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRcdC8vIEFsbG93IHNldHRpbmcgdGltZW91dCB0byBmdW5jdGlvblxyXG5cdFx0XHRcdFx0ZHluYW1pYy5zZXRUaW1lb3V0ID0gZnVuY3Rpb24gKG5ld1RpbWVvdXQpIHtcclxuXHRcdFx0XHRcdFx0dGltZW91dCA9IG5ld1RpbWVvdXQ7XHJcblx0XHRcdFx0XHR9O1xyXG5cclxuXHRcdFx0XHRcdC8vIEFsbG93IGdldHRpbmcgdGltZW91dCB0byBmdW5jdGlvblxyXG5cdFx0XHRcdFx0ZHluYW1pYy5nZXRUaW1lb3V0ID0gZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRcdFx0XHRyZXR1cm4gdGltZW91dDtcclxuXHRcdFx0XHRcdH07XHJcblxyXG5cdFx0XHRcdFx0cmV0dXJuIGR5bmFtaWM7XHJcblx0XHRcdFx0fSgpO1xyXG5cdFx0XHR9KTtcclxuXHRcdH0pO1xyXG5cdH0pO1xyXG59XHJcbiIsICIvKlxyXG4gX1x0ICAgX19cdCAgXyBfX1xyXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xyXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXHJcbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxyXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cclxuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xyXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XHJcbiovXHJcblxyXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXHJcblxyXG5cclxuaW1wb3J0IHsgQ2FsbCB9IGZyb20gXCIuL2NhbGxzXCI7XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93UmVsb2FkKCkge1xyXG4gICAgd2luZG93LmxvY2F0aW9uLnJlbG9hZCgpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93UmVsb2FkQXBwKCkge1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXUicpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0U3lzdGVtRGVmYXVsdFRoZW1lKCkge1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXQVNEVCcpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0TGlnaHRUaGVtZSgpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0FMVCcpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0RGFya1RoZW1lKCkge1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXQURUJyk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBQbGFjZSB0aGUgd2luZG93IGluIHRoZSBjZW50ZXIgb2YgdGhlIHNjcmVlblxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93Q2VudGVyKCkge1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXYycpO1xyXG59XHJcblxyXG4vKipcclxuICogU2V0cyB0aGUgd2luZG93IHRpdGxlXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSB0aXRsZVxyXG4gKiBAZXhwb3J0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0VGl0bGUodGl0bGUpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV1QnICsgdGl0bGUpO1xyXG59XHJcblxyXG4vKipcclxuICogTWFrZXMgdGhlIHdpbmRvdyBnbyBmdWxsc2NyZWVuXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dGdWxsc2NyZWVuKCkge1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXRicpO1xyXG59XHJcblxyXG4vKipcclxuICogUmV2ZXJ0cyB0aGUgd2luZG93IGZyb20gZnVsbHNjcmVlblxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93VW5mdWxsc2NyZWVuKCkge1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXZicpO1xyXG59XHJcblxyXG4vKipcclxuICogU2V0IHRoZSBTaXplIG9mIHRoZSB3aW5kb3dcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge251bWJlcn0gd2lkdGhcclxuICogQHBhcmFtIHtudW1iZXJ9IGhlaWdodFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldFNpemUod2lkdGgsIGhlaWdodCkge1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXczonICsgd2lkdGggKyAnOicgKyBoZWlnaHQpO1xyXG59XHJcblxyXG4vKipcclxuICogR2V0IHRoZSBTaXplIG9mIHRoZSB3aW5kb3dcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcmV0dXJuIHtQcm9taXNlPHt3OiBudW1iZXIsIGg6IG51bWJlcn0+fSBUaGUgc2l6ZSBvZiB0aGUgd2luZG93XHJcblxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0dldFNpemUoKSB7XHJcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpXaW5kb3dHZXRTaXplXCIpO1xyXG59XHJcblxyXG4vKipcclxuICogU2V0IHRoZSBtYXhpbXVtIHNpemUgb2YgdGhlIHdpbmRvd1xyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aFxyXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0TWF4U2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XHJcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1daOicgKyB3aWR0aCArICc6JyArIGhlaWdodCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBTZXQgdGhlIG1pbmltdW0gc2l6ZSBvZiB0aGUgd2luZG93XHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHRcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRNaW5TaXplKHdpZHRoLCBoZWlnaHQpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3o6JyArIHdpZHRoICsgJzonICsgaGVpZ2h0KTtcclxufVxyXG5cclxuXHJcblxyXG4vKipcclxuICogU2V0IHRoZSB3aW5kb3cgQWx3YXlzT25Ub3Agb3Igbm90IG9uIHRvcFxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0QWx3YXlzT25Ub3AoYikge1xyXG5cclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0FUUDonICsgKGIgPyAnMScgOiAnMCcpKTtcclxufVxyXG5cclxuXHJcblxyXG5cclxuLyoqXHJcbiAqIFNldCB0aGUgUG9zaXRpb24gb2YgdGhlIHdpbmRvd1xyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7bnVtYmVyfSB4XHJcbiAqIEBwYXJhbSB7bnVtYmVyfSB5XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0UG9zaXRpb24oeCwgeSkge1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXcDonICsgeCArICc6JyArIHkpO1xyXG59XHJcblxyXG4vKipcclxuICogR2V0IHRoZSBQb3NpdGlvbiBvZiB0aGUgd2luZG93XHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHJldHVybiB7UHJvbWlzZTx7eDogbnVtYmVyLCB5OiBudW1iZXJ9Pn0gVGhlIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3dcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dHZXRQb3NpdGlvbigpIHtcclxuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOldpbmRvd0dldFBvc1wiKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEhpZGUgdGhlIFdpbmRvd1xyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93SGlkZSgpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0gnKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNob3cgdGhlIFdpbmRvd1xyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2hvdygpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV1MnKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIE1heGltaXNlIHRoZSBXaW5kb3dcclxuICpcclxuICogQGV4cG9ydFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd01heGltaXNlKCkge1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXTScpO1xyXG59XHJcblxyXG4vKipcclxuICogVG9nZ2xlIHRoZSBNYXhpbWlzZSBvZiB0aGUgV2luZG93XHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dUb2dnbGVNYXhpbWlzZSgpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3QnKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFVubWF4aW1pc2UgdGhlIFdpbmRvd1xyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93VW5tYXhpbWlzZSgpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV1UnKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIE1pbmltaXNlIHRoZSBXaW5kb3dcclxuICpcclxuICogQGV4cG9ydFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd01pbmltaXNlKCkge1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXbScpO1xyXG59XHJcblxyXG4vKipcclxuICogVW5taW5pbWlzZSB0aGUgV2luZG93XHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dVbm1pbmltaXNlKCkge1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXdScpO1xyXG59XHJcblxyXG4vKipcclxuICogU2V0cyB0aGUgYmFja2dyb3VuZCBjb2xvdXIgb2YgdGhlIHdpbmRvd1xyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBSIFJlZFxyXG4gKiBAcGFyYW0ge251bWJlcn0gRyBHcmVlblxyXG4gKiBAcGFyYW0ge251bWJlcn0gQiBCbHVlXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBBIEFscGhhXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0QmFja2dyb3VuZENvbG91cihSLCBHLCBCLCBBKSB7XHJcbiAgICBsZXQgcmdiYSA9IEpTT04uc3RyaW5naWZ5KHsgcjogUiB8fCAwLCBnOiBHIHx8IDAsIGI6IEIgfHwgMCwgYTogQSB8fCAyNTUgfSk7XHJcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dyOicgKyByZ2JhKTtcclxufVxyXG5cclxuIiwgIi8qKlxyXG4gKiBAZGVzY3JpcHRpb246IFVzZSB0aGUgc3lzdGVtIGRlZmF1bHQgYnJvd3NlciB0byBvcGVuIHRoZSB1cmxcclxuICogQHBhcmFtIHtzdHJpbmd9IHVybCBcclxuICogQHJldHVybiB7dm9pZH1cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBCcm93c2VyT3BlblVSTCh1cmwpIHtcclxuICB3aW5kb3cuV2FpbHNJbnZva2UoJ0JPOicgKyB1cmwpO1xyXG59IiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xyXG5pbXBvcnQgKiBhcyBMb2cgZnJvbSAnLi9sb2cnO1xyXG5pbXBvcnQge2V2ZW50TGlzdGVuZXJzLCBFdmVudHNFbWl0LCBFdmVudHNOb3RpZnksIEV2ZW50c09mZiwgRXZlbnRzT24sIEV2ZW50c09uY2UsIEV2ZW50c09uTXVsdGlwbGV9IGZyb20gJy4vZXZlbnRzJztcclxuaW1wb3J0IHtDYWxsLCBDYWxsYmFjaywgY2FsbGJhY2tzfSBmcm9tICcuL2NhbGxzJztcclxuaW1wb3J0IHtTZXRCaW5kaW5nc30gZnJvbSBcIi4vYmluZGluZ3NcIjtcclxuaW1wb3J0ICogYXMgV2luZG93IGZyb20gXCIuL3dpbmRvd1wiO1xyXG5pbXBvcnQgKiBhcyBCcm93c2VyIGZyb20gXCIuL2Jyb3dzZXJcIjtcclxuXHJcblxyXG5leHBvcnQgZnVuY3Rpb24gUXVpdCgpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnUScpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gRW52aXJvbm1lbnQoKSB7XHJcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpFbnZpcm9ubWVudFwiKTtcclxufVxyXG5cclxuLy8gVGhlIEpTIHJ1bnRpbWVcclxud2luZG93LnJ1bnRpbWUgPSB7XHJcbiAgICAuLi5Mb2csXHJcbiAgICAuLi5XaW5kb3csXHJcbiAgICAuLi5Ccm93c2VyLFxyXG4gICAgRXZlbnRzT24sXHJcbiAgICBFdmVudHNPbmNlLFxyXG4gICAgRXZlbnRzT25NdWx0aXBsZSxcclxuICAgIEV2ZW50c0VtaXQsXHJcbiAgICBFdmVudHNPZmYsXHJcbiAgICBFbnZpcm9ubWVudCxcclxuICAgIFF1aXRcclxufTtcclxuXHJcbi8vIEludGVybmFsIHdhaWxzIGVuZHBvaW50c1xyXG53aW5kb3cud2FpbHMgPSB7XHJcbiAgICBDYWxsYmFjayxcclxuICAgIEV2ZW50c05vdGlmeSxcclxuICAgIFNldEJpbmRpbmdzLFxyXG4gICAgZXZlbnRMaXN0ZW5lcnMsXHJcbiAgICBjYWxsYmFja3MsXHJcbiAgICBmbGFnczoge1xyXG4gICAgICAgIGRpc2FibGVTY3JvbGxiYXJEcmFnOiBmYWxzZSxcclxuICAgICAgICBkaXNhYmxlV2FpbHNEZWZhdWx0Q29udGV4dE1lbnU6IGZhbHNlLFxyXG4gICAgICAgIGVuYWJsZVJlc2l6ZTogZmFsc2UsXHJcbiAgICAgICAgZGVmYXVsdEN1cnNvcjogbnVsbCxcclxuICAgICAgICBib3JkZXJUaGlja25lc3M6IDYsXHJcbiAgICAgICAgZGJDbGlja0ludGVydmFsOiAxMDAsXHJcbiAgICB9XHJcbn07XHJcblxyXG4vLyBTZXQgdGhlIGJpbmRpbmdzXHJcbndpbmRvdy53YWlscy5TZXRCaW5kaW5ncyh3aW5kb3cud2FpbHNiaW5kaW5ncyk7XHJcbmRlbGV0ZSB3aW5kb3cud2FpbHMuU2V0QmluZGluZ3M7XHJcblxyXG4vLyBUaGlzIGlzIGV2YWx1YXRlZCBhdCBidWlsZCB0aW1lIGluIHBhY2thZ2UuanNvblxyXG4vLyBjb25zdCBkZXYgPSAwO1xyXG4vLyBjb25zdCBwcm9kdWN0aW9uID0gMTtcclxuaWYgKEVOViA9PT0gMCkge1xyXG4gICAgZGVsZXRlIHdpbmRvdy53YWlsc2JpbmRpbmdzO1xyXG59XHJcblxyXG52YXIgZHJhZ1RpbWVPdXQ7XHJcbnZhciBkcmFnTGFzdFRpbWUgPSAwO1xyXG5cclxuZnVuY3Rpb24gZHJhZygpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZShcImRyYWdcIik7XHJcbn1cclxuXHJcbi8vIFNldHVwIGRyYWcgaGFuZGxlclxyXG4vLyBCYXNlZCBvbiBjb2RlIGZyb206IGh0dHBzOi8vZ2l0aHViLmNvbS9wYXRyMG51cy9EZXNrR2FwXHJcbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCAoZSkgPT4ge1xyXG5cclxuICAgIC8vIENoZWNrIGZvciByZXNpemluZ1xyXG4gICAgaWYgKHdpbmRvdy53YWlscy5mbGFncy5yZXNpemVFZGdlKSB7XHJcbiAgICAgICAgd2luZG93LldhaWxzSW52b2tlKFwicmVzaXplOlwiICsgd2luZG93LndhaWxzLmZsYWdzLnJlc2l6ZUVkZ2UpO1xyXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQ2hlY2sgZm9yIGRyYWdnaW5nXHJcbiAgICBsZXQgY3VycmVudEVsZW1lbnQgPSBlLnRhcmdldDtcclxuICAgIHdoaWxlIChjdXJyZW50RWxlbWVudCAhPSBudWxsKSB7XHJcbiAgICAgICAgaWYgKGN1cnJlbnRFbGVtZW50Lmhhc0F0dHJpYnV0ZSgnZGF0YS13YWlscy1uby1kcmFnJykpIHtcclxuICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50RWxlbWVudC5oYXNBdHRyaWJ1dGUoJ2RhdGEtd2FpbHMtZHJhZycpKSB7XHJcbiAgICAgICAgICAgIGlmICh3aW5kb3cud2FpbHMuZmxhZ3MuZGlzYWJsZVNjcm9sbGJhckRyYWcpIHtcclxuICAgICAgICAgICAgICAgIC8vIFRoaXMgY2hlY2tzIGZvciBjbGlja3Mgb24gdGhlIHNjcm9sbCBiYXJcclxuICAgICAgICAgICAgICAgIGlmIChlLm9mZnNldFggPiBlLnRhcmdldC5jbGllbnRXaWR0aCB8fCBlLm9mZnNldFkgPiBlLnRhcmdldC5jbGllbnRIZWlnaHQpIHtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAobmV3IERhdGUoKS5nZXRUaW1lKCkgLSBkcmFnTGFzdFRpbWUgPCB3aW5kb3cud2FpbHMuZmxhZ3MuZGJDbGlja0ludGVydmFsKSB7XHJcbiAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQoZHJhZ1RpbWVPdXQpO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZHJhZ1RpbWVPdXQgPSBzZXRUaW1lb3V0KGRyYWcsIHdpbmRvdy53YWlscy5mbGFncy5kYkNsaWNrSW50ZXJ2YWwpO1xyXG4gICAgICAgICAgICBkcmFnTGFzdFRpbWUgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcclxuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgICAgICBicmVhaztcclxuICAgICAgICB9XHJcbiAgICAgICAgY3VycmVudEVsZW1lbnQgPSBjdXJyZW50RWxlbWVudC5wYXJlbnRFbGVtZW50O1xyXG4gICAgfVxyXG59KTtcclxuXHJcbmZ1bmN0aW9uIHNldFJlc2l6ZShjdXJzb3IpIHtcclxuICAgIGRvY3VtZW50LmJvZHkuc3R5bGUuY3Vyc29yID0gY3Vyc29yIHx8IHdpbmRvdy53YWlscy5mbGFncy5kZWZhdWx0Q3Vyc29yO1xyXG4gICAgd2luZG93LndhaWxzLmZsYWdzLnJlc2l6ZUVkZ2UgPSBjdXJzb3I7XHJcbn1cclxuXHJcbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBmdW5jdGlvbiAoZSkge1xyXG4gICAgaWYgKCF3aW5kb3cud2FpbHMuZmxhZ3MuZW5hYmxlUmVzaXplKSB7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgaWYgKHdpbmRvdy53YWlscy5mbGFncy5kZWZhdWx0Q3Vyc29yID09IG51bGwpIHtcclxuICAgICAgICB3aW5kb3cud2FpbHMuZmxhZ3MuZGVmYXVsdEN1cnNvciA9IGRvY3VtZW50LmJvZHkuc3R5bGUuY3Vyc29yO1xyXG4gICAgfVxyXG4gICAgaWYgKHdpbmRvdy5vdXRlcldpZHRoIC0gZS5jbGllbnRYIDwgd2luZG93LndhaWxzLmZsYWdzLmJvcmRlclRoaWNrbmVzcyAmJiB3aW5kb3cub3V0ZXJIZWlnaHQgLSBlLmNsaWVudFkgPCB3aW5kb3cud2FpbHMuZmxhZ3MuYm9yZGVyVGhpY2tuZXNzKSB7XHJcbiAgICAgICAgZG9jdW1lbnQuYm9keS5zdHlsZS5jdXJzb3IgPSBcInNlLXJlc2l6ZVwiO1xyXG4gICAgfVxyXG4gICAgbGV0IHJpZ2h0Qm9yZGVyID0gd2luZG93Lm91dGVyV2lkdGggLSBlLmNsaWVudFggPCB3aW5kb3cud2FpbHMuZmxhZ3MuYm9yZGVyVGhpY2tuZXNzO1xyXG4gICAgbGV0IGxlZnRCb3JkZXIgPSBlLmNsaWVudFggPCB3aW5kb3cud2FpbHMuZmxhZ3MuYm9yZGVyVGhpY2tuZXNzO1xyXG4gICAgbGV0IHRvcEJvcmRlciA9IGUuY2xpZW50WSA8IHdpbmRvdy53YWlscy5mbGFncy5ib3JkZXJUaGlja25lc3M7XHJcbiAgICBsZXQgYm90dG9tQm9yZGVyID0gd2luZG93Lm91dGVySGVpZ2h0IC0gZS5jbGllbnRZIDwgd2luZG93LndhaWxzLmZsYWdzLmJvcmRlclRoaWNrbmVzcztcclxuXHJcbiAgICAvLyBJZiB3ZSBhcmVuJ3Qgb24gYW4gZWRnZSwgYnV0IHdlcmUsIHJlc2V0IHRoZSBjdXJzb3IgdG8gZGVmYXVsdFxyXG4gICAgaWYgKCFsZWZ0Qm9yZGVyICYmICFyaWdodEJvcmRlciAmJiAhdG9wQm9yZGVyICYmICFib3R0b21Cb3JkZXIgJiYgd2luZG93LndhaWxzLmZsYWdzLnJlc2l6ZUVkZ2UgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgIHNldFJlc2l6ZSgpO1xyXG4gICAgfSBlbHNlIGlmIChyaWdodEJvcmRlciAmJiBib3R0b21Cb3JkZXIpIHNldFJlc2l6ZShcInNlLXJlc2l6ZVwiKTtcclxuICAgIGVsc2UgaWYgKGxlZnRCb3JkZXIgJiYgYm90dG9tQm9yZGVyKSBzZXRSZXNpemUoXCJzdy1yZXNpemVcIik7XHJcbiAgICBlbHNlIGlmIChsZWZ0Qm9yZGVyICYmIHRvcEJvcmRlcikgc2V0UmVzaXplKFwibnctcmVzaXplXCIpO1xyXG4gICAgZWxzZSBpZiAodG9wQm9yZGVyICYmIHJpZ2h0Qm9yZGVyKSBzZXRSZXNpemUoXCJuZS1yZXNpemVcIik7XHJcbiAgICBlbHNlIGlmIChsZWZ0Qm9yZGVyKSBzZXRSZXNpemUoXCJ3LXJlc2l6ZVwiKTtcclxuICAgIGVsc2UgaWYgKHRvcEJvcmRlcikgc2V0UmVzaXplKFwibi1yZXNpemVcIik7XHJcbiAgICBlbHNlIGlmIChib3R0b21Cb3JkZXIpIHNldFJlc2l6ZShcInMtcmVzaXplXCIpO1xyXG4gICAgZWxzZSBpZiAocmlnaHRCb3JkZXIpIHNldFJlc2l6ZShcImUtcmVzaXplXCIpO1xyXG5cclxufSk7XHJcblxyXG4vLyBTZXR1cCBjb250ZXh0IG1lbnUgaG9va1xyXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignY29udGV4dG1lbnUnLCBmdW5jdGlvbiAoZSkge1xyXG4gICAgaWYgKHdpbmRvdy53YWlscy5mbGFncy5kaXNhYmxlV2FpbHNEZWZhdWx0Q29udGV4dE1lbnUpIHtcclxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICB9XHJcbn0pOyJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFrQkEsMEJBQXdCLE9BQU8sU0FBUztBQUl2QyxXQUFPLFlBQVksTUFBTSxRQUFRO0FBQUE7QUFTM0Isb0JBQWtCLFNBQVM7QUFDakMsbUJBQWUsS0FBSztBQUFBO0FBU2Qsb0JBQWtCLFNBQVM7QUFDakMsbUJBQWUsS0FBSztBQUFBO0FBU2Qsb0JBQWtCLFNBQVM7QUFDakMsbUJBQWUsS0FBSztBQUFBO0FBU2QsbUJBQWlCLFNBQVM7QUFDaEMsbUJBQWUsS0FBSztBQUFBO0FBU2Qsc0JBQW9CLFNBQVM7QUFDbkMsbUJBQWUsS0FBSztBQUFBO0FBU2Qsb0JBQWtCLFNBQVM7QUFDakMsbUJBQWUsS0FBSztBQUFBO0FBU2Qsb0JBQWtCLFNBQVM7QUFDakMsbUJBQWUsS0FBSztBQUFBO0FBU2QsdUJBQXFCLFVBQVU7QUFDckMsbUJBQWUsS0FBSztBQUFBO0FBSWQsTUFBTSxXQUFXO0FBQUEsSUFDdkIsT0FBTztBQUFBLElBQ1AsT0FBTztBQUFBLElBQ1AsTUFBTTtBQUFBLElBQ04sU0FBUztBQUFBLElBQ1QsT0FBTztBQUFBOzs7QUM3RlIsdUJBQWU7QUFBQSxJQU9YLFlBQVksVUFBVSxjQUFjO0FBRWhDLHFCQUFlLGdCQUFnQjtBQUcvQixXQUFLLFdBQVcsQ0FBQyxTQUFTO0FBQ3RCLGlCQUFTLE1BQU0sTUFBTTtBQUVyQixZQUFJLGlCQUFpQixJQUFJO0FBQ3JCLGlCQUFPO0FBQUE7QUFHWCx3QkFBZ0I7QUFDaEIsZUFBTyxpQkFBaUI7QUFBQTtBQUFBO0FBQUE7QUFLN0IsTUFBTSxpQkFBaUI7QUFVdkIsNEJBQTBCLFdBQVcsVUFBVSxjQUFjO0FBQ2hFLG1CQUFlLGFBQWEsZUFBZSxjQUFjO0FBQ3pELFVBQU0sZUFBZSxJQUFJLFNBQVMsVUFBVTtBQUM1QyxtQkFBZSxXQUFXLEtBQUs7QUFBQTtBQVU1QixvQkFBa0IsV0FBVyxVQUFVO0FBQzFDLHFCQUFpQixXQUFXLFVBQVU7QUFBQTtBQVVuQyxzQkFBb0IsV0FBVyxVQUFVO0FBQzVDLHFCQUFpQixXQUFXLFVBQVU7QUFBQTtBQUcxQywyQkFBeUIsV0FBVztBQUdoQyxRQUFJLFlBQVksVUFBVTtBQUcxQixRQUFJLGVBQWUsWUFBWTtBQUczQixZQUFNLHVCQUF1QixlQUFlLFdBQVc7QUFHdkQsZUFBUyxRQUFRLEdBQUcsUUFBUSxlQUFlLFdBQVcsUUFBUSxTQUFTLEdBQUc7QUFHdEUsY0FBTSxXQUFXLGVBQWUsV0FBVztBQUUzQyxZQUFJLE9BQU8sVUFBVTtBQUdyQixjQUFNLFVBQVUsU0FBUyxTQUFTO0FBQ2xDLFlBQUksU0FBUztBQUVULCtCQUFxQixPQUFPLE9BQU87QUFBQTtBQUFBO0FBSzNDLHFCQUFlLGFBQWE7QUFBQTtBQUFBO0FBVzdCLHdCQUFzQixlQUFlO0FBRXhDLFFBQUk7QUFDSixRQUFJO0FBQ0EsZ0JBQVUsS0FBSyxNQUFNO0FBQUEsYUFDaEIsR0FBUDtBQUNFLFlBQU0sUUFBUSxvQ0FBb0M7QUFDbEQsWUFBTSxJQUFJLE1BQU07QUFBQTtBQUVwQixvQkFBZ0I7QUFBQTtBQVNiLHNCQUFvQixXQUFXO0FBRWxDLFVBQU0sVUFBVTtBQUFBLE1BQ1osTUFBTTtBQUFBLE1BQ04sTUFBTSxHQUFHLE1BQU0sTUFBTSxXQUFXLE1BQU07QUFBQTtBQUkxQyxvQkFBZ0I7QUFHaEIsV0FBTyxZQUFZLE9BQU8sS0FBSyxVQUFVO0FBQUE7QUFHdEMscUJBQW1CLFdBQVc7QUFFakMsV0FBTyxlQUFlO0FBR3RCLFdBQU8sWUFBWSxPQUFPO0FBQUE7OztBQ2xKdkIsTUFBTSxZQUFZO0FBT3pCLDBCQUF3QjtBQUN2QixRQUFJLFFBQVEsSUFBSSxZQUFZO0FBQzVCLFdBQU8sT0FBTyxPQUFPLGdCQUFnQixPQUFPO0FBQUE7QUFTN0MseUJBQXVCO0FBQ3RCLFdBQU8sS0FBSyxXQUFXO0FBQUE7QUFJeEIsTUFBSTtBQUNKLE1BQUksT0FBTyxRQUFRO0FBQ2xCLGlCQUFhO0FBQUEsU0FDUDtBQUNOLGlCQUFhO0FBQUE7QUFrQlAsZ0JBQWMsTUFBTSxNQUFNLFNBQVM7QUFHekMsUUFBSSxXQUFXLE1BQU07QUFDcEIsZ0JBQVU7QUFBQTtBQUlYLFdBQU8sSUFBSSxRQUFRLFNBQVUsU0FBUyxRQUFRO0FBRzdDLFVBQUk7QUFDSixTQUFHO0FBQ0YscUJBQWEsT0FBTyxNQUFNO0FBQUEsZUFDbEIsVUFBVTtBQUVuQixVQUFJO0FBRUosVUFBSSxVQUFVLEdBQUc7QUFDaEIsd0JBQWdCLFdBQVcsV0FBWTtBQUN0QyxpQkFBTyxNQUFNLGFBQWEsT0FBTyw2QkFBNkI7QUFBQSxXQUM1RDtBQUFBO0FBSUosZ0JBQVUsY0FBYztBQUFBLFFBQ3ZCO0FBQUEsUUFDQTtBQUFBLFFBQ0E7QUFBQTtBQUdELFVBQUk7QUFDSCxjQUFNLFVBQVU7QUFBQSxVQUNmO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQTtBQUlELGVBQU8sWUFBWSxNQUFNLEtBQUssVUFBVTtBQUFBLGVBQ2hDLEdBQVA7QUFFRCxnQkFBUSxNQUFNO0FBQUE7QUFBQTtBQUFBO0FBY1Ysb0JBQWtCLGlCQUFpQjtBQUV6QyxRQUFJO0FBQ0osUUFBSTtBQUNILGdCQUFVLEtBQUssTUFBTTtBQUFBLGFBQ2IsR0FBUDtBQUNELFlBQU0sUUFBUSxvQ0FBb0MsRUFBRSxxQkFBcUI7QUFDekUsY0FBUSxTQUFTO0FBQ2pCLFlBQU0sSUFBSSxNQUFNO0FBQUE7QUFFakIsUUFBSSxhQUFhLFFBQVE7QUFDekIsUUFBSSxlQUFlLFVBQVU7QUFDN0IsUUFBSSxDQUFDLGNBQWM7QUFDbEIsWUFBTSxRQUFRLGFBQWE7QUFDM0IsY0FBUSxNQUFNO0FBQ2QsWUFBTSxJQUFJLE1BQU07QUFBQTtBQUVqQixpQkFBYSxhQUFhO0FBRTFCLFdBQU8sVUFBVTtBQUVqQixRQUFJLFFBQVEsT0FBTztBQUNsQixtQkFBYSxPQUFPLFFBQVE7QUFBQSxXQUN0QjtBQUNOLG1CQUFhLFFBQVEsUUFBUTtBQUFBO0FBQUE7OztBQzFIL0IsU0FBTyxLQUFLO0FBRUwsdUJBQXFCLGFBQWE7QUFDeEMsUUFBSTtBQUNILG9CQUFjLEtBQUssTUFBTTtBQUFBLGFBQ2pCLEdBQVA7QUFDRCxjQUFRLE1BQU07QUFBQTtBQUlmLFdBQU8sS0FBSyxPQUFPLE1BQU07QUFHekIsV0FBTyxLQUFLLGFBQWEsUUFBUSxDQUFDLGdCQUFnQjtBQUdqRCxhQUFPLEdBQUcsZUFBZSxPQUFPLEdBQUcsZ0JBQWdCO0FBR25ELGFBQU8sS0FBSyxZQUFZLGNBQWMsUUFBUSxDQUFDLGVBQWU7QUFHN0QsZUFBTyxHQUFHLGFBQWEsY0FBYyxPQUFPLEdBQUcsYUFBYSxlQUFlO0FBRTNFLGVBQU8sS0FBSyxZQUFZLGFBQWEsYUFBYSxRQUFRLENBQUMsZUFBZTtBQUV6RSxpQkFBTyxHQUFHLGFBQWEsWUFBWSxjQUFjLFdBQVk7QUFHNUQsZ0JBQUksVUFBVTtBQUdkLCtCQUFtQjtBQUNsQixvQkFBTSxPQUFPLEdBQUcsTUFBTSxLQUFLO0FBQzNCLHFCQUFPLEtBQUssQ0FBQyxhQUFhLFlBQVksWUFBWSxLQUFLLE1BQU0sTUFBTTtBQUFBO0FBSXBFLG9CQUFRLGFBQWEsU0FBVSxZQUFZO0FBQzFDLHdCQUFVO0FBQUE7QUFJWCxvQkFBUSxhQUFhLFdBQVk7QUFDaEMscUJBQU87QUFBQTtBQUdSLG1CQUFPO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTs7O0FDN0RaO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQWVPLDBCQUF3QjtBQUMzQixXQUFPLFNBQVM7QUFBQTtBQUdiLDZCQUEyQjtBQUM5QixXQUFPLFlBQVk7QUFBQTtBQUdoQix5Q0FBdUM7QUFDMUMsV0FBTyxZQUFZO0FBQUE7QUFHaEIsaUNBQStCO0FBQ2xDLFdBQU8sWUFBWTtBQUFBO0FBR2hCLGdDQUE4QjtBQUNqQyxXQUFPLFlBQVk7QUFBQTtBQVFoQiwwQkFBd0I7QUFDM0IsV0FBTyxZQUFZO0FBQUE7QUFTaEIsMEJBQXdCLE9BQU87QUFDbEMsV0FBTyxZQUFZLE9BQU87QUFBQTtBQVF2Qiw4QkFBNEI7QUFDL0IsV0FBTyxZQUFZO0FBQUE7QUFRaEIsZ0NBQThCO0FBQ2pDLFdBQU8sWUFBWTtBQUFBO0FBVWhCLHlCQUF1QixPQUFPLFFBQVE7QUFDekMsV0FBTyxZQUFZLFFBQVEsUUFBUSxNQUFNO0FBQUE7QUFVdEMsMkJBQXlCO0FBQzVCLFdBQU8sS0FBSztBQUFBO0FBVVQsNEJBQTBCLE9BQU8sUUFBUTtBQUM1QyxXQUFPLFlBQVksUUFBUSxRQUFRLE1BQU07QUFBQTtBQVV0Qyw0QkFBMEIsT0FBTyxRQUFRO0FBQzVDLFdBQU8sWUFBWSxRQUFRLFFBQVEsTUFBTTtBQUFBO0FBVXRDLGdDQUE4QixHQUFHO0FBRXBDLFdBQU8sWUFBWSxVQUFXLEtBQUksTUFBTTtBQUFBO0FBYXJDLDZCQUEyQixHQUFHLEdBQUc7QUFDcEMsV0FBTyxZQUFZLFFBQVEsSUFBSSxNQUFNO0FBQUE7QUFTbEMsK0JBQTZCO0FBQ2hDLFdBQU8sS0FBSztBQUFBO0FBUVQsd0JBQXNCO0FBQ3pCLFdBQU8sWUFBWTtBQUFBO0FBUWhCLHdCQUFzQjtBQUN6QixXQUFPLFlBQVk7QUFBQTtBQVFoQiw0QkFBMEI7QUFDN0IsV0FBTyxZQUFZO0FBQUE7QUFRaEIsa0NBQWdDO0FBQ25DLFdBQU8sWUFBWTtBQUFBO0FBUWhCLDhCQUE0QjtBQUMvQixXQUFPLFlBQVk7QUFBQTtBQVFoQiw0QkFBMEI7QUFDN0IsV0FBTyxZQUFZO0FBQUE7QUFRaEIsOEJBQTRCO0FBQy9CLFdBQU8sWUFBWTtBQUFBO0FBWWhCLHFDQUFtQyxHQUFHLEdBQUcsR0FBRyxHQUFHO0FBQ2xELFFBQUksT0FBTyxLQUFLLFVBQVUsRUFBRSxHQUFHLEtBQUssR0FBRyxHQUFHLEtBQUssR0FBRyxHQUFHLEtBQUssR0FBRyxHQUFHLEtBQUs7QUFDckUsV0FBTyxZQUFZLFFBQVE7QUFBQTs7O0FDbE8vQjtBQUFBO0FBQUE7QUFBQTtBQUtPLDBCQUF3QixLQUFLO0FBQ2xDLFdBQU8sWUFBWSxRQUFRO0FBQUE7OztBQ1l0QixrQkFBZ0I7QUFDbkIsV0FBTyxZQUFZO0FBQUE7QUFHaEIseUJBQXVCO0FBQzFCLFdBQU8sS0FBSztBQUFBO0FBSWhCLFNBQU8sVUFBVTtBQUFBLE9BQ1Y7QUFBQSxPQUNBO0FBQUEsT0FDQTtBQUFBLElBQ0g7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQTtBQUlKLFNBQU8sUUFBUTtBQUFBLElBQ1g7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQSxPQUFPO0FBQUEsTUFDSCxzQkFBc0I7QUFBQSxNQUN0QixnQ0FBZ0M7QUFBQSxNQUNoQyxjQUFjO0FBQUEsTUFDZCxlQUFlO0FBQUEsTUFDZixpQkFBaUI7QUFBQSxNQUNqQixpQkFBaUI7QUFBQTtBQUFBO0FBS3pCLFNBQU8sTUFBTSxZQUFZLE9BQU87QUFDaEMsU0FBTyxPQUFPLE1BQU07QUFLcEIsTUFBSSxNQUFXO0FBQ1gsV0FBTyxPQUFPO0FBQUE7QUFHbEIsTUFBSTtBQUNKLE1BQUksZUFBZTtBQUVuQixrQkFBZ0I7QUFDWixXQUFPLFlBQVk7QUFBQTtBQUt2QixTQUFPLGlCQUFpQixhQUFhLENBQUMsTUFBTTtBQUd4QyxRQUFJLE9BQU8sTUFBTSxNQUFNLFlBQVk7QUFDL0IsYUFBTyxZQUFZLFlBQVksT0FBTyxNQUFNLE1BQU07QUFDbEQsUUFBRTtBQUNGO0FBQUE7QUFJSixRQUFJLGlCQUFpQixFQUFFO0FBQ3ZCLFdBQU8sa0JBQWtCLE1BQU07QUFDM0IsVUFBSSxlQUFlLGFBQWEsdUJBQXVCO0FBQ25EO0FBQUEsaUJBQ08sZUFBZSxhQUFhLG9CQUFvQjtBQUN2RCxZQUFJLE9BQU8sTUFBTSxNQUFNLHNCQUFzQjtBQUV6QyxjQUFJLEVBQUUsVUFBVSxFQUFFLE9BQU8sZUFBZSxFQUFFLFVBQVUsRUFBRSxPQUFPLGNBQWM7QUFDdkU7QUFBQTtBQUFBO0FBR1IsWUFBSSxJQUFJLE9BQU8sWUFBWSxlQUFlLE9BQU8sTUFBTSxNQUFNLGlCQUFpQjtBQUMxRSx1QkFBYTtBQUNiO0FBQUE7QUFFSixzQkFBYyxXQUFXLE1BQU0sT0FBTyxNQUFNLE1BQU07QUFDbEQsdUJBQWUsSUFBSSxPQUFPO0FBQzFCLFVBQUU7QUFDRjtBQUFBO0FBRUosdUJBQWlCLGVBQWU7QUFBQTtBQUFBO0FBSXhDLHFCQUFtQixRQUFRO0FBQ3ZCLGFBQVMsS0FBSyxNQUFNLFNBQVMsVUFBVSxPQUFPLE1BQU0sTUFBTTtBQUMxRCxXQUFPLE1BQU0sTUFBTSxhQUFhO0FBQUE7QUFHcEMsU0FBTyxpQkFBaUIsYUFBYSxTQUFVLEdBQUc7QUFDOUMsUUFBSSxDQUFDLE9BQU8sTUFBTSxNQUFNLGNBQWM7QUFDbEM7QUFBQTtBQUVKLFFBQUksT0FBTyxNQUFNLE1BQU0saUJBQWlCLE1BQU07QUFDMUMsYUFBTyxNQUFNLE1BQU0sZ0JBQWdCLFNBQVMsS0FBSyxNQUFNO0FBQUE7QUFFM0QsUUFBSSxPQUFPLGFBQWEsRUFBRSxVQUFVLE9BQU8sTUFBTSxNQUFNLG1CQUFtQixPQUFPLGNBQWMsRUFBRSxVQUFVLE9BQU8sTUFBTSxNQUFNLGlCQUFpQjtBQUMzSSxlQUFTLEtBQUssTUFBTSxTQUFTO0FBQUE7QUFFakMsUUFBSSxjQUFjLE9BQU8sYUFBYSxFQUFFLFVBQVUsT0FBTyxNQUFNLE1BQU07QUFDckUsUUFBSSxhQUFhLEVBQUUsVUFBVSxPQUFPLE1BQU0sTUFBTTtBQUNoRCxRQUFJLFlBQVksRUFBRSxVQUFVLE9BQU8sTUFBTSxNQUFNO0FBQy9DLFFBQUksZUFBZSxPQUFPLGNBQWMsRUFBRSxVQUFVLE9BQU8sTUFBTSxNQUFNO0FBR3ZFLFFBQUksQ0FBQyxjQUFjLENBQUMsZUFBZSxDQUFDLGFBQWEsQ0FBQyxnQkFBZ0IsT0FBTyxNQUFNLE1BQU0sZUFBZSxRQUFXO0FBQzNHO0FBQUEsZUFDTyxlQUFlO0FBQWMsZ0JBQVU7QUFBQSxhQUN6QyxjQUFjO0FBQWMsZ0JBQVU7QUFBQSxhQUN0QyxjQUFjO0FBQVcsZ0JBQVU7QUFBQSxhQUNuQyxhQUFhO0FBQWEsZ0JBQVU7QUFBQSxhQUNwQztBQUFZLGdCQUFVO0FBQUEsYUFDdEI7QUFBVyxnQkFBVTtBQUFBLGFBQ3JCO0FBQWMsZ0JBQVU7QUFBQSxhQUN4QjtBQUFhLGdCQUFVO0FBQUE7QUFLcEMsU0FBTyxpQkFBaUIsZUFBZSxTQUFVLEdBQUc7QUFDaEQsUUFBSSxPQUFPLE1BQU0sTUFBTSxnQ0FBZ0M7QUFDbkQsUUFBRTtBQUFBO0FBQUE7IiwKICAibmFtZXMiOiBbXQp9Cg==
diff --git a/v2/internal/frontend/runtime/runtime_prod_desktop.js b/v2/internal/frontend/runtime/runtime_prod_desktop.js
index c98ae9063..51ef29128 100644
--- a/v2/internal/frontend/runtime/runtime_prod_desktop.js
+++ b/v2/internal/frontend/runtime/runtime_prod_desktop.js
@@ -1 +1 @@
-(()=>{var m=Object.defineProperty;var D=e=>m(e,"__esModule",{value:!0});var W=(e,n)=>{D(e);for(var o in n)m(e,o,{get:n[o],enumerable:!0})};var g={};W(g,{LogDebug:()=>B,LogError:()=>J,LogFatal:()=>G,LogInfo:()=>A,LogLevel:()=>U,LogPrint:()=>R,LogTrace:()=>C,LogWarning:()=>H,SetLogLevel:()=>M});function w(e,n){window.WailsInvoke("L"+e+n)}function C(e){w("T",e)}function R(e){w("P",e)}function B(e){w("D",e)}function A(e){w("I",e)}function H(e){w("W",e)}function J(e){w("E",e)}function G(e){w("F",e)}function M(e){w("S",e)}var U={TRACE:1,DEBUG:2,INFO:3,WARNING:4,ERROR:5};var k=class{constructor(n,o){o=o||-1,this.Callback=i=>(n.apply(null,i),o===-1?!1:(o-=1,o===0))}},s={};function c(e,n,o){s[e]=s[e]||[];let i=new k(n,o);s[e].push(i)}function b(e,n){c(e,n,-1)}function E(e,n){c(e,n,1)}function I(e){let n=e.name;if(s[n]){let o=s[n].slice();for(let i=0;i0&&(a=setTimeout(function(){t(Error("Call to "+e+" timed out. Request ID: "+r))},o)),f[r]={timeoutHandle:a,reject:t,resolve:i};try{let u={name:e,args:n,callbackID:r};window.WailsInvoke("C"+JSON.stringify(u))}catch(u){console.error(u)}})}function T(e){let n;try{n=JSON.parse(e)}catch(t){let r=`Invalid JSON passed to callback: ${t.message}. Message: ${e}`;throw runtime.LogDebug(r),new Error(r)}let o=n.callbackid,i=f[o];if(!i){let t=`Callback '${o}' not registered!!!`;throw console.error(t),new Error(t)}clearTimeout(i.timeoutHandle),delete f[o],n.error?i.reject(n.error):i.resolve(n.result)}window.go={};function L(e){try{e=JSON.parse(e)}catch(n){console.error(n)}window.go=window.go||{},Object.keys(e).forEach(n=>{window.go[n]=window.go[n]||{},Object.keys(e[n]).forEach(o=>{window.go[n][o]=window.go[n][o]||{},Object.keys(e[n][o]).forEach(i=>{window.go[n][o][i]=function(){let t=0;function r(){let a=[].slice.call(arguments);return d([n,o,i].join("."),a,t)}return r.setTimeout=function(a){t=a},r.getTimeout=function(){return t},r}()})})})}var v={};W(v,{WindowCenter:()=>V,WindowFullscreen:()=>N,WindowGetPosition:()=>ie,WindowGetSize:()=>_,WindowHide:()=>te,WindowMaximise:()=>se,WindowMinimise:()=>ae,WindowReload:()=>j,WindowReloadApp:()=>X,WindowSetDarkTheme:()=>Q,WindowSetLightTheme:()=>$,WindowSetMaxSize:()=>ee,WindowSetMinSize:()=>ne,WindowSetPosition:()=>oe,WindowSetRGBA:()=>fe,WindowSetSize:()=>K,WindowSetSystemDefaultTheme:()=>Y,WindowSetTitle:()=>q,WindowShow:()=>re,WindowToggleMaximise:()=>le,WindowUnfullscreen:()=>Z,WindowUnmaximise:()=>we,WindowUnminimise:()=>de});function j(){window.location.reload()}function X(){window.WailsInvoke("WR")}function Y(){window.WailsInvoke("WASDT")}function $(){window.WailsInvoke("WALT")}function Q(){window.WailsInvoke("WADT")}function V(){window.WailsInvoke("Wc")}function q(e){window.WailsInvoke("WT"+e)}function N(){window.WailsInvoke("WF")}function Z(){window.WailsInvoke("Wf")}function K(e,n){window.WailsInvoke("Ws:"+e+":"+n)}function _(){return d(":wails:WindowGetSize")}function ee(e,n){window.WailsInvoke("WZ:"+e+":"+n)}function ne(e,n){window.WailsInvoke("Wz:"+e+":"+n)}function oe(e,n){window.WailsInvoke("Wp:"+e+":"+n)}function ie(){return d(":wails:WindowGetPos")}function te(){window.WailsInvoke("WH")}function re(){window.WailsInvoke("WS")}function se(){window.WailsInvoke("WM")}function le(){window.WailsInvoke("Wt")}function we(){window.WailsInvoke("WU")}function ae(){window.WailsInvoke("Wm")}function de(){window.WailsInvoke("Wu")}function fe(e,n,o,i){let t=JSON.stringify({r:e||0,g:n||0,b:o||0,a:i||255});window.WailsInvoke("Wr:"+t)}var x={};W(x,{BrowserOpenURL:()=>ce});function ce(e){window.WailsInvoke("BO:"+e)}function ue(){window.WailsInvoke("Q")}function We(){return d(":wails:Environment")}window.runtime={...g,...v,...x,EventsOn:b,EventsOnce:E,EventsOnMultiple:c,EventsEmit:S,EventsOff:y,Environment:We,Quit:ue};window.wails={Callback:T,EventsNotify:h,SetBindings:L,eventListeners:s,callbacks:f,flags:{disableScrollbarDrag:!1,disableWailsDefaultContextMenu:!1,enableResize:!1,defaultCursor:null,borderThickness:6,dbClickInterval:100}};window.wails.SetBindings(window.wailsbindings);delete window.wails.SetBindings;var O,z=0;function ge(){window.WailsInvoke("drag")}window.addEventListener("mousedown",e=>{if(window.wails.flags.resizeEdge){window.WailsInvoke("resize:"+window.wails.flags.resizeEdge),e.preventDefault();return}let n=e.target;for(;n!=null&&!n.hasAttribute("data-wails-no-drag");){if(n.hasAttribute("data-wails-drag")){if(window.wails.flags.disableScrollbarDrag&&(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight))break;if(new Date().getTime()-z{var k=Object.defineProperty;var D=e=>k(e,"__esModule",{value:!0});var W=(e,n)=>{D(e);for(var o in n)k(e,o,{get:n[o],enumerable:!0})};var g={};W(g,{LogDebug:()=>B,LogError:()=>J,LogFatal:()=>M,LogInfo:()=>A,LogLevel:()=>U,LogPrint:()=>R,LogTrace:()=>C,LogWarning:()=>H,SetLogLevel:()=>P});function w(e,n){window.WailsInvoke("L"+e+n)}function C(e){w("T",e)}function R(e){w("P",e)}function B(e){w("D",e)}function A(e){w("I",e)}function H(e){w("W",e)}function J(e){w("E",e)}function M(e){w("F",e)}function P(e){w("S",e)}var U={TRACE:1,DEBUG:2,INFO:3,WARNING:4,ERROR:5};var m=class{constructor(n,o){o=o||-1,this.Callback=i=>(n.apply(null,i),o===-1?!1:(o-=1,o===0))}},s={};function c(e,n,o){s[e]=s[e]||[];let i=new m(n,o);s[e].push(i)}function b(e,n){c(e,n,-1)}function E(e,n){c(e,n,1)}function I(e){let n=e.name;if(s[n]){let o=s[n].slice();for(let i=0;i0&&(a=setTimeout(function(){t(Error("Call to "+e+" timed out. Request ID: "+r))},o)),f[r]={timeoutHandle:a,reject:t,resolve:i};try{let u={name:e,args:n,callbackID:r};window.WailsInvoke("C"+JSON.stringify(u))}catch(u){console.error(u)}})}function T(e){let n;try{n=JSON.parse(e)}catch(t){let r=`Invalid JSON passed to callback: ${t.message}. Message: ${e}`;throw runtime.LogDebug(r),new Error(r)}let o=n.callbackid,i=f[o];if(!i){let t=`Callback '${o}' not registered!!!`;throw console.error(t),new Error(t)}clearTimeout(i.timeoutHandle),delete f[o],n.error?i.reject(n.error):i.resolve(n.result)}window.go={};function L(e){try{e=JSON.parse(e)}catch(n){console.error(n)}window.go=window.go||{},Object.keys(e).forEach(n=>{window.go[n]=window.go[n]||{},Object.keys(e[n]).forEach(o=>{window.go[n][o]=window.go[n][o]||{},Object.keys(e[n][o]).forEach(i=>{window.go[n][o][i]=function(){let t=0;function r(){let a=[].slice.call(arguments);return d([n,o,i].join("."),a,t)}return r.setTimeout=function(a){t=a},r.getTimeout=function(){return t},r}()})})})}var v={};W(v,{WindowCenter:()=>V,WindowFullscreen:()=>N,WindowGetPosition:()=>te,WindowGetSize:()=>_,WindowHide:()=>re,WindowMaximise:()=>le,WindowMinimise:()=>de,WindowReload:()=>j,WindowReloadApp:()=>X,WindowSetAlwaysOnTop:()=>oe,WindowSetBackgroundColour:()=>ce,WindowSetDarkTheme:()=>Q,WindowSetLightTheme:()=>$,WindowSetMaxSize:()=>ee,WindowSetMinSize:()=>ne,WindowSetPosition:()=>ie,WindowSetSize:()=>K,WindowSetSystemDefaultTheme:()=>Y,WindowSetTitle:()=>q,WindowShow:()=>se,WindowToggleMaximise:()=>we,WindowUnfullscreen:()=>Z,WindowUnmaximise:()=>ae,WindowUnminimise:()=>fe});function j(){window.location.reload()}function X(){window.WailsInvoke("WR")}function Y(){window.WailsInvoke("WASDT")}function $(){window.WailsInvoke("WALT")}function Q(){window.WailsInvoke("WADT")}function V(){window.WailsInvoke("Wc")}function q(e){window.WailsInvoke("WT"+e)}function N(){window.WailsInvoke("WF")}function Z(){window.WailsInvoke("Wf")}function K(e,n){window.WailsInvoke("Ws:"+e+":"+n)}function _(){return d(":wails:WindowGetSize")}function ee(e,n){window.WailsInvoke("WZ:"+e+":"+n)}function ne(e,n){window.WailsInvoke("Wz:"+e+":"+n)}function oe(e){window.WailsInvoke("WATP:"+(e?"1":"0"))}function ie(e,n){window.WailsInvoke("Wp:"+e+":"+n)}function te(){return d(":wails:WindowGetPos")}function re(){window.WailsInvoke("WH")}function se(){window.WailsInvoke("WS")}function le(){window.WailsInvoke("WM")}function we(){window.WailsInvoke("Wt")}function ae(){window.WailsInvoke("WU")}function de(){window.WailsInvoke("Wm")}function fe(){window.WailsInvoke("Wu")}function ce(e,n,o,i){let t=JSON.stringify({r:e||0,g:n||0,b:o||0,a:i||255});window.WailsInvoke("Wr:"+t)}var x={};W(x,{BrowserOpenURL:()=>ue});function ue(e){window.WailsInvoke("BO:"+e)}function We(){window.WailsInvoke("Q")}function ge(){return d(":wails:Environment")}window.runtime={...g,...v,...x,EventsOn:b,EventsOnce:E,EventsOnMultiple:c,EventsEmit:S,EventsOff:y,Environment:ge,Quit:We};window.wails={Callback:T,EventsNotify:h,SetBindings:L,eventListeners:s,callbacks:f,flags:{disableScrollbarDrag:!1,disableWailsDefaultContextMenu:!1,enableResize:!1,defaultCursor:null,borderThickness:6,dbClickInterval:100}};window.wails.SetBindings(window.wailsbindings);delete window.wails.SetBindings;var O,z=0;function pe(){window.WailsInvoke("drag")}window.addEventListener("mousedown",e=>{if(window.wails.flags.resizeEdge){window.WailsInvoke("resize:"+window.wails.flags.resizeEdge),e.preventDefault();return}let n=e.target;for(;n!=null&&!n.hasAttribute("data-wails-no-drag");){if(n.hasAttribute("data-wails-drag")){if(window.wails.flags.disableScrollbarDrag&&(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight))break;if(new Date().getTime()-z;
// [Quit](https://wails.io/docs/reference/runtime/intro#quit)
// Quits the application.
diff --git a/v2/internal/frontend/runtime/wrapper/runtime.js b/v2/internal/frontend/runtime/wrapper/runtime.js
index 8f47e62f1..73f607ba7 100644
--- a/v2/internal/frontend/runtime/wrapper/runtime.js
+++ b/v2/internal/frontend/runtime/wrapper/runtime.js
@@ -41,7 +41,7 @@ export function EventsOnMultiple(eventName, callback, maxCallbacks) {
}
export function EventsOn(eventName, callback) {
- OnMultiple(eventName, callback, -1);
+ EventsOnMultiple(eventName, callback, -1);
}
export function EventsOff(eventName) {
@@ -49,7 +49,7 @@ export function EventsOff(eventName) {
}
export function EventsOnce(eventName, callback) {
- OnMultiple(eventName, callback, 1);
+ EventsOnMultiple(eventName, callback, 1);
}
export function EventsEmit(eventName) {
@@ -145,8 +145,8 @@ export function WindowUnminimise() {
window.runtime.WindowUnminimise();
}
-export function WindowSetRGBA(RGBA) {
- window.runtime.WindowSetRGBA(RGBA);
+export function WindowSetBackgroundColour(R, G, B, A) {
+ window.runtime.WindowSetBackgroundColour(R, G, B, A);
}
export function BrowserOpenURL(url) {
diff --git a/v2/internal/go-common-file-dialog/LICENSE b/v2/internal/go-common-file-dialog/LICENSE
new file mode 100644
index 000000000..508b6978e
--- /dev/null
+++ b/v2/internal/go-common-file-dialog/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 Harry Phillips
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/v2/internal/go-common-file-dialog/README.md b/v2/internal/go-common-file-dialog/README.md
new file mode 100644
index 000000000..1cb5902d1
--- /dev/null
+++ b/v2/internal/go-common-file-dialog/README.md
@@ -0,0 +1,31 @@
+# Common File Dialog bindings for Golang
+
+[Project Home](https://github.com/harry1453/go-common-file-dialog)
+
+This library contains bindings for Windows Vista and
+newer's [Common File Dialogs](https://docs.microsoft.com/en-us/windows/win32/shell/common-file-dialog), which is the
+standard system dialog for selecting files or folders to open or save.
+
+The Common File Dialogs have to be accessed via
+the [COM Interface](https://en.wikipedia.org/wiki/Component_Object_Model), normally via C++ or via bindings (like in C#)
+.
+
+This library contains bindings for Golang. **It does not require CGO**, and contains empty stubs for non-windows
+platforms (so is safe to compile and run on platforms other than windows, but will just return errors at runtime).
+
+This can be very useful if you want to quickly get a file selector in your Golang application. The `cfdutil` package
+contains utility functions with a single call to open and configure a dialog, and then get the result from it. Examples
+for this are in [`_examples/usingutil`](_examples/usingutil). Or, if you want finer control over the dialog's operation,
+you can use the base package. Examples for this are in [`_examples/notusingutil`](_examples/notusingutil).
+
+This library is available under the MIT license.
+
+Currently supported features:
+
+* Open File Dialog (to open a single file)
+* Open Multiple Files Dialog (to open multiple files)
+* Open Folder Dialog
+* Save File Dialog
+* Dialog "roles" to allow Windows to remember different "last locations" for different types of dialog
+* Set dialog Title, Default Folder and Initial Folder
+* Set dialog File Filters
diff --git a/v2/internal/go-common-file-dialog/cfd/CommonFileDialog.go b/v2/internal/go-common-file-dialog/cfd/CommonFileDialog.go
new file mode 100644
index 000000000..58e97aa4e
--- /dev/null
+++ b/v2/internal/go-common-file-dialog/cfd/CommonFileDialog.go
@@ -0,0 +1,72 @@
+// Cross-platform.
+
+// Common File Dialogs
+package cfd
+
+type Dialog interface {
+ // Show the dialog to the user.
+ // Blocks until the user has closed the dialog.
+ Show() error
+ // Sets the dialog's parent window. Use 0 to set the dialog to have no parent window.
+ SetParentWindowHandle(hwnd uintptr)
+ // Show the dialog to the user.
+ // Blocks until the user has closed the dialog and returns their selection.
+ // Returns an error if the user cancelled the dialog.
+ // Do not use for the Open Multiple Files dialog. Use ShowAndGetResults instead.
+ ShowAndGetResult() (string, error)
+ // Sets the title of the dialog window.
+ SetTitle(title string) error
+ // Sets the "role" of the dialog. This is used to derive the dialog's GUID, which the
+ // OS will use to differentiate it from dialogs that are intended for other purposes.
+ // This means that, for example, a dialog with role "Import" will have a different
+ // previous location that it will open to than a dialog with role "Open". Can be any string.
+ SetRole(role string) error
+ // Sets the folder used as a default if there is not a recently used folder value available
+ SetDefaultFolder(defaultFolder string) error
+ // Sets the folder that the dialog always opens to.
+ // If this is set, it will override the "default folder" behaviour and the dialog will always open to this folder.
+ SetFolder(folder string) error
+ // Gets the selected file or folder path, as an absolute path eg. "C:\Folder\file.txt"
+ // Do not use for the Open Multiple Files dialog. Use GetResults instead.
+ GetResult() (string, error)
+ // Sets the file name, I.E. the contents of the file name text box.
+ // For Select Folder Dialog, sets folder name.
+ SetFileName(fileName string) error
+ // Release the resources allocated to this Dialog.
+ // Should be called when the dialog is finished with.
+ Release() error
+}
+
+type FileDialog interface {
+ Dialog
+ // Set the list of file filters that the user can select.
+ SetFileFilters(fileFilter []FileFilter) error
+ // Set the selected item from the list of file filters (set using SetFileFilters) by its index. Defaults to 0 (the first item in the list) if not called.
+ SetSelectedFileFilterIndex(index uint) error
+ // Sets the default extension applied when a user does not provide one as part of the file name.
+ // If the user selects a different file filter, the default extension will be automatically updated to match the new file filter.
+ // For Open / Open Multiple File Dialog, this only has an effect when the user specifies a file name with no extension and a file with the default extension exists.
+ // For Save File Dialog, this extension will be used whenever a user does not specify an extension.
+ SetDefaultExtension(defaultExtension string) error
+}
+
+type OpenFileDialog interface {
+ FileDialog
+}
+
+type OpenMultipleFilesDialog interface {
+ FileDialog
+ // Show the dialog to the user.
+ // Blocks until the user has closed the dialog and returns the selected files.
+ ShowAndGetResults() ([]string, error)
+ // Gets the selected file paths, as absolute paths eg. "C:\Folder\file.txt"
+ GetResults() ([]string, error)
+}
+
+type SelectFolderDialog interface {
+ Dialog
+}
+
+type SaveFileDialog interface { // TODO Properties
+ FileDialog
+}
diff --git a/v2/internal/go-common-file-dialog/cfd/CommonFileDialog_nonWindows.go b/v2/internal/go-common-file-dialog/cfd/CommonFileDialog_nonWindows.go
new file mode 100644
index 000000000..3ab969850
--- /dev/null
+++ b/v2/internal/go-common-file-dialog/cfd/CommonFileDialog_nonWindows.go
@@ -0,0 +1,28 @@
+//go:build !windows
+// +build !windows
+
+package cfd
+
+import "fmt"
+
+var unsupportedError = fmt.Errorf("common file dialogs are only available on windows")
+
+// TODO doc
+func NewOpenFileDialog(config DialogConfig) (OpenFileDialog, error) {
+ return nil, unsupportedError
+}
+
+// TODO doc
+func NewOpenMultipleFilesDialog(config DialogConfig) (OpenMultipleFilesDialog, error) {
+ return nil, unsupportedError
+}
+
+// TODO doc
+func NewSelectFolderDialog(config DialogConfig) (SelectFolderDialog, error) {
+ return nil, unsupportedError
+}
+
+// TODO doc
+func NewSaveFileDialog(config DialogConfig) (SaveFileDialog, error) {
+ return nil, unsupportedError
+}
diff --git a/v2/internal/go-common-file-dialog/cfd/CommonFileDialog_windows.go b/v2/internal/go-common-file-dialog/cfd/CommonFileDialog_windows.go
new file mode 100644
index 000000000..69f46118e
--- /dev/null
+++ b/v2/internal/go-common-file-dialog/cfd/CommonFileDialog_windows.go
@@ -0,0 +1,79 @@
+//go:build windows
+// +build windows
+
+package cfd
+
+import "github.com/go-ole/go-ole"
+
+func initialize() {
+ // Swallow error
+ _ = ole.CoInitializeEx(0, ole.COINIT_APARTMENTTHREADED|ole.COINIT_DISABLE_OLE1DDE)
+}
+
+// TODO doc
+func NewOpenFileDialog(config DialogConfig) (OpenFileDialog, error) {
+ initialize()
+
+ openDialog, err := newIFileOpenDialog()
+ if err != nil {
+ return nil, err
+ }
+ err = config.apply(openDialog)
+ if err != nil {
+ return nil, err
+ }
+ return openDialog, nil
+}
+
+// TODO doc
+func NewOpenMultipleFilesDialog(config DialogConfig) (OpenMultipleFilesDialog, error) {
+ initialize()
+
+ openDialog, err := newIFileOpenDialog()
+ if err != nil {
+ return nil, err
+ }
+ err = config.apply(openDialog)
+ if err != nil {
+ return nil, err
+ }
+ err = openDialog.setIsMultiselect(true)
+ if err != nil {
+ return nil, err
+ }
+ return openDialog, nil
+}
+
+// TODO doc
+func NewSelectFolderDialog(config DialogConfig) (SelectFolderDialog, error) {
+ initialize()
+
+ openDialog, err := newIFileOpenDialog()
+ if err != nil {
+ return nil, err
+ }
+ err = config.apply(openDialog)
+ if err != nil {
+ return nil, err
+ }
+ err = openDialog.setPickFolders(true)
+ if err != nil {
+ return nil, err
+ }
+ return openDialog, nil
+}
+
+// TODO doc
+func NewSaveFileDialog(config DialogConfig) (SaveFileDialog, error) {
+ initialize()
+
+ saveDialog, err := newIFileSaveDialog()
+ if err != nil {
+ return nil, err
+ }
+ err = config.apply(saveDialog)
+ if err != nil {
+ return nil, err
+ }
+ return saveDialog, nil
+}
diff --git a/v2/internal/go-common-file-dialog/cfd/DialogConfig.go b/v2/internal/go-common-file-dialog/cfd/DialogConfig.go
new file mode 100644
index 000000000..221dbef27
--- /dev/null
+++ b/v2/internal/go-common-file-dialog/cfd/DialogConfig.go
@@ -0,0 +1,120 @@
+// Cross-platform.
+
+package cfd
+
+type FileFilter struct {
+ // The display name of the filter (That is shown to the user)
+ DisplayName string
+ // The filter pattern. Eg. "*.txt;*.png" to select all txt and png files, "*.*" to select any files, etc.
+ Pattern string
+}
+
+type DialogConfig struct {
+ // The title of the dialog
+ Title string
+ // The role of the dialog. This is used to derive the dialog's GUID, which the
+ // OS will use to differentiate it from dialogs that are intended for other purposes.
+ // This means that, for example, a dialog with role "Import" will have a different
+ // previous location that it will open to than a dialog with role "Open". Can be any string.
+ Role string
+ // The default folder - the folder that is used the first time the user opens it
+ // (after the first time their last used location is used).
+ DefaultFolder string
+ // The initial folder - the folder that the dialog always opens to if not empty.
+ // If this is not empty, it will override the "default folder" behaviour and
+ // the dialog will always open to this folder.
+ Folder string
+ // The file filters that restrict which types of files the dialog is able to choose.
+ // Ignored by Select Folder Dialog.
+ FileFilters []FileFilter
+ // Sets the initially selected file filter. This is an index of FileFilters.
+ // Ignored by Select Folder Dialog.
+ SelectedFileFilterIndex uint
+ // The initial name of the file (I.E. the text in the file name text box) when the user opens the dialog.
+ // For the Select Folder Dialog, this sets the initial folder name.
+ FileName string
+ // The default extension applied when a user does not provide one as part of the file name.
+ // If the user selects a different file filter, the default extension will be automatically updated to match the new file filter.
+ // For Open / Open Multiple File Dialog, this only has an effect when the user specifies a file name with no extension and a file with the default extension exists.
+ // For Save File Dialog, this extension will be used whenever a user does not specify an extension.
+ // Ignored by Select Folder Dialog.
+ DefaultExtension string
+ // ParentWindowHandle is the handle (HWND) to the parent window of the dialog.
+ // If left as 0 / nil, the dialog will have no parent window.
+ ParentWindowHandle uintptr
+}
+
+var defaultFilters = []FileFilter{
+ {
+ DisplayName: "All Files (*.*)",
+ Pattern: "*.*",
+ },
+}
+
+func (config *DialogConfig) apply(dialog Dialog) (err error) {
+ if config.Title != "" {
+ err = dialog.SetTitle(config.Title)
+ if err != nil {
+ return
+ }
+ }
+
+ if config.Role != "" {
+ err = dialog.SetRole(config.Role)
+ if err != nil {
+ return
+ }
+ }
+
+ if config.Folder != "" {
+ err = dialog.SetFolder(config.Folder)
+ if err != nil {
+ return
+ }
+ }
+
+ if config.DefaultFolder != "" {
+ err = dialog.SetDefaultFolder(config.DefaultFolder)
+ if err != nil {
+ return
+ }
+ }
+
+ if config.FileName != "" {
+ err = dialog.SetFileName(config.FileName)
+ if err != nil {
+ return
+ }
+ }
+
+ dialog.SetParentWindowHandle(config.ParentWindowHandle)
+
+ if dialog, ok := dialog.(FileDialog); ok {
+ var fileFilters []FileFilter
+ if config.FileFilters != nil && len(config.FileFilters) > 0 {
+ fileFilters = config.FileFilters
+ } else {
+ fileFilters = defaultFilters
+ }
+ err = dialog.SetFileFilters(fileFilters)
+ if err != nil {
+ return
+ }
+
+ if config.SelectedFileFilterIndex != 0 {
+ err = dialog.SetSelectedFileFilterIndex(config.SelectedFileFilterIndex)
+ if err != nil {
+ return
+ }
+ }
+
+ if config.DefaultExtension != "" {
+ err = dialog.SetDefaultExtension(config.DefaultExtension)
+ if err != nil {
+ return
+ }
+ }
+ }
+
+ return
+}
diff --git a/v2/internal/go-common-file-dialog/cfd/errors.go b/v2/internal/go-common-file-dialog/cfd/errors.go
new file mode 100644
index 000000000..c097c8eb2
--- /dev/null
+++ b/v2/internal/go-common-file-dialog/cfd/errors.go
@@ -0,0 +1,7 @@
+package cfd
+
+import "errors"
+
+var (
+ ErrorCancelled = errors.New("cancelled by user")
+)
diff --git a/v2/internal/go-common-file-dialog/cfd/iFileOpenDialog.go b/v2/internal/go-common-file-dialog/cfd/iFileOpenDialog.go
new file mode 100644
index 000000000..8c82cda2c
--- /dev/null
+++ b/v2/internal/go-common-file-dialog/cfd/iFileOpenDialog.go
@@ -0,0 +1,197 @@
+//go:build windows
+// +build windows
+
+package cfd
+
+import (
+ "github.com/go-ole/go-ole"
+ "github.com/wailsapp/wails/v2/internal/go-common-file-dialog/util"
+ "syscall"
+ "unsafe"
+)
+
+var (
+ fileOpenDialogCLSID = ole.NewGUID("{DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7}")
+ fileOpenDialogIID = ole.NewGUID("{d57c7288-d4ad-4768-be02-9d969532d960}")
+)
+
+type iFileOpenDialog struct {
+ vtbl *iFileOpenDialogVtbl
+ parentWindowHandle uintptr
+}
+
+type iFileOpenDialogVtbl struct {
+ iFileDialogVtbl
+
+ GetResults uintptr // func (ppenum **IShellItemArray) HRESULT
+ GetSelectedItems uintptr
+}
+
+func newIFileOpenDialog() (*iFileOpenDialog, error) {
+ if unknown, err := ole.CreateInstance(fileOpenDialogCLSID, fileOpenDialogIID); err == nil {
+ return (*iFileOpenDialog)(unsafe.Pointer(unknown)), nil
+ } else {
+ return nil, err
+ }
+}
+
+func (fileOpenDialog *iFileOpenDialog) Show() error {
+ return fileOpenDialog.vtbl.show(unsafe.Pointer(fileOpenDialog), fileOpenDialog.parentWindowHandle)
+}
+
+func (fileOpenDialog *iFileOpenDialog) SetParentWindowHandle(hwnd uintptr) {
+ fileOpenDialog.parentWindowHandle = hwnd
+}
+
+func (fileOpenDialog *iFileOpenDialog) ShowAndGetResult() (string, error) {
+ isMultiselect, err := fileOpenDialog.isMultiselect()
+ if err != nil {
+ return "", err
+ }
+ if isMultiselect {
+ // We should panic as this error is caused by the developer using the library
+ panic("use ShowAndGetResults for open multiple files dialog")
+ }
+ if err := fileOpenDialog.Show(); err != nil {
+ return "", err
+ }
+ return fileOpenDialog.GetResult()
+}
+
+func (fileOpenDialog *iFileOpenDialog) ShowAndGetResults() ([]string, error) {
+ isMultiselect, err := fileOpenDialog.isMultiselect()
+ if err != nil {
+ return nil, err
+ }
+ if !isMultiselect {
+ // We should panic as this error is caused by the developer using the library
+ panic("use ShowAndGetResult for open single file dialog")
+ }
+ if err := fileOpenDialog.Show(); err != nil {
+ return nil, err
+ }
+ return fileOpenDialog.GetResults()
+}
+
+func (fileOpenDialog *iFileOpenDialog) SetTitle(title string) error {
+ return fileOpenDialog.vtbl.setTitle(unsafe.Pointer(fileOpenDialog), title)
+}
+
+func (fileOpenDialog *iFileOpenDialog) GetResult() (string, error) {
+ isMultiselect, err := fileOpenDialog.isMultiselect()
+ if err != nil {
+ return "", err
+ }
+ if isMultiselect {
+ // We should panic as this error is caused by the developer using the library
+ panic("use GetResults for open multiple files dialog")
+ }
+ return fileOpenDialog.vtbl.getResultString(unsafe.Pointer(fileOpenDialog))
+}
+
+func (fileOpenDialog *iFileOpenDialog) Release() error {
+ return fileOpenDialog.vtbl.release(unsafe.Pointer(fileOpenDialog))
+}
+
+func (fileOpenDialog *iFileOpenDialog) SetDefaultFolder(defaultFolderPath string) error {
+ return fileOpenDialog.vtbl.setDefaultFolder(unsafe.Pointer(fileOpenDialog), defaultFolderPath)
+}
+
+func (fileOpenDialog *iFileOpenDialog) SetFolder(defaultFolderPath string) error {
+ return fileOpenDialog.vtbl.setFolder(unsafe.Pointer(fileOpenDialog), defaultFolderPath)
+}
+
+func (fileOpenDialog *iFileOpenDialog) SetFileFilters(filter []FileFilter) error {
+ return fileOpenDialog.vtbl.setFileTypes(unsafe.Pointer(fileOpenDialog), filter)
+}
+
+func (fileOpenDialog *iFileOpenDialog) SetRole(role string) error {
+ return fileOpenDialog.vtbl.setClientGuid(unsafe.Pointer(fileOpenDialog), util.StringToUUID(role))
+}
+
+// This should only be callable when the user asks for a multi select because
+// otherwise they will be given the Dialog interface which does not expose this function.
+func (fileOpenDialog *iFileOpenDialog) GetResults() ([]string, error) {
+ isMultiselect, err := fileOpenDialog.isMultiselect()
+ if err != nil {
+ return nil, err
+ }
+ if !isMultiselect {
+ // We should panic as this error is caused by the developer using the library
+ panic("use GetResult for open single file dialog")
+ }
+ return fileOpenDialog.vtbl.getResultsStrings(unsafe.Pointer(fileOpenDialog))
+}
+
+func (fileOpenDialog *iFileOpenDialog) SetDefaultExtension(defaultExtension string) error {
+ return fileOpenDialog.vtbl.setDefaultExtension(unsafe.Pointer(fileOpenDialog), defaultExtension)
+}
+
+func (fileOpenDialog *iFileOpenDialog) SetFileName(initialFileName string) error {
+ return fileOpenDialog.vtbl.setFileName(unsafe.Pointer(fileOpenDialog), initialFileName)
+}
+
+func (fileOpenDialog *iFileOpenDialog) SetSelectedFileFilterIndex(index uint) error {
+ return fileOpenDialog.vtbl.setSelectedFileFilterIndex(unsafe.Pointer(fileOpenDialog), index)
+}
+
+func (fileOpenDialog *iFileOpenDialog) setPickFolders(pickFolders bool) error {
+ const FosPickfolders = 0x20
+ if pickFolders {
+ return fileOpenDialog.vtbl.addOption(unsafe.Pointer(fileOpenDialog), FosPickfolders)
+ } else {
+ return fileOpenDialog.vtbl.removeOption(unsafe.Pointer(fileOpenDialog), FosPickfolders)
+ }
+}
+
+const FosAllowMultiselect = 0x200
+
+func (fileOpenDialog *iFileOpenDialog) isMultiselect() (bool, error) {
+ options, err := fileOpenDialog.vtbl.getOptions(unsafe.Pointer(fileOpenDialog))
+ if err != nil {
+ return false, err
+ }
+ return options&FosAllowMultiselect != 0, nil
+}
+
+func (fileOpenDialog *iFileOpenDialog) setIsMultiselect(isMultiselect bool) error {
+ if isMultiselect {
+ return fileOpenDialog.vtbl.addOption(unsafe.Pointer(fileOpenDialog), FosAllowMultiselect)
+ } else {
+ return fileOpenDialog.vtbl.removeOption(unsafe.Pointer(fileOpenDialog), FosAllowMultiselect)
+ }
+}
+
+func (vtbl *iFileOpenDialogVtbl) getResults(objPtr unsafe.Pointer) (*iShellItemArray, error) {
+ var shellItemArray *iShellItemArray
+ ret, _, _ := syscall.Syscall(vtbl.GetResults,
+ 1,
+ uintptr(objPtr),
+ uintptr(unsafe.Pointer(&shellItemArray)),
+ 0)
+ return shellItemArray, hresultToError(ret)
+}
+
+func (vtbl *iFileOpenDialogVtbl) getResultsStrings(objPtr unsafe.Pointer) ([]string, error) {
+ shellItemArray, err := vtbl.getResults(objPtr)
+ if err != nil {
+ return nil, err
+ }
+ if shellItemArray == nil {
+ return nil, ErrorCancelled
+ }
+ defer shellItemArray.vtbl.release(unsafe.Pointer(shellItemArray))
+ count, err := shellItemArray.vtbl.getCount(unsafe.Pointer(shellItemArray))
+ if err != nil {
+ return nil, err
+ }
+ var results []string
+ for i := uintptr(0); i < count; i++ {
+ newItem, err := shellItemArray.vtbl.getItemAt(unsafe.Pointer(shellItemArray), i)
+ if err != nil {
+ return nil, err
+ }
+ results = append(results, newItem)
+ }
+ return results, nil
+}
diff --git a/v2/internal/go-common-file-dialog/cfd/iFileSaveDialog.go b/v2/internal/go-common-file-dialog/cfd/iFileSaveDialog.go
new file mode 100644
index 000000000..3effeda25
--- /dev/null
+++ b/v2/internal/go-common-file-dialog/cfd/iFileSaveDialog.go
@@ -0,0 +1,93 @@
+//go:build windows
+// +build windows
+
+package cfd
+
+import (
+ "github.com/go-ole/go-ole"
+ "github.com/wailsapp/wails/v2/internal/go-common-file-dialog/util"
+ "unsafe"
+)
+
+var (
+ saveFileDialogCLSID = ole.NewGUID("{C0B4E2F3-BA21-4773-8DBA-335EC946EB8B}")
+ saveFileDialogIID = ole.NewGUID("{84bccd23-5fde-4cdb-aea4-af64b83d78ab}")
+)
+
+type iFileSaveDialog struct {
+ vtbl *iFileSaveDialogVtbl
+ parentWindowHandle uintptr
+}
+
+type iFileSaveDialogVtbl struct {
+ iFileDialogVtbl
+
+ SetSaveAsItem uintptr
+ SetProperties uintptr
+ SetCollectedProperties uintptr
+ GetProperties uintptr
+ ApplyProperties uintptr
+}
+
+func newIFileSaveDialog() (*iFileSaveDialog, error) {
+ if unknown, err := ole.CreateInstance(saveFileDialogCLSID, saveFileDialogIID); err == nil {
+ return (*iFileSaveDialog)(unsafe.Pointer(unknown)), nil
+ } else {
+ return nil, err
+ }
+}
+
+func (fileSaveDialog *iFileSaveDialog) Show() error {
+ return fileSaveDialog.vtbl.show(unsafe.Pointer(fileSaveDialog), fileSaveDialog.parentWindowHandle)
+}
+
+func (fileSaveDialog *iFileSaveDialog) SetParentWindowHandle(hwnd uintptr) {
+ fileSaveDialog.parentWindowHandle = hwnd
+}
+
+func (fileSaveDialog *iFileSaveDialog) ShowAndGetResult() (string, error) {
+ if err := fileSaveDialog.Show(); err != nil {
+ return "", err
+ }
+ return fileSaveDialog.GetResult()
+}
+
+func (fileSaveDialog *iFileSaveDialog) SetTitle(title string) error {
+ return fileSaveDialog.vtbl.setTitle(unsafe.Pointer(fileSaveDialog), title)
+}
+
+func (fileSaveDialog *iFileSaveDialog) GetResult() (string, error) {
+ return fileSaveDialog.vtbl.getResultString(unsafe.Pointer(fileSaveDialog))
+}
+
+func (fileSaveDialog *iFileSaveDialog) Release() error {
+ return fileSaveDialog.vtbl.release(unsafe.Pointer(fileSaveDialog))
+}
+
+func (fileSaveDialog *iFileSaveDialog) SetDefaultFolder(defaultFolderPath string) error {
+ return fileSaveDialog.vtbl.setDefaultFolder(unsafe.Pointer(fileSaveDialog), defaultFolderPath)
+}
+
+func (fileSaveDialog *iFileSaveDialog) SetFolder(defaultFolderPath string) error {
+ return fileSaveDialog.vtbl.setFolder(unsafe.Pointer(fileSaveDialog), defaultFolderPath)
+}
+
+func (fileSaveDialog *iFileSaveDialog) SetFileFilters(filter []FileFilter) error {
+ return fileSaveDialog.vtbl.setFileTypes(unsafe.Pointer(fileSaveDialog), filter)
+}
+
+func (fileSaveDialog *iFileSaveDialog) SetRole(role string) error {
+ return fileSaveDialog.vtbl.setClientGuid(unsafe.Pointer(fileSaveDialog), util.StringToUUID(role))
+}
+
+func (fileSaveDialog *iFileSaveDialog) SetDefaultExtension(defaultExtension string) error {
+ return fileSaveDialog.vtbl.setDefaultExtension(unsafe.Pointer(fileSaveDialog), defaultExtension)
+}
+
+func (fileSaveDialog *iFileSaveDialog) SetFileName(initialFileName string) error {
+ return fileSaveDialog.vtbl.setFileName(unsafe.Pointer(fileSaveDialog), initialFileName)
+}
+
+func (fileSaveDialog *iFileSaveDialog) SetSelectedFileFilterIndex(index uint) error {
+ return fileSaveDialog.vtbl.setSelectedFileFilterIndex(unsafe.Pointer(fileSaveDialog), index)
+}
diff --git a/v2/internal/go-common-file-dialog/cfd/iShellItem.go b/v2/internal/go-common-file-dialog/cfd/iShellItem.go
new file mode 100644
index 000000000..6a747f4d9
--- /dev/null
+++ b/v2/internal/go-common-file-dialog/cfd/iShellItem.go
@@ -0,0 +1,53 @@
+//go:build windows
+// +build windows
+
+package cfd
+
+import (
+ "github.com/go-ole/go-ole"
+ "syscall"
+ "unsafe"
+)
+
+var (
+ procSHCreateItemFromParsingName = syscall.NewLazyDLL("Shell32.dll").NewProc("SHCreateItemFromParsingName")
+ iidShellItem = ole.NewGUID("43826d1e-e718-42ee-bc55-a1e261c37bfe")
+)
+
+type iShellItem struct {
+ vtbl *iShellItemVtbl
+}
+
+type iShellItemVtbl struct {
+ iUnknownVtbl
+ BindToHandler uintptr
+ GetParent uintptr
+ GetDisplayName uintptr // func (sigdnName SIGDN, ppszName *LPWSTR) HRESULT
+ GetAttributes uintptr
+ Compare uintptr
+}
+
+func newIShellItem(path string) (*iShellItem, error) {
+ var shellItem *iShellItem
+ pathPtr := ole.SysAllocString(path)
+ ret, _, _ := procSHCreateItemFromParsingName.Call(
+ uintptr(unsafe.Pointer(pathPtr)),
+ 0,
+ uintptr(unsafe.Pointer(iidShellItem)),
+ uintptr(unsafe.Pointer(&shellItem)))
+ return shellItem, hresultToError(ret)
+}
+
+func (vtbl *iShellItemVtbl) getDisplayName(objPtr unsafe.Pointer) (string, error) {
+ var ptr *uint16
+ ret, _, _ := syscall.Syscall(vtbl.GetDisplayName,
+ 2,
+ uintptr(objPtr),
+ 0x80058000, // SIGDN_FILESYSPATH
+ uintptr(unsafe.Pointer(&ptr)))
+ if err := hresultToError(ret); err != nil {
+ return "", err
+ }
+ defer ole.CoTaskMemFree(uintptr(unsafe.Pointer(ptr)))
+ return ole.LpOleStrToString(ptr), nil
+}
diff --git a/v2/internal/go-common-file-dialog/cfd/iShellItemArray.go b/v2/internal/go-common-file-dialog/cfd/iShellItemArray.go
new file mode 100644
index 000000000..84f26fa20
--- /dev/null
+++ b/v2/internal/go-common-file-dialog/cfd/iShellItemArray.go
@@ -0,0 +1,67 @@
+//go:build windows
+// +build windows
+
+package cfd
+
+import (
+ "github.com/go-ole/go-ole"
+ "syscall"
+ "unsafe"
+)
+
+const (
+ iidShellItemArrayGUID = "{b63ea76d-1f85-456f-a19c-48159efa858b}"
+)
+
+var (
+ iidShellItemArray *ole.GUID
+)
+
+func init() {
+ iidShellItemArray, _ = ole.IIDFromString(iidShellItemArrayGUID)
+}
+
+type iShellItemArray struct {
+ vtbl *iShellItemArrayVtbl
+}
+
+type iShellItemArrayVtbl struct {
+ iUnknownVtbl
+ BindToHandler uintptr
+ GetPropertyStore uintptr
+ GetPropertyDescriptionList uintptr
+ GetAttributes uintptr
+ GetCount uintptr // func (pdwNumItems *DWORD) HRESULT
+ GetItemAt uintptr // func (dwIndex DWORD, ppsi **IShellItem) HRESULT
+ EnumItems uintptr
+}
+
+func (vtbl *iShellItemArrayVtbl) getCount(objPtr unsafe.Pointer) (uintptr, error) {
+ var count uintptr
+ ret, _, _ := syscall.Syscall(vtbl.GetCount,
+ 1,
+ uintptr(objPtr),
+ uintptr(unsafe.Pointer(&count)),
+ 0)
+ if err := hresultToError(ret); err != nil {
+ return 0, err
+ }
+ return count, nil
+}
+
+func (vtbl *iShellItemArrayVtbl) getItemAt(objPtr unsafe.Pointer, index uintptr) (string, error) {
+ var shellItem *iShellItem
+ ret, _, _ := syscall.Syscall(vtbl.GetItemAt,
+ 2,
+ uintptr(objPtr),
+ index,
+ uintptr(unsafe.Pointer(&shellItem)))
+ if err := hresultToError(ret); err != nil {
+ return "", err
+ }
+ if shellItem == nil {
+ return "", ErrorCancelled
+ }
+ defer shellItem.vtbl.release(unsafe.Pointer(shellItem))
+ return shellItem.vtbl.getDisplayName(unsafe.Pointer(shellItem))
+}
diff --git a/v2/internal/go-common-file-dialog/cfd/vtblCommon.go b/v2/internal/go-common-file-dialog/cfd/vtblCommon.go
new file mode 100644
index 000000000..21015c27c
--- /dev/null
+++ b/v2/internal/go-common-file-dialog/cfd/vtblCommon.go
@@ -0,0 +1,48 @@
+//go:build windows
+// +build windows
+
+package cfd
+
+type comDlgFilterSpec struct {
+ pszName *int16
+ pszSpec *int16
+}
+
+type iUnknownVtbl struct {
+ QueryInterface uintptr
+ AddRef uintptr
+ Release uintptr
+}
+
+type iModalWindowVtbl struct {
+ iUnknownVtbl
+ Show uintptr // func (hwndOwner HWND) HRESULT
+}
+
+type iFileDialogVtbl struct {
+ iModalWindowVtbl
+ SetFileTypes uintptr // func (cFileTypes UINT, rgFilterSpec *COMDLG_FILTERSPEC) HRESULT
+ SetFileTypeIndex uintptr // func(iFileType UINT) HRESULT
+ GetFileTypeIndex uintptr
+ Advise uintptr
+ Unadvise uintptr
+ SetOptions uintptr // func (fos FILEOPENDIALOGOPTIONS) HRESULT
+ GetOptions uintptr // func (pfos *FILEOPENDIALOGOPTIONS) HRESULT
+ SetDefaultFolder uintptr // func (psi *IShellItem) HRESULT
+ SetFolder uintptr // func (psi *IShellItem) HRESULT
+ GetFolder uintptr
+ GetCurrentSelection uintptr
+ SetFileName uintptr // func (pszName LPCWSTR) HRESULT
+ GetFileName uintptr
+ SetTitle uintptr // func(pszTitle LPCWSTR) HRESULT
+ SetOkButtonLabel uintptr
+ SetFileNameLabel uintptr
+ GetResult uintptr // func (ppsi **IShellItem) HRESULT
+ AddPlace uintptr
+ SetDefaultExtension uintptr // func (pszDefaultExtension LPCWSTR) HRESULT
+ // This can only be used from a callback.
+ Close uintptr
+ SetClientGuid uintptr // func (guid REFGUID) HRESULT
+ ClearClientData uintptr
+ SetFilter uintptr
+}
diff --git a/v2/internal/go-common-file-dialog/cfd/vtblCommonFunc.go b/v2/internal/go-common-file-dialog/cfd/vtblCommonFunc.go
new file mode 100644
index 000000000..a92100010
--- /dev/null
+++ b/v2/internal/go-common-file-dialog/cfd/vtblCommonFunc.go
@@ -0,0 +1,227 @@
+//go:build windows
+// +build windows
+
+package cfd
+
+import (
+ "fmt"
+ "github.com/go-ole/go-ole"
+ "strings"
+ "syscall"
+ "unsafe"
+)
+
+func hresultToError(hr uintptr) error {
+ if hr < 0 {
+ return ole.NewError(hr)
+ }
+ return nil
+}
+
+func (vtbl *iUnknownVtbl) release(objPtr unsafe.Pointer) error {
+ ret, _, _ := syscall.Syscall(vtbl.Release,
+ 0,
+ uintptr(objPtr),
+ 0,
+ 0)
+ return hresultToError(ret)
+}
+
+func (vtbl *iModalWindowVtbl) show(objPtr unsafe.Pointer, hwnd uintptr) error {
+ ret, _, _ := syscall.Syscall(vtbl.Show,
+ 1,
+ uintptr(objPtr),
+ hwnd,
+ 0)
+ return hresultToError(ret)
+}
+
+func (vtbl *iFileDialogVtbl) setFileTypes(objPtr unsafe.Pointer, filters []FileFilter) error {
+ cFileTypes := len(filters)
+ if cFileTypes < 0 {
+ return fmt.Errorf("must specify at least one filter")
+ }
+ comDlgFilterSpecs := make([]comDlgFilterSpec, cFileTypes)
+ for i := 0; i < cFileTypes; i++ {
+ filter := &filters[i]
+ comDlgFilterSpecs[i] = comDlgFilterSpec{
+ pszName: ole.SysAllocString(filter.DisplayName),
+ pszSpec: ole.SysAllocString(filter.Pattern),
+ }
+ }
+ ret, _, _ := syscall.Syscall(vtbl.SetFileTypes,
+ 2,
+ uintptr(objPtr),
+ uintptr(cFileTypes),
+ uintptr(unsafe.Pointer(&comDlgFilterSpecs[0])))
+ return hresultToError(ret)
+}
+
+// Options are:
+// FOS_OVERWRITEPROMPT = 0x2,
+// FOS_STRICTFILETYPES = 0x4,
+// FOS_NOCHANGEDIR = 0x8,
+// FOS_PICKFOLDERS = 0x20,
+// FOS_FORCEFILESYSTEM = 0x40,
+// FOS_ALLNONSTORAGEITEMS = 0x80,
+// FOS_NOVALIDATE = 0x100,
+// FOS_ALLOWMULTISELECT = 0x200,
+// FOS_PATHMUSTEXIST = 0x800,
+// FOS_FILEMUSTEXIST = 0x1000,
+// FOS_CREATEPROMPT = 0x2000,
+// FOS_SHAREAWARE = 0x4000,
+// FOS_NOREADONLYRETURN = 0x8000,
+// FOS_NOTESTFILECREATE = 0x10000,
+// FOS_HIDEMRUPLACES = 0x20000,
+// FOS_HIDEPINNEDPLACES = 0x40000,
+// FOS_NODEREFERENCELINKS = 0x100000,
+// FOS_OKBUTTONNEEDSINTERACTION = 0x200000,
+// FOS_DONTADDTORECENT = 0x2000000,
+// FOS_FORCESHOWHIDDEN = 0x10000000,
+// FOS_DEFAULTNOMINIMODE = 0x20000000,
+// FOS_FORCEPREVIEWPANEON = 0x40000000,
+// FOS_SUPPORTSTREAMABLEITEMS = 0x80000000
+func (vtbl *iFileDialogVtbl) setOptions(objPtr unsafe.Pointer, options uint32) error {
+ ret, _, _ := syscall.Syscall(vtbl.SetOptions,
+ 1,
+ uintptr(objPtr),
+ uintptr(options),
+ 0)
+ return hresultToError(ret)
+}
+
+func (vtbl *iFileDialogVtbl) getOptions(objPtr unsafe.Pointer) (uint32, error) {
+ var options uint32
+ ret, _, _ := syscall.Syscall(vtbl.GetOptions,
+ 1,
+ uintptr(objPtr),
+ uintptr(unsafe.Pointer(&options)),
+ 0)
+ return options, hresultToError(ret)
+}
+
+func (vtbl *iFileDialogVtbl) addOption(objPtr unsafe.Pointer, option uint32) error {
+ if options, err := vtbl.getOptions(objPtr); err == nil {
+ return vtbl.setOptions(objPtr, options|option)
+ } else {
+ return err
+ }
+}
+
+func (vtbl *iFileDialogVtbl) removeOption(objPtr unsafe.Pointer, option uint32) error {
+ if options, err := vtbl.getOptions(objPtr); err == nil {
+ return vtbl.setOptions(objPtr, options&^option)
+ } else {
+ return err
+ }
+}
+
+func (vtbl *iFileDialogVtbl) setDefaultFolder(objPtr unsafe.Pointer, path string) error {
+ shellItem, err := newIShellItem(path)
+ if err != nil {
+ return err
+ }
+ defer shellItem.vtbl.release(unsafe.Pointer(shellItem))
+ ret, _, _ := syscall.Syscall(vtbl.SetDefaultFolder,
+ 1,
+ uintptr(objPtr),
+ uintptr(unsafe.Pointer(shellItem)),
+ 0)
+ return hresultToError(ret)
+}
+
+func (vtbl *iFileDialogVtbl) setFolder(objPtr unsafe.Pointer, path string) error {
+ shellItem, err := newIShellItem(path)
+ if err != nil {
+ return err
+ }
+ defer shellItem.vtbl.release(unsafe.Pointer(shellItem))
+ ret, _, _ := syscall.Syscall(vtbl.SetFolder,
+ 1,
+ uintptr(objPtr),
+ uintptr(unsafe.Pointer(shellItem)),
+ 0)
+ return hresultToError(ret)
+}
+
+func (vtbl *iFileDialogVtbl) setTitle(objPtr unsafe.Pointer, title string) error {
+ titlePtr := ole.SysAllocString(title)
+ ret, _, _ := syscall.Syscall(vtbl.SetTitle,
+ 1,
+ uintptr(objPtr),
+ uintptr(unsafe.Pointer(titlePtr)),
+ 0)
+ return hresultToError(ret)
+}
+
+func (vtbl *iFileDialogVtbl) close(objPtr unsafe.Pointer) error {
+ ret, _, _ := syscall.Syscall(vtbl.Close,
+ 1,
+ uintptr(objPtr),
+ 0,
+ 0)
+ return hresultToError(ret)
+}
+
+func (vtbl *iFileDialogVtbl) getResult(objPtr unsafe.Pointer) (*iShellItem, error) {
+ var shellItem *iShellItem
+ ret, _, _ := syscall.Syscall(vtbl.GetResult,
+ 1,
+ uintptr(objPtr),
+ uintptr(unsafe.Pointer(&shellItem)),
+ 0)
+ return shellItem, hresultToError(ret)
+}
+
+func (vtbl *iFileDialogVtbl) getResultString(objPtr unsafe.Pointer) (string, error) {
+ shellItem, err := vtbl.getResult(objPtr)
+ if err != nil {
+ return "", err
+ }
+ if shellItem == nil {
+ return "", ErrorCancelled
+ }
+ defer shellItem.vtbl.release(unsafe.Pointer(shellItem))
+ return shellItem.vtbl.getDisplayName(unsafe.Pointer(shellItem))
+}
+
+func (vtbl *iFileDialogVtbl) setClientGuid(objPtr unsafe.Pointer, guid *ole.GUID) error {
+ ret, _, _ := syscall.Syscall(vtbl.SetClientGuid,
+ 1,
+ uintptr(objPtr),
+ uintptr(unsafe.Pointer(guid)),
+ 0)
+ return hresultToError(ret)
+}
+
+func (vtbl *iFileDialogVtbl) setDefaultExtension(objPtr unsafe.Pointer, defaultExtension string) error {
+ if defaultExtension[0] == '.' {
+ defaultExtension = strings.TrimPrefix(defaultExtension, ".")
+ }
+ defaultExtensionPtr := ole.SysAllocString(defaultExtension)
+ ret, _, _ := syscall.Syscall(vtbl.SetDefaultExtension,
+ 1,
+ uintptr(objPtr),
+ uintptr(unsafe.Pointer(defaultExtensionPtr)),
+ 0)
+ return hresultToError(ret)
+}
+
+func (vtbl *iFileDialogVtbl) setFileName(objPtr unsafe.Pointer, fileName string) error {
+ fileNamePtr := ole.SysAllocString(fileName)
+ ret, _, _ := syscall.Syscall(vtbl.SetFileName,
+ 1,
+ uintptr(objPtr),
+ uintptr(unsafe.Pointer(fileNamePtr)),
+ 0)
+ return hresultToError(ret)
+}
+
+func (vtbl *iFileDialogVtbl) setSelectedFileFilterIndex(objPtr unsafe.Pointer, index uint) error {
+ ret, _, _ := syscall.Syscall(vtbl.SetFileTypeIndex,
+ 1,
+ uintptr(objPtr),
+ uintptr(index+1), // SetFileTypeIndex counts from 1
+ 0)
+ return hresultToError(ret)
+}
diff --git a/v2/internal/go-common-file-dialog/cfdutil/CFDUtil.go b/v2/internal/go-common-file-dialog/cfdutil/CFDUtil.go
new file mode 100644
index 000000000..bde52d743
--- /dev/null
+++ b/v2/internal/go-common-file-dialog/cfdutil/CFDUtil.go
@@ -0,0 +1,45 @@
+package cfdutil
+
+import (
+ "github.com/wailsapp/wails/v2/internal/go-common-file-dialog/cfd"
+)
+
+// TODO doc
+func ShowOpenFileDialog(config cfd.DialogConfig) (string, error) {
+ dialog, err := cfd.NewOpenFileDialog(config)
+ if err != nil {
+ return "", err
+ }
+ defer dialog.Release()
+ return dialog.ShowAndGetResult()
+}
+
+// TODO doc
+func ShowOpenMultipleFilesDialog(config cfd.DialogConfig) ([]string, error) {
+ dialog, err := cfd.NewOpenMultipleFilesDialog(config)
+ if err != nil {
+ return nil, err
+ }
+ defer dialog.Release()
+ return dialog.ShowAndGetResults()
+}
+
+// TODO doc
+func ShowPickFolderDialog(config cfd.DialogConfig) (string, error) {
+ dialog, err := cfd.NewSelectFolderDialog(config)
+ if err != nil {
+ return "", err
+ }
+ defer dialog.Release()
+ return dialog.ShowAndGetResult()
+}
+
+// TODO doc
+func ShowSaveFileDialog(config cfd.DialogConfig) (string, error) {
+ dialog, err := cfd.NewSaveFileDialog(config)
+ if err != nil {
+ return "", err
+ }
+ defer dialog.Release()
+ return dialog.ShowAndGetResult()
+}
diff --git a/v2/internal/go-common-file-dialog/util/util.go b/v2/internal/go-common-file-dialog/util/util.go
new file mode 100644
index 000000000..723fbedc0
--- /dev/null
+++ b/v2/internal/go-common-file-dialog/util/util.go
@@ -0,0 +1,10 @@
+package util
+
+import (
+ "github.com/go-ole/go-ole"
+ "github.com/google/uuid"
+)
+
+func StringToUUID(str string) *ole.GUID {
+ return ole.NewGUID(uuid.NewSHA1(uuid.Nil, []byte(str)).String())
+}
diff --git a/v2/internal/go-common-file-dialog/util/util_test.go b/v2/internal/go-common-file-dialog/util/util_test.go
new file mode 100644
index 000000000..2e8ffeb05
--- /dev/null
+++ b/v2/internal/go-common-file-dialog/util/util_test.go
@@ -0,0 +1,14 @@
+package util
+
+import (
+ "github.com/go-ole/go-ole"
+ "testing"
+)
+
+func TestStringToUUID(t *testing.T) {
+ generated := *StringToUUID("TestTestTest")
+ expected := *ole.NewGUID("7933985F-2C87-5A5B-A26E-5D0326829AC2")
+ if generated != expected {
+ t.Errorf("not equal. expected %s, found %s", expected.String(), generated.String())
+ }
+}
diff --git a/v2/internal/gomod/gomod_test.go b/v2/internal/gomod/gomod_test.go
index 5173a2230..43907c4a2 100644
--- a/v2/internal/gomod/gomod_test.go
+++ b/v2/internal/gomod/gomod_test.go
@@ -28,7 +28,6 @@ require (
github.com/klauspost/compress v1.12.2 // indirect
github.com/leaanthony/debme v1.2.1 // indirect
github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
- github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
github.com/leaanthony/gosod v1.0.3 // indirect
github.com/leaanthony/slicer v1.5.0 // indirect
@@ -91,7 +90,7 @@ require (
github.com/klauspost/compress v1.12.2 // indirect
github.com/leaanthony/debme v1.2.1 // indirect
github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
- github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+ github.com/wailsapp/wails/v2/internal/go-common-file-dialog v1.0.3 // indirect
github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
github.com/leaanthony/gosod v1.0.3 // indirect
github.com/leaanthony/slicer v1.5.0 // indirect
@@ -132,7 +131,7 @@ require (
github.com/klauspost/compress v1.12.2 // indirect
github.com/leaanthony/debme v1.2.1 // indirect
github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
- github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+ github.com/wailsapp/wails/v2/internal/go-common-file-dialog v1.0.3 // indirect
github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
github.com/leaanthony/gosod v1.0.3 // indirect
github.com/leaanthony/slicer v1.5.0 // indirect
@@ -172,7 +171,7 @@ require (
github.com/klauspost/compress v1.12.2 // indirect
github.com/leaanthony/debme v1.2.1 // indirect
github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
- github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+ github.com/wailsapp/wails/v2/internal/go-common-file-dialog v1.0.3 // indirect
github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
github.com/leaanthony/gosod v1.0.3 // indirect
github.com/leaanthony/slicer v1.5.0 // indirect
@@ -213,7 +212,7 @@ require (
github.com/klauspost/compress v1.12.2 // indirect
github.com/leaanthony/debme v1.2.1 // indirect
github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
- github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+ github.com/wailsapp/wails/v2/internal/go-common-file-dialog v1.0.3 // indirect
github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
github.com/leaanthony/gosod v1.0.3 // indirect
github.com/leaanthony/slicer v1.5.0 // indirect
@@ -254,7 +253,7 @@ require (
github.com/klauspost/compress v1.12.2 // indirect
github.com/leaanthony/debme v1.2.1 // indirect
github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
- github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+ github.com/wailsapp/wails/v2/internal/go-common-file-dialog v1.0.3 // indirect
github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
github.com/leaanthony/gosod v1.0.3 // indirect
github.com/leaanthony/slicer v1.5.0 // indirect
@@ -297,7 +296,7 @@ require (
github.com/klauspost/compress v1.12.2 // indirect
github.com/leaanthony/debme v1.2.1 // indirect
github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
- github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+ github.com/wailsapp/wails/v2/internal/go-common-file-dialog v1.0.3 // indirect
github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
github.com/leaanthony/gosod v1.0.3 // indirect
github.com/leaanthony/slicer v1.5.0 // indirect
@@ -341,7 +340,7 @@ require (
github.com/klauspost/compress v1.12.2 // indirect
github.com/leaanthony/debme v1.2.1 // indirect
github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
- github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+ github.com/wailsapp/wails/v2/internal/go-common-file-dialog v1.0.3 // indirect
github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
github.com/leaanthony/gosod v1.0.3 // indirect
github.com/leaanthony/slicer v1.5.0 // indirect
@@ -443,7 +442,7 @@ require (
github.com/klauspost/compress v1.12.2 // indirect
github.com/leaanthony/debme v1.2.1 // indirect
github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
- github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+ github.com/wailsapp/wails/v2/internal/go-common-file-dialog v1.0.3 // indirect
github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
github.com/leaanthony/gosod v1.0.3 // indirect
github.com/leaanthony/slicer v1.5.0 // indirect
@@ -484,7 +483,7 @@ require (
github.com/klauspost/compress v1.12.2 // indirect
github.com/leaanthony/debme v1.2.1 // indirect
github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
- github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+ github.com/wailsapp/wails/v2/internal/go-common-file-dialog v1.0.3 // indirect
github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
github.com/leaanthony/gosod v1.0.3 // indirect
github.com/leaanthony/slicer v1.5.0 // indirect
@@ -525,7 +524,7 @@ require (
github.com/klauspost/compress v1.12.2 // indirect
github.com/leaanthony/debme v1.2.1 // indirect
github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
- github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+ github.com/wailsapp/wails/v2/internal/go-common-file-dialog v1.0.3 // indirect
github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
github.com/leaanthony/gosod v1.0.3 // indirect
github.com/leaanthony/slicer v1.5.0 // indirect
@@ -569,7 +568,7 @@ require (
github.com/klauspost/compress v1.12.2 // indirect
github.com/leaanthony/debme v1.2.1 // indirect
github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
- github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
+ github.com/wailsapp/wails/v2/internal/go-common-file-dialog v1.0.3 // indirect
github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2 v0.0.0-20211007092718-65d2f028ef2d // indirect
github.com/leaanthony/gosod v1.0.3 // indirect
github.com/leaanthony/slicer v1.5.0 // indirect
diff --git a/v2/internal/menumanager/processedMenu.go b/v2/internal/menumanager/processedMenu.go
index 2722f86cd..8d886e19e 100644
--- a/v2/internal/menumanager/processedMenu.go
+++ b/v2/internal/menumanager/processedMenu.go
@@ -70,7 +70,7 @@ func NewProcessedMenuItem(menuItemMap *MenuItemMap, menuItem *menu.MenuItem) *Pr
Hidden: menuItem.Hidden,
Checked: menuItem.Checked,
SubMenu: nil,
- //RGBA: menuItem.RGBA,
+ //BackgroundColour: menuItem.BackgroundColour,
//FontSize: menuItem.FontSize,
//FontName: menuItem.FontName,
//Image: menuItem.Image,
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/generate/s/s.go b/v2/internal/s/s.go
similarity index 100%
rename from v2/cmd/wails/internal/commands/initialise/templates/generate/s/s.go
rename to v2/internal/s/s.go
diff --git a/v2/internal/signal/signal.go b/v2/internal/signal/signal.go
index f6db19cd3..96e10bee6 100644
--- a/v2/internal/signal/signal.go
+++ b/v2/internal/signal/signal.go
@@ -1,73 +1,39 @@
package signal
import (
- "context"
"os"
gosignal "os/signal"
"sync"
"syscall"
-
- "github.com/wailsapp/wails/v2/internal/logger"
- "github.com/wailsapp/wails/v2/internal/servicebus"
)
-// Manager manages signals such as CTRL-C
-type Manager struct {
- // Service Bus
- bus *servicebus.ServiceBus
+var signalChannel = make(chan os.Signal, 2)
- // logger
- logger logger.CustomLogger
+var callbacks []func()
+var lock sync.Mutex
- // signalChannel
- signalchannel chan os.Signal
-
- // ctx
- ctx context.Context
- cancel context.CancelFunc
-
- // Parent waitgroup
- wg *sync.WaitGroup
-}
-
-// NewManager creates a new signal manager
-func NewManager(ctx context.Context, cancel context.CancelFunc, bus *servicebus.ServiceBus, logger *logger.Logger) (*Manager, error) {
-
- result := &Manager{
- bus: bus,
- logger: logger.CustomLogger("Signal Manager"),
- signalchannel: make(chan os.Signal, 2),
- ctx: ctx,
- cancel: cancel,
- wg: ctx.Value("waitgroup").(*sync.WaitGroup),
- }
-
- return result, nil
+func OnShutdown(callback func()) {
+ lock.Lock()
+ defer lock.Unlock()
+ callbacks = append(callbacks, callback)
}
// Start the Signal Manager
-func (m *Manager) Start() {
+func Start() {
// Hook into interrupts
- gosignal.Notify(m.signalchannel, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
-
- m.wg.Add(1)
+ gosignal.Notify(signalChannel, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
// Spin off signal listener and wait for either a cancellation
// or signal
go func() {
select {
- case <-m.signalchannel:
- println()
- m.logger.Trace("Ctrl+C detected. Shutting down...")
- m.bus.Publish("quit", "ctrl-c pressed")
-
- // Start shutdown of Wails
- m.cancel()
-
- case <-m.ctx.Done():
+ case <-signalChannel:
+ println("")
+ println("Ctrl+C detected. Shutting down...")
+ for _, callback := range callbacks {
+ callback()
+ }
}
- m.logger.Trace("Shutdown")
- m.wg.Done()
}()
}
diff --git a/v2/internal/system/packagemanager/apt.go b/v2/internal/system/packagemanager/apt.go
index a01c8b03d..a650c754f 100644
--- a/v2/internal/system/packagemanager/apt.go
+++ b/v2/internal/system/packagemanager/apt.go
@@ -65,7 +65,7 @@ func (a *Apt) PackageInstalled(pkg *Package) (bool, error) {
if pkg.SystemPackage == false {
return false, nil
}
- cmd := exec.Command("apt", "-qq", "list", pkg.Name)
+ cmd := exec.Command("apt", "list", "-qq", pkg.Name)
var stdo, stde bytes.Buffer
cmd.Stdout = &stdo
cmd.Stderr = &stde
@@ -79,7 +79,7 @@ func (a *Apt) PackageAvailable(pkg *Package) (bool, error) {
if pkg.SystemPackage == false {
return false, nil
}
- stdout, _, err := shell.RunCommand(".", "apt", "-qq", "list", pkg.Name)
+ stdout, _, err := shell.RunCommand(".", "apt", "list", "-qq", pkg.Name)
// We add a space to ensure we get a full match, not partial match
output := a.removeEscapeSequences(stdout)
installed := strings.HasPrefix(output, pkg.Name)
diff --git a/v2/internal/system/system_windows.go b/v2/internal/system/system_windows.go
index 4bb6d6707..3d1b8dc79 100644
--- a/v2/internal/system/system_windows.go
+++ b/v2/internal/system/system_windows.go
@@ -28,8 +28,7 @@ func (i *Info) discover() error {
}
func checkWebView2() *packagemanager.Dependancy {
-
- version, _ := webviewloader.GetInstalledVersion()
+ version, _ := webviewloader.GetWebviewVersion("")
installed := version != ""
return &packagemanager.Dependancy{
diff --git a/v2/internal/wv2installer/wv2installer.go b/v2/internal/wv2installer/wv2installer.go
index e9daae886..1549cf1ba 100644
--- a/v2/internal/wv2installer/wv2installer.go
+++ b/v2/internal/wv2installer/wv2installer.go
@@ -3,44 +3,57 @@
package wv2installer
import (
+ "fmt"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/webviewloader"
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/windows"
)
-const MinimumRuntimeVersion string = "91.0.992.28"
+const MinimumRuntimeVersion string = "94.0.992.31" // Webview2 SDK 1.0.992.28
type installationStatus int
const (
needsInstalling installationStatus = iota
needsUpdating
- installed
)
func Process(appoptions *options.App) (string, error) {
-
messages := windows.DefaultMessages()
if appoptions.Windows != nil && appoptions.Windows.Messages != nil {
messages = appoptions.Windows.Messages
}
+
installStatus := needsInstalling
- installedVersion, err := webviewloader.GetInstalledVersion()
+
+ // Override version check for manually specified webview path if present
+ var webviewPath = ""
+ if opts := appoptions.Windows; opts != nil && opts.WebviewBrowserPath != "" {
+ webviewPath = opts.WebviewBrowserPath
+ }
+
+ installedVersion, err := webviewloader.GetWebviewVersion(webviewPath)
if err != nil {
return "", err
}
+
if installedVersion != "" {
- installStatus = installed
+ installStatus = needsUpdating
compareResult, err := webviewloader.CompareBrowserVersions(installedVersion, MinimumRuntimeVersion)
if err != nil {
return "", err
}
- updateRequired := compareResult == -1
+ updateRequired := compareResult < 0
// Installed and does not require updating
if !updateRequired {
return installedVersion, nil
}
-
}
+
+ // Force error strategy if webview is manually specified
+ if webviewPath != "" {
+ return installedVersion, fmt.Errorf(messages.InvalidFixedWebview2)
+ }
+
return installedVersion, doInstallationStrategy(installStatus, messages)
}
diff --git a/v2/pkg/commands/build/base.go b/v2/pkg/commands/build/base.go
index 9bb19be57..351d944fc 100644
--- a/v2/pkg/commands/build/base.go
+++ b/v2/pkg/commands/build/base.go
@@ -182,6 +182,10 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
commands.Add("-trimpath")
}
+ if options.RaceDetector {
+ commands.Add("-race")
+ }
+
var tags slicer.StringSlicer
tags.Add(options.OutputType)
tags.AddSlice(options.UserTags)
@@ -213,7 +217,7 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
if options.Mode == Production {
ldflags.Add("-w", "-s")
- if options.Platform == "windows" {
+ if options.Platform == "windows" && !options.WindowsConsole {
ldflags.Add("-H windowsgui")
}
}
diff --git a/v2/pkg/commands/build/build.go b/v2/pkg/commands/build/build.go
index 091de85e2..edc233b57 100644
--- a/v2/pkg/commands/build/build.go
+++ b/v2/pkg/commands/build/build.go
@@ -56,6 +56,8 @@ type Options struct {
ForceBuild bool // Force
BundleName string // Bundlename for Mac
TrimPath bool // Use Go's trimpath compiler flag
+ RaceDetector bool // Build with Go's race detector
+ WindowsConsole bool // Indicates that the windows console should be kept
}
// Build the project!
diff --git a/v2/pkg/options/options.go b/v2/pkg/options/options.go
index 1e0b9dfca..c5e19ba38 100644
--- a/v2/pkg/options/options.go
+++ b/v2/pkg/options/options.go
@@ -41,18 +41,20 @@ type App struct {
StartHidden bool
HideWindowOnClose bool
AlwaysOnTop bool
- RGBA *RGBA
- Assets fs.FS
- AssetsHandler http.Handler
- Menu *menu.Menu
- Logger logger.Logger `json:"-"`
- LogLevel logger.LogLevel
- OnStartup func(ctx context.Context) `json:"-"`
- OnDomReady func(ctx context.Context) `json:"-"`
- OnShutdown func(ctx context.Context) `json:"-"`
- OnBeforeClose func(ctx context.Context) (prevent bool) `json:"-"`
- Bind []interface{}
- WindowStartState WindowStartState
+ BackgroundColour *RGBA
+ // RGBA is deprecated. Please use BackgroundColour
+ RGBA *RGBA
+ Assets fs.FS
+ AssetsHandler http.Handler
+ Menu *menu.Menu
+ Logger logger.Logger `json:"-"`
+ LogLevel logger.LogLevel
+ OnStartup func(ctx context.Context) `json:"-"`
+ OnDomReady func(ctx context.Context) `json:"-"`
+ OnShutdown func(ctx context.Context) `json:"-"`
+ OnBeforeClose func(ctx context.Context) (prevent bool) `json:"-"`
+ Bind []interface{}
+ WindowStartState WindowStartState
//ContextMenus []*menu.ContextMenu
//TrayMenus []*menu.TrayMenu
@@ -75,9 +77,9 @@ func MergeDefaults(appoptions *App) {
log.Fatal(err)
}
- // DEfault colour. Doesn't work well with mergo
- if appoptions.RGBA == nil {
- appoptions.RGBA = &RGBA{
+ // Default colour. Doesn't work well with mergo
+ if appoptions.BackgroundColour == nil {
+ appoptions.BackgroundColour = &RGBA{
R: 255,
G: 255,
B: 255,
diff --git a/v2/pkg/options/windows/windows.go b/v2/pkg/options/windows/windows.go
index 4c553fc89..5c18d1737 100644
--- a/v2/pkg/options/windows/windows.go
+++ b/v2/pkg/options/windows/windows.go
@@ -12,6 +12,7 @@ type Messages struct {
DownloadPage string
PressOKToInstall string
ContactAdmin string
+ InvalidFixedWebview2 string
}
const (
@@ -23,6 +24,16 @@ const (
Light Theme = 2
)
+type BackdropType int32
+
+const (
+ Auto BackdropType = 0
+ Disable BackdropType = 1 // None
+ MainWindow BackdropType = 2 // Mica
+ TransientWindow BackdropType = 3 // Acrylic
+ TabbedWindow BackdropType = 4 // Tabbed
+)
+
func RGB(r, g, b uint8) int32 {
var col = int32(b)
col = col<<8 | int32(g)
@@ -61,14 +72,29 @@ type Options struct {
// If the path is not valid, a messagebox will be displayed with the error and the app will exit with error code.
WebviewUserDataPath string
+ // Path to the directory with WebView2 executables. If empty WebView2 installed in the system will be used.
+ WebviewBrowserPath string
+
// Dark/Light or System Default Theme
Theme Theme
// Custom settings for dark/light mode
CustomTheme *ThemeSettings
+ // Windows 11 22579 minimum
+ TranslucencyType BackdropType
+
// User messages that can be customised
Messages *Messages
+
+ // ResizeDebounceMS is the amount of time to debounce redraws of webview2
+ // when resizing the window
+ ResizeDebounceMS uint16
+
+ // OnSuspend is called when Windows enters low power mode
+ OnSuspend func()
+ // OnResume is called when Windows resumes from low power mode
+ OnResume func()
}
func DefaultMessages() *Messages {
@@ -82,5 +108,6 @@ func DefaultMessages() *Messages {
DownloadPage: "This application requires the WebView2 runtime. Press OK to open the download page. Minimum version required: ",
PressOKToInstall: "Press Ok to install.",
ContactAdmin: "The WebView2 runtime is required to run this application. Please contact your system administrator.",
+ InvalidFixedWebview2: "The WebView2 runtime is manually specified, but It is not valid. Check minimum required version and webview2 path.",
}
}
diff --git a/v2/pkg/runtime/runtime.go b/v2/pkg/runtime/runtime.go
index 20e44dc72..6dc61f368 100644
--- a/v2/pkg/runtime/runtime.go
+++ b/v2/pkg/runtime/runtime.go
@@ -67,12 +67,14 @@ func Quit(ctx context.Context) {
appFrontend.Quit()
}
+// EnvironmentInfo contains information about the environment
type EnvironmentInfo struct {
- BuildType string `json:"buildtype"`
+ BuildType string `json:"buildType"`
Platform string `json:"platform"`
Arch string `json:"arch"`
}
+// Environment returns information about the environment
func Environment(ctx context.Context) EnvironmentInfo {
var result EnvironmentInfo
buildType := ctx.Value("buildtype")
diff --git a/v2/pkg/runtime/window.go b/v2/pkg/runtime/window.go
index 178f5abea..fb1cd6126 100644
--- a/v2/pkg/runtime/window.go
+++ b/v2/pkg/runtime/window.go
@@ -92,6 +92,12 @@ func WindowSetMaxSize(ctx context.Context, width int, height int) {
appFrontend.WindowSetMaxSize(width, height)
}
+// WindowSetAlwaysOnTop sets the window AlwaysOnTop or not on top
+func WindowSetAlwaysOnTop(ctx context.Context, b bool) {
+ appFrontend := getFrontend(ctx)
+ appFrontend.WindowSetAlwaysOnTop(b)
+}
+
// WindowSetPosition sets the position of the window
func WindowSetPosition(ctx context.Context, x int, y int) {
appFrontend := getFrontend(ctx)
@@ -133,7 +139,8 @@ func WindowUnminimise(ctx context.Context) {
appFrontend.WindowUnminimise()
}
-func WindowSetRGBA(ctx context.Context, R, G, B, A uint8) {
+// WindowSetBackgroundColour sets the colour of the window background
+func WindowSetBackgroundColour(ctx context.Context, R, G, B, A uint8) {
appFrontend := getFrontend(ctx)
col := &options.RGBA{
R: R,
@@ -141,5 +148,5 @@ func WindowSetRGBA(ctx context.Context, R, G, B, A uint8) {
B: B,
A: A,
}
- appFrontend.WindowSetRGBA(col)
+ appFrontend.WindowSetBackgroundColour(col)
}
diff --git a/v2/tools/release/release.go b/v2/tools/release/release.go
new file mode 100644
index 000000000..c61a1c72a
--- /dev/null
+++ b/v2/tools/release/release.go
@@ -0,0 +1,67 @@
+package main
+
+import (
+ "encoding/json"
+ "github.com/wailsapp/wails/v2/internal/s"
+ "os"
+ "os/exec"
+ "strconv"
+ "strings"
+)
+
+const versionFile = "../../cmd/wails/internal/version.txt"
+
+func checkError(err error) {
+ if err != nil {
+ println(err.Error())
+ os.Exit(1)
+ }
+}
+
+func updateVersion() string {
+
+ currentVersionData, err := os.ReadFile(versionFile)
+ checkError(err)
+ currentVersion := string(currentVersionData)
+ vsplit := strings.Split(currentVersion, ".")
+ minorVersion, err := strconv.Atoi(vsplit[len(vsplit)-1])
+ checkError(err)
+ minorVersion++
+ vsplit[len(vsplit)-1] = strconv.Itoa(minorVersion)
+ newVersion := strings.Join(vsplit, ".")
+ err = os.WriteFile(versionFile, []byte(newVersion), 0755)
+ checkError(err)
+ return newVersion
+}
+
+func main() {
+ newVersion := updateVersion()
+ s.CD("../../../website")
+ s.ECHO("Generating new Docs for version: " + newVersion)
+ cmd := exec.Command("npm", "run", "docusaurus", "docs:version", newVersion)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ err := cmd.Run()
+ checkError(err)
+
+ // Load the version list
+ versionsData, err := os.ReadFile("versions.json")
+ checkError(err)
+ var versions []string
+ err = json.Unmarshal(versionsData, &versions)
+ checkError(err)
+ oldestVersion := versions[len(versions)-1]
+ s.ECHO(oldestVersion)
+ versions = versions[0 : len(versions)-1]
+ newVersions, err := json.Marshal(&versions)
+ checkError(err)
+ err = os.WriteFile("versions.json", newVersions, 0755)
+ checkError(err)
+
+ s.ECHO("Removing old version: " + oldestVersion)
+ s.CD("versioned_docs")
+ s.RMDIR("version-" + oldestVersion)
+ s.CD("../versioned_sidebars")
+ s.RM("version-" + oldestVersion + "-sidebars.json")
+
+}
diff --git a/v2/wails.go b/v2/wails.go
index 33d07a561..e35ca82e9 100644
--- a/v2/wails.go
+++ b/v2/wails.go
@@ -4,12 +4,22 @@ package wails
import (
app "github.com/wailsapp/wails/v2/internal/appng"
+ "github.com/wailsapp/wails/v2/internal/signal"
"github.com/wailsapp/wails/v2/pkg/options"
)
// Run creates an application based on the given config and executes it
func Run(options *options.App) error {
+ if options.RGBA != nil {
+ println("---- WARNING ----")
+ println("The `RGBA` option has been deprecated. Please use `BackgroundColour`.")
+
+ if options.BackgroundColour == nil {
+ options.BackgroundColour = options.RGBA
+ }
+ }
+
// Call an Init method manually
err := Init()
if err != nil {
@@ -21,5 +31,11 @@ func Run(options *options.App) error {
return err
}
+ signal.OnShutdown(func() {
+ mainapp.Shutdown()
+ })
+
+ signal.Start()
+
return mainapp.Run()
}
diff --git a/website/docs/community/showcase/october.mdx b/website/docs/community/showcase/october.mdx
new file mode 100644
index 000000000..fbabff01e
--- /dev/null
+++ b/website/docs/community/showcase/october.mdx
@@ -0,0 +1,11 @@
+# October
+
+
+
+
+
+[October](https://october.utf9k.net) is a small Wails application that makes it really easy to extract highlights from [Kobo eReaders](https://en.wikipedia.org/wiki/Kobo_eReader) and then forward them to [Readwise](https://readwise.io).
+
+It has a relatively small scope with all platform versions weighing in under 10MB, and that's without enabling [UPX compression](https://upx.github.io/)!
+
+In contrast, the author's previous attempts with Electron quickly bloated to several hundred megabytes.
\ No newline at end of file
diff --git a/website/docs/community/showcase/surge.mdx b/website/docs/community/showcase/surge.mdx
index 774e86e70..b1693a6de 100644
--- a/website/docs/community/showcase/surge.mdx
+++ b/website/docs/community/showcase/surge.mdx
@@ -5,5 +5,5 @@
-[Surge](https://surge.rule110.io/) is a p2p filesharing app designed to utilize blockchain technologies to enable 100% anonymous file transfers. Surge is end-to-end encrypted, decentralized and open source.
+[Surge](https://getsurge.io/) is a p2p filesharing app designed to utilize blockchain technologies to enable 100% anonymous file transfers. Surge is end-to-end encrypted, decentralized and open source.
diff --git a/website/docs/community/templates.mdx b/website/docs/community/templates.mdx
index 076a6b041..6d090bb3d 100644
--- a/website/docs/community/templates.mdx
+++ b/website/docs/community/templates.mdx
@@ -35,6 +35,7 @@ If you are unsure about a template, inspect `package.json` and `wails.json` for
- [wails-react-template](https://github.com/AlienRecall/wails-react-template) - A template using reactjs
- [wails-react-template](https://github.com/flin7/wails-react-template) - A minimal template for React that supports live development
+- [wails-template-nextjs](https://github.com/LGiki/wails-template-nextjs) - A template using Next.js and TypeScript
## Svelte
diff --git a/website/docs/contributing/_category_.json b/website/docs/contributing/_category_.json
new file mode 100644
index 000000000..fad21931a
--- /dev/null
+++ b/website/docs/contributing/_category_.json
@@ -0,0 +1,4 @@
+{
+ "label": "Contributing",
+ "position": 99
+}
diff --git a/website/docs/contributing/developing_new_features.mdx b/website/docs/contributing/developing_new_features.mdx
new file mode 100644
index 000000000..1aa5ea145
--- /dev/null
+++ b/website/docs/contributing/developing_new_features.mdx
@@ -0,0 +1,35 @@
+---
+sidebar_position: 20
+---
+
+# Developing New Features
+
+We are always keen to add features to Wails and expand on what the project can do.
+The process for adding new features are as follows:
+
+- Pick an enhancement ticket with the "TODO" label. It's preferable to select one from the current
+[Backlog](https://github.com/orgs/wailsapp/projects/1/views/1) but the choice is yours.
+- Before developing, check that the ticket includes the following information:
+- The purpose of the enhancement
+- What is out of scope for the enhancement
+- What platforms the enhancement targets (most features should be cross-platform unless there's a very specific reason)
+- If the ticket does not include this information, feel free to request the information from the
+person who opened the ticket. Sometimes placeholder tickets are created and require more details
+- Comment on the ticket stating you wish to develop the feature
+- Clone the repository and create a branch with the format `feature/_`
+- New features often require documentation so please ensure you have also added or updated the documentation as part of
+the changes
+- Once the feature is ready for testing, create a draft PR. Please ensure the PR description has the test scenarios and
+test cases listed with checkmarks, so that others can know what still needs to be tested.
+- Once all the testing is completed, please update the status of the PR from draft and leave a message.
+
+:::note
+There is nothing stopping you from opening a ticket and working on it yourself, but please be aware that all
+enhancement requests are reviewed for good fit. Not all ideas will be selected so it's best to have discussion
+on the ticket first.
+:::
+
+:::warning
+Any PRs opened without a corresponding ticket may be rejected.
+:::
+
diff --git a/website/docs/contributing/documenting.mdx b/website/docs/contributing/documenting.mdx
new file mode 100644
index 000000000..1655a44fe
--- /dev/null
+++ b/website/docs/contributing/documenting.mdx
@@ -0,0 +1,39 @@
+---
+sidebar_position: 40
+---
+
+# Documenting
+
+This website is also the main documentation site for the project. Sometimes this gets
+out of date and needs some slight adjustments. Some of the documentation isn't written
+to the best standards either. Developing documentation is hard and so any contribution
+to this is greatly appreciated. Features without documentation are unfinished so to the
+project, it's *as important* as the code.
+
+We generally do not create tickets for updating documentation so if there is text you
+think should be updated or rephrased then feel free to submit a PR for that. This site
+is in the main repository under the `website` directory. We use [Docusaurus](https://docusaurus.io/) to create
+the site so there is plenty of existing documentation and tutorials around to get started.
+
+To set up a local documentation development environment, do the following:
+
+- [Install npm](https://docs.npmjs.com/cli/v8/configuring-npm/install)
+- `cd website`
+- `npm install`
+- `npm run start`
+
+After it has all installed and is running, you should see the site at [`http://localhost:3000`](http://localhost:3000).
+Any changes made to the site text will be immediately reflected in the browser.
+
+## Versioning
+
+We employ a versioning system where we have the "latest" documentation AKA "Next Version" which
+has all the changes that have occurred since the last release. We also keep the last release
+documentation as well as the version before that.
+
+There isn't usually a reason to update released documentation so we don't generally update
+the documents in the `versioned_docs` or `versioned_sidebars` directories.
+
+The "next version" docs are mainly in `website/docs` with some "version independent" documents
+in `src/pages`. Any updates should be made in the `website/docs` directory.
+
diff --git a/website/docs/contributing/fixing_bugs.mdx b/website/docs/contributing/fixing_bugs.mdx
new file mode 100644
index 000000000..7e1c78ad3
--- /dev/null
+++ b/website/docs/contributing/fixing_bugs.mdx
@@ -0,0 +1,30 @@
+---
+sidebar_position: 30
+---
+
+# Fixing Bugs
+
+The process for fixing bugs are as follows:
+
+- Check the current [Backlog](https://github.com/orgs/wailsapp/projects/1/views/1) and select a bug to fix
+- Before developing, check that the ticket includes the following information:
+- The scope of the issue including platforms affected
+- The steps to reproduce. Sometimes bugs are opened that are not Wails issues and the onus is on the reporter to
+prove that it is a Wails issue with a minimal reproducible example
+- The output of `wails doctor`
+- If the ticket does not include this information, feel free to request the information from the
+person who opened the ticket.
+- Comment on the ticket stating you wish to develop a fix
+- Clone the repository and create a branch with the format `bugfix/_`
+- Once the fix is ready for testing, create a draft PR. Please ensure the PR description has the test scenarios and
+test cases listed with checkmarks, so that others can know what still needs to be tested.
+- Once all the testing is completed, please update the status of the PR from draft and leave a message.
+
+:::note
+There is nothing stopping you from opening a ticket and working on it yourself, but please be aware that all
+bugfixes should be discussed as the approach may have unintended side effects.
+:::
+
+:::warning
+Any PRs opened without a corresponding ticket may be rejected.
+:::
\ No newline at end of file
diff --git a/website/docs/contributing/helping_others.mdx b/website/docs/contributing/helping_others.mdx
new file mode 100644
index 000000000..340f51a2a
--- /dev/null
+++ b/website/docs/contributing/helping_others.mdx
@@ -0,0 +1,17 @@
+---
+sidebar_position: 50
+---
+
+# Helping Others
+
+A great way to contribute to the project is to help others who are experiencing difficulty.
+This is normally reported as a ticket or a message on the Wails slack channel. Even just
+clarifying the issue can really help out. Sometimes, when an issue is discussed and gets
+resolved, we create a guide out of it to help others who face the same issues.
+
+To join the Wails slack channel, accept the invite [here](https://gophers.slack.com/join/shared_invite/zt-197vymgt3-sJt4oyakb6nqlVKjXTyeVw#/shared-invite/email)
+and join us on the channel by following [this link](https://gophers.slack.com/?redir=%2Fmessages%2FCJ4P9F7MZ%2F).
+
+:::note
+Work In Progress
+:::
diff --git a/website/docs/contributing/introduction.mdx b/website/docs/contributing/introduction.mdx
new file mode 100644
index 000000000..53763adff
--- /dev/null
+++ b/website/docs/contributing/introduction.mdx
@@ -0,0 +1,24 @@
+---
+sidebar_position: 1
+---
+
+# Introduction
+
+Wails is an open source, community driven project. We welcome anyone to join us in
+contributing to the project. This documentation is aimed at anyone wishing to get
+familiar with the project and the development processes.
+
+# Ways of contributing
+
+There are many ways to contribute to the project:
+
+- Developing new features
+- Fixing bugs
+- Testing
+- Documenting features
+- Writing tutorials / guides
+- Helping others on the issues + discussions boards
+
+Guides for these have been created in their own sections. Before getting started,
+please introduce yourself in the [Contributing to Wails](https://github.com/wailsapp/wails/discussions/1520)
+discussion.
\ No newline at end of file
diff --git a/website/docs/contributing/setting_up_a_dev_environment.mdx b/website/docs/contributing/setting_up_a_dev_environment.mdx
new file mode 100644
index 000000000..b5cfd8eca
--- /dev/null
+++ b/website/docs/contributing/setting_up_a_dev_environment.mdx
@@ -0,0 +1,34 @@
+---
+sidebar_position: 10
+---
+
+# Setting up a Development Environment
+
+You can set up a development environment by doing the following:
+
+- Install the latest versions of Go and Git
+- `git clone https://github.com/wailsapp/wails`
+- `cd wails/v2/cmd/wails`
+- `go install`
+
+NOTE: The directory that you cloned the project into will now be called "clonedir".
+
+The Wails CLI will now be at the very latest version.
+
+To update projects to use the latest version, update the project's `go.mod` and
+ensure the following line is at the bottom of the file:
+
+`replace github.com/wailsapp/wails/v2 => `
+
+Example:
+
+On Windows:
+`replace github.com/wailsapp/wails/v2 => C:\Users\leaan\Documents\wails-v2-beta\wails\v2`
+
+On 'nix:
+`replace github.com/wailsapp/wails/v2 => /home/me/projects/wails/v2`
+
+To revert back to a stable version, run:
+
+`go install github.com/wailsapp/wails/v2/cmd/wails@latest`
+
diff --git a/website/docs/contributing/testing.mdx b/website/docs/contributing/testing.mdx
new file mode 100644
index 000000000..d01204651
--- /dev/null
+++ b/website/docs/contributing/testing.mdx
@@ -0,0 +1,21 @@
+---
+sidebar_position: 35
+---
+
+# Testing
+
+Testing is vitally important to ensure quality in the project. There are a couple of
+scenarios where testing can really help the project:
+
+- Testing if a bug is reproducible on your local system
+- Testing PRs to ensure that they work correctly
+
+If you chose to test if someone's bug report is reproducible on your local system, then
+feel free to add a comment on the ticket confirming this with the output of `wails doctor`.
+
+To test PRs, choose a PR to test and check if the PR description has the testing scenarios
+listed. If not, please ask the person who opened the PR to provide that list. Once you have
+determined a valid test scenario, please report your findings on the PR.
+
+If you ever need more clarity or help on testing, please ask a question in the [Contributing to Wails](https://github.com/wailsapp/wails/discussions/1520)
+discussion or on slack.
diff --git a/website/docs/gettingstarted/installation.mdx b/website/docs/gettingstarted/installation.mdx
index 3b4cd33cc..7358a3ecd 100644
--- a/website/docs/gettingstarted/installation.mdx
+++ b/website/docs/gettingstarted/installation.mdx
@@ -20,9 +20,9 @@ Wails has a number of common dependencies that are required before installation:
### Go
-Download Go from the [Go Downloads Page](https://golang.org/dl/).
+Download Go from the [Go Downloads Page](https://go.dev/doc/install).
-Ensure that you follow the official [Go installation instructions](https://golang.org/doc/install.mdx#install). You will also need to ensure that your `PATH` environment variable also includes the path to your `~/go/bin` directory. Restart your terminal and do the following checks:
+Ensure that you follow the official [Go installation instructions](https://go.dev/doc/install). You will also need to ensure that your `PATH` environment variable also includes the path to your `~/go/bin` directory. Restart your terminal and do the following checks:
- Check Go is installed correctly: `go version`
- Check "~/go/bin" is in your PATH variable: `echo $PATH | grep go/bin`
@@ -37,6 +37,7 @@ Run `npm --version` to verify.
You will also need to install platform specific dependencies:
+
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
@@ -76,3 +77,10 @@ Run `go install github.com/wailsapp/wails/v2/cmd/wails@latest` to install the Wa
## System Check
Running `wails doctor` will check if you have the correct dependencies installed. If not, it will advise on what is missing and help on how to rectify any problems.
+
+## The `wails` command appears to be missing?
+
+If your system is reporting that the `wails` command is missing, make sure you have followed the Go installation guide
+correctly. Normally, it means that the `go/bin` directory in your User's home directory is not in the `PATH` environment
+variable. You will also normally need to close and reopen any open command prompts so that changes to the environment
+made by the installer are reflected at the command prompt.
\ No newline at end of file
diff --git a/website/docs/guides/application-development.mdx b/website/docs/guides/application-development.mdx
index 039cb227d..d9de25d2e 100644
--- a/website/docs/guides/application-development.mdx
+++ b/website/docs/guides/application-development.mdx
@@ -113,6 +113,40 @@ func main() {
This will bind all public methods in our `App` struct (it will never bind the startup and shutdown methods).
+### Dealing with context when binding multiple structs
+
+If you want to bind methods for multiple structs but want each struct to keep a reference to the context so that you
+can use the runtime functions, a good pattern is to pass the context from the `OnStartup` method to your struct instances
+:
+
+```go
+func main() {
+
+ app := NewApp()
+ otherStruct := NewOtherStruct()
+
+ err := wails.Run(&options.App{
+ Title: "My App",
+ Width: 800,
+ Height: 600,
+ OnStartup: func(ctx context.Context){
+ app.SetContext(ctx)
+ otherStruct.SetContext(ctx)
+ },
+ OnShutdown: app.shutdown,
+ Bind: []interface{}{
+ app,
+ otherStruct
+ },
+ })
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+```
+
+
+
More information on Binding can be found [here](../howdoesitwork.mdx#method-binding).
## Application Menu
diff --git a/website/docs/guides/frontend.mdx b/website/docs/guides/frontend.mdx
index 84489cd99..6c9d0cf27 100644
--- a/website/docs/guides/frontend.mdx
+++ b/website/docs/guides/frontend.mdx
@@ -3,7 +3,7 @@
## Script Injection
-When Wails serves your `index.html`, by default, it will inject 2 script entries into the `` tag to load `/wails/bindings.js`
+When Wails serves your `index.html`, by default, it will inject 2 script entries into the `` tag to load `/wails/ipc.js`
and `/wails/runtime.js`. These files install the bindings and runtime respectively.
The code below shows where these are injected by default:
diff --git a/website/docs/guides/troubleshooting.mdx b/website/docs/guides/troubleshooting.mdx
index 1ab08d6f3..2bea2216e 100644
--- a/website/docs/guides/troubleshooting.mdx
+++ b/website/docs/guides/troubleshooting.mdx
@@ -1,8 +1,14 @@
-
# Troubleshooting
An assortment of troubleshooting tips.
+## The `wails` command appears to be missing?
+
+If your system is reporting that the `wails` command is missing, make sure you have followed the Go installation guide
+correctly. Normally, it means that the `go/bin` directory in your User's home directory is not in the `PATH` environment
+variable. You will also normally need to close and reopen any open command prompts so that changes to the environment
+made by the installer are reflected at the command prompt.
+
## My application is displaying a white/blank screen
Check that your application includes the assets from the correct directory. In your `main.go` file, you will have
@@ -14,6 +20,20 @@ var assets embed.FS
```
Check that `frontend/dist` contains your application assets.
+### Mac
+
+If this happens on Mac, try adding the following to your `Info.plist`:
+
+```xml
+NSAppTransportSecurity
+
+ NSAllowsLocalNetworking
+
+
+```
+
+Reference: https://github.com/wailsapp/wails/issues/1504#issuecomment-1174317433
+
## Mac application not valid
If your built application looks like this in finder:
@@ -22,7 +42,7 @@ If your built application looks like this in finder:
-it's likely that your application's `info.plist` is invalid. Update the file in `build/.app/Contents/info.plist`
+it''s likely that your application''s `info.plist` is invalid. Update the file in `build/.app/Contents/info.plist`
and check if the data is valid, EG check the binary name is correct. To persist the changes, copy the file back to
the `build/darwin` directory.
@@ -56,7 +76,7 @@ window.go.main.App.TestFunc(msg, args).then((result) => { //without the 3 dots
```
Credit: https://github.com/wailsapp/wails/issues/1186
-## I'm having getting proxy errors when trying to install Wails
+## I''m having getting proxy errors when trying to install Wails
If you are getting errors like this:
```
@@ -68,4 +88,10 @@ The solution is to set up the proxy manually, eg:
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct
```
-Source: https://github.com/wailsapp/wails/issues/1233
\ No newline at end of file
+Source: https://github.com/wailsapp/wails/issues/1233
+
+## The generated Typescript doesn''t have the correct types
+
+Sometimes the generated Typescript doesn''t have the correct types. To mitigate this,
+it is possible to specify what types should be generated using the `ts_type` struct tag. For
+more details, please read [this](https://github.com/tkrajina/typescriptify-golang-structs#custom-types).
\ No newline at end of file
diff --git a/website/docs/guides/windows.mdx b/website/docs/guides/windows.mdx
index e0ec17d5f..520f0bd86 100644
--- a/website/docs/guides/windows.mdx
+++ b/website/docs/guides/windows.mdx
@@ -35,3 +35,20 @@ up to the user.
### Error
If no suitable runtime is found, an error is given to the user and no further action taken.
+
+## Fixed version runtime
+
+Another way of dealing with webview2 dependency is shipping it yourself.
+You can download [fixed version runtime](https://developer.microsoft.com/ru-ru/microsoft-edge/webview2/#download-section) and bundle or download it with your application.
+
+Also, you should specify path to fixed version of webview2 runtime in the `windows.Options` structure when launching wails.
+
+```go
+ wails.Run(&options.App{
+ Windows: &windows.Options{
+ WebviewBrowserPath: "",
+ },
+ })
+```
+
+Note: When `WebviewBrowserPath` is specified, `error` strategy will be forced in case of minimal required version mismatch or invalid path to a runtime.
\ No newline at end of file
diff --git a/website/docs/reference/cli.mdx b/website/docs/reference/cli.mdx
index 44ba1f165..54259b809 100644
--- a/website/docs/reference/cli.mdx
+++ b/website/docs/reference/cli.mdx
@@ -68,8 +68,10 @@ A list of community maintained templates can be found [here](../community/templa
| -v int | Verbosity level (0 - silent, 1 - default, 2 - verbose) | 1 |
| -webview2 | WebView2 installer strategy: download,embed,browser,error | download |
| -u | Updates your project's `go.mod` to use the same version of Wails as the CLI | |
-| -debug | Retains debug information in the application | false |
+| -debug | Retains debug information in the application. Allows the use of the devtools in the application window | false |
| -trimpath | Remove all file system paths from the resulting executable. | false |
+| -race | Build with Go's race detector | false |
+| -windowsconsole | Keep the console window for Windows builds | false |
For a detailed description of the `webview2` flag, please refer to the [Windows](../guides/windows.mdx) Guide.
@@ -168,6 +170,7 @@ Your system is ready for Wails development!
| -tags "extra tags" | Build tags to pass to compiler (quoted and space separated) | |
| -loglevel "loglevel"| Loglevel to use - Trace, Debug, Info, Warning, Error | Debug |
| -noreload | Disable automatic reload when assets change | |
+| -nogen | Disable generate module | |
| -v | Verbosity level (0 - silent, 1 - standard, 2 - verbose) | 1 |
| -wailsjsdir | The directory to generate the generated Wails JS modules | Value in `wails.json` |
| -debounce | The time to wait for reload after an asset change is detected | 100 (milliseconds) |
@@ -175,8 +178,8 @@ Your system is ready for Wails development!
| -frontenddevserverurl "url" | Use 3rd party dev server url to serve assets, EG Vite | "" |
| -appargs "args" | Arguments passed to the application in shell style | |
| -platform "platform" | Platform/Arch to target | `runtime.GOOS` |
-| -save | Saves the given `assetdir`, `reloaddirs`, `wailsjsdir`, `debounce`, `devserver` and `frontenddevserverurl` flags in
- `wails.json` to become the defaults for subsequent invocations. | |
+| -save | Saves the given `assetdir`, `reloaddirs`, `wailsjsdir`, `debounce`, `devserver` and `frontenddevserverurl` flags in `wails.json` to become the defaults for subsequent invocations. | |
+| -race | Build with Go's race detector | false |
Example:
@@ -217,4 +220,4 @@ For more details on creating templates, consult the [Templates guide](../guides/
## version
-`wails version` will simply output the current CLI version.
\ No newline at end of file
+`wails version` will simply output the current CLI version.
diff --git a/website/docs/reference/menus.mdx b/website/docs/reference/menus.mdx
index bab623586..ac083ef51 100644
--- a/website/docs/reference/menus.mdx
+++ b/website/docs/reference/menus.mdx
@@ -18,6 +18,10 @@ An example of how to create a menu:
FileMenu.AddText("Quit", keys.CmdOrCtrl("q"), func(_ *menu.CallbackData) {
runtime.Quit()
})
+
+ if runtime.GOOS == "darwin" {
+ AppMenu.Append(menu.EditMenu()) // on macos platform, we should append EditMenu to enable Cmd+C,Cmd+V,Cmd+Z... shortcut
+ }
err := wails.Run(&options.App{
Title: "Menus Demo",
diff --git a/website/docs/reference/options.mdx b/website/docs/reference/options.mdx
index eb3177633..c557ef612 100644
--- a/website/docs/reference/options.mdx
+++ b/website/docs/reference/options.mdx
@@ -27,7 +27,7 @@ func main() {
MaxHeight: 1024,
StartHidden: false,
HideWindowOnClose: false,
- RGBA: &options.RGBA{R: 0, G: 0, B: 0, A: 255},
+ BackgroundColour: &options.RGBA{R: 0, G: 0, B: 0, A: 255},
AlwaysOnTop: false,
Assets: assets,
AssetsHandler: assetsHandler,
@@ -48,6 +48,7 @@ func main() {
DisableWindowIcon: false,
DisableFramelessWindowDecorations: false,
WebviewUserDataPath: "",
+ WebviewBrowserPath: "",
Theme: windows.SystemDefault,
CustomTheme: &windows.ThemeSettings{
DarkModeTitleBar: windows.RGB(20, 20, 20),
@@ -196,14 +197,14 @@ Type: bool
By default, closing the window will close the application. Setting this to `true` means closing the window will
hide the window instead.
-### RGBA
+### BackgroundColour
-Name: RGBA
+Name: BackgroundColour
Type: int (0xRRGGBBAA)
Example: 0xFF000088 - Red at 50% transparency
-This value is the RGBA value to set the window by default.
+This value is the default background colour of the window.
Default: 0xFFFFFFFF.
### AlwaysOnTop
@@ -392,7 +393,7 @@ Name: WebviewIsTransparent
Type: bool
Setting this to `true` will make the webview background transparent when an alpha value of `0` is used.
-This means that if you use `rgba(0,0,0,0)`, the host window will show through.
+This means that if you use `rgba(0,0,0,0)` for `background-color` in your CSS, the host window will show through.
Often combined with [WindowIsTranslucent](#WindowIsTranslucent) to make frosty-looking applications.
### WindowIsTranslucent
@@ -430,6 +431,19 @@ Type: string
This defines the path where the WebView2 stores the user data. If empty `%APPDATA%\[BinaryName.exe]` will be used.
+### WebviewBrowserPath
+
+Name: WebviewBrowserPath
+
+Type: string
+
+This defines the path to a directory with WebView2 executable files and libraries. If empty, webview2 installed in the system will be used.
+
+Important information about distribution of fixed version runtime:
+- [How to get and extract runtime](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#details-about-the-fixed-version-runtime-distribution-mode)
+- [Known issues for fixed version](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#known-issues-for-fixed-version)
+- [The path of fixed version of the WebView2 Runtime should not contain \Edge\Application\.](https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.1245.22#createcorewebview2environmentwithoptions)
+
### Theme
Name: Theme
@@ -511,6 +525,33 @@ Type: `*windows.Messages`
A struct of strings used by the webview2 installer if a valid webview2 runtime is not found.
Customise this for any language you choose to support.
+### ResizeDebounceMS
+
+Name: ResizeDebounceMS
+
+Type: uint16
+
+ResizeDebounceMS is the amount of time to debounce redraws of webview2 when resizing the window.
+The default value (0) will perform redraws as fast as it can.
+
+### OnSuspend
+
+Name: OnSuspend
+
+Type: func()
+
+If set, this function will be called when windows initiates a switch to low power mode (suspend/hibernate)
+
+### OnResume
+
+Name: OnResume
+
+Type: func()
+
+If set, this function will be called when windows resumes from low power mode (suspend/hibernate)
+
+
+
## Mac Specific Options
### TitleBar
@@ -536,7 +577,7 @@ Name: WebviewIsTransparent
Type: bool
Setting this to `true` will make the webview background transparent when an alpha value of `0` is used.
-This means that if you use `rgba(0,0,0,0)`, the host window will show through.
+This means that if you use `rgba(0,0,0,0)` for `background-color` in your CSS, the host window will show through.
Often combined with [WindowIsTranslucent](#WindowIsTranslucent) to make frosty-looking applications.
### WindowIsTranslucent
diff --git a/website/docs/reference/project-config.mdx b/website/docs/reference/project-config.mdx
index 178504a63..de612d5f7 100644
--- a/website/docs/reference/project-config.mdx
+++ b/website/docs/reference/project-config.mdx
@@ -19,7 +19,7 @@ The project config resides in the `wails.json` file in the project directory. Th
"wailsjsdir": "[Relative path to the directory that the auto-generated JS modules will be created]",
"version": "[Project config version]",
"outputfilename": "[The name of the binary]",
- "debounceMS": 100, // The default time the dev server waits to reload when it detects a vhange in assets
+ "debounceMS": 100, // The default time the dev server waits to reload when it detects a change in assets
"devServer": "[Address to bind the wails dev sever to. Default: localhost:34115]",
"appargs": "[Arguments passed to the application in shell style when in dev mode]",
"runNonNativeBuildHooks": false, // Defines if build hooks should be run though they are defined for an OS other than the host OS.
@@ -35,7 +35,7 @@ The project config resides in the `wails.json` file in the project directory. Th
"copyright": "[The copyright of the product. Default: 'Copyright.........']",
"comments": "[A short comment of the app. Default: 'Built using Wails (https://wails.app)']"
},
- "nsisType": "['multiple': One installer per achitecture. 'single': Single universal installer for all architectures being built. Default: 'multiple']"
+ "nsisType": "['multiple': One installer per architecture. 'single': Single universal installer for all architectures being built. Default: 'multiple']"
}
```
diff --git a/website/docs/reference/runtime/intro.mdx b/website/docs/reference/runtime/intro.mdx
index b3616f689..583c84791 100644
--- a/website/docs/reference/runtime/intro.mdx
+++ b/website/docs/reference/runtime/intro.mdx
@@ -32,7 +32,7 @@ Quits the application.
### Environment
-Go Signature: `Enviromnent(ctx context.Context) EnvironmentInfo`
+Go Signature: `Environment(ctx context.Context) EnvironmentInfo`
Returns details of the current environment.
diff --git a/website/docs/reference/runtime/window.mdx b/website/docs/reference/runtime/window.mdx
index 915ca9ac4..baf6222e5 100644
--- a/website/docs/reference/runtime/window.mdx
+++ b/website/docs/reference/runtime/window.mdx
@@ -127,6 +127,14 @@ Will resize the window if the window is currently larger than the given dimensio
Setting a size of `0,0` will disable this constraint.
+### WindowSetAlwaysOnTop
+Go Signature: `WindowSetAlwaysOnTop(ctx context.Context, b bool)`
+
+JS Signature: `WindowSetAlwaysOnTop(b: Boolen)`
+
+Sets the window AlwaysOnTop or not on top.
+
+
### WindowSetPosition
Go Signature: `WindowSetPosition(ctx context.Context, x int, y int)`
@@ -176,10 +184,10 @@ JS Signature: `WindowUnminimise()`
Restores the window to the dimensions and position prior to minimising.
-### WindowSetRGBA
-Go Signature: `WindowSetRGBA(ctx context.Context, R, G, B, A uint8)`
+### WindowSetBackgroundColour
+Go Signature: `WindowSetBackgroundColour(ctx context.Context, R, G, B, A uint8)`
-JS Signature: `WindowSetRGBA(R, G, B, A)`
+JS Signature: `WindowSetBackgroundColour(R, G, B, A)`
Sets the background colour of the window to the given RGBA colour definition.
This colour will show through for all transparent pixels.
diff --git a/website/i18n/en/code.json b/website/i18n/en/code.json
index 4827318b8..8c25f6120 100644
--- a/website/i18n/en/code.json
+++ b/website/i18n/en/code.json
@@ -18,7 +18,7 @@
"message": "Quickly generate, build and package your projects using the Wails CLI."
},
"homepage.Tagline": {
- "message": "Build beautiful cross-platform applications using Go + HTML + CSS + JS"
+ "message": "Build beautiful cross-platform applications using Go"
},
"homepage.ButtonText": {
"message": "Get Started"
diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/community/templates.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/community/templates.mdx
index dfdc392b9..32a39ac2f 100644
--- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/community/templates.mdx
+++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/community/templates.mdx
@@ -35,7 +35,7 @@ sidebar_position: 1
- [wails-react-template](https://github.com/AlienRecall/wails-react-template) - 基于 reactjs 的模板
- [wails-react-template](https://github.com/flin7/wails-react-template) - 基于 React 并支持实时开发模式的轻量级模板
- [wails-vite-react-ts](https://github.com/lontten/wails-vite-react-ts) - 基于 Vite + React + TypeScript 的模板
-
+- [wails-template-nextjs](https://github.com/LGiki/wails-template-nextjs) - 基于 Next.js + TypeScript 的模板
## Svelte
diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/guides/frontend.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/guides/frontend.mdx
index af76b5d2c..1cb7ba724 100644
--- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/guides/frontend.mdx
+++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/guides/frontend.mdx
@@ -2,7 +2,7 @@
## 脚本注入
-当 Wails 为您的`index.html`提供服务时,默认情况下,它会将 2 个脚本注入``标签以加载`/wails/bindings.js`和`/wails/runtime.js`。 这些文件分别安装绑定和运行时。
+当 Wails 为您的`index.html`提供服务时,默认情况下,它会将 2 个脚本注入``标签以加载`/wails/ipc.js`和`/wails/runtime.js`。 这些文件分别安装绑定和运行时。
下面的代码显示了这些默认注入的位置:
diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/reference/runtime/intro.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/reference/runtime/intro.mdx
index 18de6ed93..08abbef9f 100644
--- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/reference/runtime/intro.mdx
+++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/reference/runtime/intro.mdx
@@ -25,7 +25,7 @@ Go 方法签名: `Quit(ctx context.Context)`
### 环境
-Go 方法签名: `Enviromnent(ctx context.Context) EnvironmentInfo`
+Go 方法签名: `Environment(ctx context.Context) EnvironmentInfo`
返回当前环境的详细信息。
diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.0.0-beta.34/community/templates.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.0.0-beta.34/community/templates.mdx
index e922abf4a..32a39ac2f 100644
--- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.0.0-beta.34/community/templates.mdx
+++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.0.0-beta.34/community/templates.mdx
@@ -35,6 +35,7 @@ sidebar_position: 1
- [wails-react-template](https://github.com/AlienRecall/wails-react-template) - 基于 reactjs 的模板
- [wails-react-template](https://github.com/flin7/wails-react-template) - 基于 React 并支持实时开发模式的轻量级模板
- [wails-vite-react-ts](https://github.com/lontten/wails-vite-react-ts) - 基于 Vite + React + TypeScript 的模板
+- [wails-template-nextjs](https://github.com/LGiki/wails-template-nextjs) - 基于 Next.js + TypeScript 的模板
## Svelte
diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.0.0-beta.34/guides/frontend.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.0.0-beta.34/guides/frontend.mdx
index af76b5d2c..1cb7ba724 100644
--- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.0.0-beta.34/guides/frontend.mdx
+++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.0.0-beta.34/guides/frontend.mdx
@@ -2,7 +2,7 @@
## 脚本注入
-当 Wails 为您的`index.html`提供服务时,默认情况下,它会将 2 个脚本注入``标签以加载`/wails/bindings.js`和`/wails/runtime.js`。 这些文件分别安装绑定和运行时。
+当 Wails 为您的`index.html`提供服务时,默认情况下,它会将 2 个脚本注入``标签以加载`/wails/ipc.js`和`/wails/runtime.js`。 这些文件分别安装绑定和运行时。
下面的代码显示了这些默认注入的位置:
diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.0.0-beta.34/reference/runtime/intro.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.0.0-beta.34/reference/runtime/intro.mdx
index 18de6ed93..08abbef9f 100644
--- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.0.0-beta.34/reference/runtime/intro.mdx
+++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.0.0-beta.34/reference/runtime/intro.mdx
@@ -25,7 +25,7 @@ Go 方法签名: `Quit(ctx context.Context)`
### 环境
-Go 方法签名: `Enviromnent(ctx context.Context) EnvironmentInfo`
+Go 方法签名: `Environment(ctx context.Context) EnvironmentInfo`
返回当前环境的详细信息。
diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-pages/credits.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-pages/credits.mdx
index f8255f21f..d5e6d2041 100644
--- a/website/i18n/zh-Hans/docusaurus-plugin-content-pages/credits.mdx
+++ b/website/i18n/zh-Hans/docusaurus-plugin-content-pages/credits.mdx
@@ -8,13 +8,13 @@
## 赞助商
@@ -65,9 +65,6 @@
-
-
-
@@ -101,15 +98,26 @@
-
-
+
+
+
+
+
+
+
+
`,
- }}
+ }}
/>
## 贡献者
+
+
+
+
+
import Contributors from "@wails/react-contributors";
diff --git a/website/src/css/custom.css b/website/src/css/custom.css
index cdfd09294..619d79f5c 100644
--- a/website/src/css/custom.css
+++ b/website/src/css/custom.css
@@ -39,7 +39,7 @@ html[data-theme="dark"] .docusaurus-highlight-code-line {
--ifm-color-primary-lightest: rgb(146, 224, 208);
--ifm-code-font-size: 95%;
--ifm-button-color: white;
- --ifm-container-width-xl: 85%;
+ --ifm-container-width-xl: 100%;
}
.docusaurus-highlight-code-line {
@@ -53,6 +53,10 @@ html[data-theme="dark"] .docusaurus-highlight-code-line {
counter-reset: line-number;
}
+.container {
+ padding-left: 2%;
+}
+
.prism-code.language-js .token-line::before,
.prism-code.language-ts .token-line::before,
.prism-code.language-go .token-line::before {
diff --git a/website/src/pages/changelog.md b/website/src/pages/changelog.md
index 086a7427e..99be4d38d 100644
--- a/website/src/pages/changelog.md
+++ b/website/src/pages/changelog.md
@@ -7,6 +7,102 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+## [v2.0.0-beta.38] - 2022-06-27
+
+### Added
+
+* Add race detector to build & dev by @Lyimmi in https://github.com/wailsapp/wails/pull/1426
+* [linux] Support `linux/arm` architecture by @Lyimmi in https://github.com/wailsapp/wails/pull/1427
+* Create gitignore when using `-g` option by @jaesung9507 in https://github.com/wailsapp/wails/pull/1430
+* [windows] Add Suspend/Resume callback support by @leaanthony in https://github.com/wailsapp/wails/pull/1474
+* Add runtime function `WindowSetAlwaysOnTop` by @chenxiao1990 in https://github.com/wailsapp/wails/pull/1442
+* [windows] Allow setting browser path by @NanoNik in https://github.com/wailsapp/wails/pull/1448
+
+### Fixed
+
+* [linux] Improve switching to main thread for callbacks by @stffabi in https://github.com/wailsapp/wails/pull/1392
+* [windows] Fix WebView2 minimum runtime version check by @stffabi in https://github.com/wailsapp/wails/pull/1456
+* [linux] Fix apt command syntax (#1458) by @abtin in https://github.com/wailsapp/wails/pull/1461
+* [windows] Set Window Background colour if provided + debounce redraw option by @leaanthony
+ in https://github.com/wailsapp/wails/pull/1466
+* Fix small typo in docs by @LukenSkyne in https://github.com/wailsapp/wails/pull/1449
+* Fix the url to surge by @andywenk in https://github.com/wailsapp/wails/pull/1460
+* Fixed theme change at runtime by @leaanthony in https://github.com/wailsapp/wails/pull/1473
+* Fix: Don't stop if unable to remove temporary bindings build by @leaanthony
+ in https://github.com/wailsapp/wails/pull/1465
+* [windows] Pass the correct installationStatus to the webview installation strategy by @stffabi
+ in https://github.com/wailsapp/wails/pull/1483
+* [windows] Make `SetBackgroundColour` compatible for `windows/386` by @stffabi
+ in https://github.com/wailsapp/wails/pull/1493
+* Fix lit-ts template by @Orijhins in https://github.com/wailsapp/wails/pull/1494
+
+### Changed
+
+* [windows] Load WebView2 loader from embedded only by @stffabi in https://github.com/wailsapp/wails/pull/1432
+* Add showcase entry for October + update homepage carousel entry for October by @marcus-crane
+ in https://github.com/wailsapp/wails/pull/1436
+* Always use return in wrapped method by @leaanthony in https://github.com/wailsapp/wails/pull/1410
+* [windows] Unlock OSThread after native calls have been finished by @stffabi
+ in https://github.com/wailsapp/wails/pull/1441
+* Add `BackgroundColour` and deprecate `RGBA` by @leaanthony in https://github.com/wailsapp/wails/pull/1475
+* AssetsHandler remove retry logic in dev mode by @stffabi in https://github.com/wailsapp/wails/pull/1479
+* Add Solid JS template to docs by @sidwebworks in https://github.com/wailsapp/wails/pull/1492
+* Better signal handling by @leaanthony in https://github.com/wailsapp/wails/pull/1488
+* Chore/react 18 create root by @tomanagle in https://github.com/wailsapp/wails/pull/1489
+
+## New Contributors
+
+* @jaesung9507 made their first contribution in https://github.com/wailsapp/wails/pull/1430
+* @LukenSkyne made their first contribution in https://github.com/wailsapp/wails/pull/1449
+* @andywenk made their first contribution in https://github.com/wailsapp/wails/pull/1460
+* @abtin made their first contribution in https://github.com/wailsapp/wails/pull/1461
+* @chenxiao1990 made their first contribution in https://github.com/wailsapp/wails/pull/1442
+* @NanoNik made their first contribution in https://github.com/wailsapp/wails/pull/1448
+* @sidwebworks made their first contribution in https://github.com/wailsapp/wails/pull/1492
+* @tomanagle made their first contribution in https://github.com/wailsapp/wails/pull/1489
+
+## [v2.0.0-beta.37] - 2022-05-26
+
+### Added
+
+* Add `nogen` flag in wails dev command by @mondy in https://github.com/wailsapp/wails/pull/1413
+* Initial support for new native translucency in Windows Preview by @leaanthony
+ in https://github.com/wailsapp/wails/pull/1400
+
+### Fixed
+
+* Bugfix/incorrect bindings by @leaanthony in https://github.com/wailsapp/wails/pull/1383
+* Fix runtime.js events by @polikow in https://github.com/wailsapp/wails/pull/1369
+* Fix docs formatting by @antimatter96 in https://github.com/wailsapp/wails/pull/1372
+* Events | fixes #1388 by @lambdajack in https://github.com/wailsapp/wails/pull/1390
+* bugfix: correct typo by @tmclane in https://github.com/wailsapp/wails/pull/1391
+* Fix typo in docs by @LGiki in https://github.com/wailsapp/wails/pull/1393
+* Fix typo bindings.js to ipc.js by @rayshoo in https://github.com/wailsapp/wails/pull/1406
+* Make sure to execute the menu callbacks on a new goroutine by @stffabi in https://github.com/wailsapp/wails/pull/1403
+* Update runtime.d.ts & templates by @Yz4230 in https://github.com/wailsapp/wails/pull/1421
+* Add missing className to input in React and Preact templates by @edwardbrowncross in https://github.com/wailsapp/wails/pull/1419
+
+### Changed
+* Improve multi-platform builds by @stffabi in https://github.com/wailsapp/wails/pull/1373
+* During wails dev only use reload logic if no AssetsHandler are in use by @stffabi in https://github.com/wailsapp/wails/pull/1385
+* Update events.mdx by @Junkher in https://github.com/wailsapp/wails/pull/1387
+* Add Next.js template by @LGiki in https://github.com/wailsapp/wails/pull/1394
+* Add docs on wails generate module by @TechplexEngineer in https://github.com/wailsapp/wails/pull/1414
+* Add macos custom menu EditMenu tips by @daodao97 in https://github.com/wailsapp/wails/pull/1423
+
+### New Contributors
+* @polikow made their first contribution in https://github.com/wailsapp/wails/pull/1369
+* @antimatter96 made their first contribution in https://github.com/wailsapp/wails/pull/1372
+* @Junkher made their first contribution in https://github.com/wailsapp/wails/pull/1387
+* @lambdajack made their first contribution in https://github.com/wailsapp/wails/pull/1390
+* @LGiki made their first contribution in https://github.com/wailsapp/wails/pull/1393
+* @rayshoo made their first contribution in https://github.com/wailsapp/wails/pull/1406
+* @TechplexEngineer made their first contribution in https://github.com/wailsapp/wails/pull/1414
+* @mondy made their first contribution in https://github.com/wailsapp/wails/pull/1413
+* @Yz4230 made their first contribution in https://github.com/wailsapp/wails/pull/1421
+* @daodao97 made their first contribution in https://github.com/wailsapp/wails/pull/1423
+* @edwardbrowncross made their first contribution in https://github.com/wailsapp/wails/pull/1419
+
## [v2.0.0-beta.36] - 2022-04-27
diff --git a/website/src/pages/credits.mdx b/website/src/pages/credits.mdx
index 21abd50e6..61b88d3dc 100644
--- a/website/src/pages/credits.mdx
+++ b/website/src/pages/credits.mdx
@@ -8,13 +8,13 @@
## Sponsors
@@ -65,9 +65,6 @@
-
-
-
@@ -101,15 +98,26 @@
-
-
+
+
+
+
+
+
+
+
`,
- }}
+ }}
/>
## Contributors
+
+
+
+
+
import Contributors from "@wails/react-contributors";
diff --git a/website/static/img/october.png b/website/static/img/october.png
index ba5052bee..b25c1dc92 100644
Binary files a/website/static/img/october.png and b/website/static/img/october.png differ
diff --git a/website/static/img/showcase/october.png b/website/static/img/showcase/october.png
new file mode 100644
index 000000000..7dfbccdf6
Binary files /dev/null and b/website/static/img/showcase/october.png differ
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/gettingstarted/firstproject.mdx b/website/versioned_docs/version-v2.0.0-beta.34/gettingstarted/firstproject.mdx
deleted file mode 100644
index 8d4c8d946..000000000
--- a/website/versioned_docs/version-v2.0.0-beta.34/gettingstarted/firstproject.mdx
+++ /dev/null
@@ -1,54 +0,0 @@
----
-sidebar_position: 2
----
-
-# Creating a Project
-
-## Project Generation
-
-Now that the CLI is installed, you can generate a new project by using the `wails init` command.
-
-To get up and running quickly, you can generate a default project by running `wails init -n myproject`. This will
-create a directory called `myproject` and populate it with the default template.
-
-Other project templates are available and can be listed using `wails init -l`.
-There are also [community templates](../community/templates) available that offer different capabilities and frameworks.
-
-To see the other options available, you can run `wails init -help`.
-More details can be found in the [CLI Reference](../reference/cli#init).
-
-## Project Layout
-
-Wails projects have the following layout:
-
-```
-.
-├── build/
-│ ├── appicon.png
-│ ├── darwin/
-│ └── windows/
-├── frontend/
-├── go.mod
-├── go.sum
-├── main.go
-└── wails.json
-```
-
-### Project structure rundown
-
-- `/main.go` - The main application
-- `/frontend/` - Frontend project files
-- `/build/` - Project build directory
- - `/build/appicon.png` - The application icon
- - `/build/darwin/` - Mac specific project files
- - `/build/windows/` - Windows specific project files
-- `/wails.json` - The project configuration
-- `/go.mod` - Go module file
-- `/go.sum` - Go module checksum file
-
-The `frontend` directory has nothing specific to Wails and can be any frontend project of your choosing.
-
-The `build` directory is used during the build process. These files may be updated to customise your builds. If
-files are removed from the build directory, default versions will be regenerated.
-
-The default module name in `go.mod` is "changeme". You should change this to something more appropriate.
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/guides/developing-wails.mdx b/website/versioned_docs/version-v2.0.0-beta.34/guides/developing-wails.mdx
deleted file mode 100644
index 58f9e9bd8..000000000
--- a/website/versioned_docs/version-v2.0.0-beta.34/guides/developing-wails.mdx
+++ /dev/null
@@ -1,39 +0,0 @@
-
-# Contributing
-
-This page is a guide on how to contribute to the Wails project.
-
-First, a word of warning: Wails v2 has been through a number of iterations and pivots. There is a lot of code that
-is either on hold or deprecated. Reading the whole project and trying to understand it may be confusing. This document
-aims to focus on what is current and how to understand that.
-
-## Bugs
-
-For raising bugs, please open a ticket on GitHub and give it the \[v2\] label. Include the output of `wails doctor`
-in the ticket to help us understand your environment.
-
-For fixing bugs, please comment on a ticket that you'd like to take it on and we will put a label on the ticket.
-It is best to use Windows as it is done in pure Go, making debugging much easier.
-
-## Features
-
-To request a new feature, raise a ticket so that it may be discussed. The ticket should be given the
-"Feature Request" label. These will be discussed and if selected for development will be given the label
-"Ready for Development".
-
-To implement a new feature, raise a ticket as above or select a ticket with the "Ready for Development" label.
-
-When raising a PR, be mindful to state what platforms the PR has been tested on. Any new feature will not be accepted unless it works
-on all platforms (if it can).
-
-:::warning What not to do
-
-PRs for features with no tickets aren't helpful as there's no context to the PR and it will not be prioritised.
-
-:::
-
-## Documentation
-
-Contributing to the documentation is easy by clicking on the "Edit this page" link on any of the pages. Documentation
-updates can be done ad-hoc, without a ticket.
-
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/community/showcase/surge.mdx b/website/versioned_docs/version-v2.0.0-beta.35/community/showcase/surge.mdx
deleted file mode 100644
index bccc51c82..000000000
--- a/website/versioned_docs/version-v2.0.0-beta.35/community/showcase/surge.mdx
+++ /dev/null
@@ -1,8 +0,0 @@
-# Surge
-
-
-
-
-
-[Surge](https://surge.rule110.io/) is a p2p filesharing app designed to utilize blockchain technologies to enable 100% anonymous file transfers. Surge is end-to-end encrypted, decentralized and open source.
-
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/appendix/_category_.json b/website/versioned_docs/version-v2.0.0-beta.37/appendix/_category_.json
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/appendix/_category_.json
rename to website/versioned_docs/version-v2.0.0-beta.37/appendix/_category_.json
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/community/_category_.json b/website/versioned_docs/version-v2.0.0-beta.37/community/_category_.json
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/community/_category_.json
rename to website/versioned_docs/version-v2.0.0-beta.37/community/_category_.json
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/community/links.mdx b/website/versioned_docs/version-v2.0.0-beta.37/community/links.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/community/links.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/community/links.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/community/showcase/_category_.json b/website/versioned_docs/version-v2.0.0-beta.37/community/showcase/_category_.json
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/community/showcase/_category_.json
rename to website/versioned_docs/version-v2.0.0-beta.37/community/showcase/_category_.json
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/community/showcase/encrypteasy.mdx b/website/versioned_docs/version-v2.0.0-beta.37/community/showcase/encrypteasy.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/community/showcase/encrypteasy.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/community/showcase/encrypteasy.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/community/showcase/filehound.mdx b/website/versioned_docs/version-v2.0.0-beta.37/community/showcase/filehound.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/community/showcase/filehound.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/community/showcase/filehound.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/community/showcase/mollywallet.mdx b/website/versioned_docs/version-v2.0.0-beta.37/community/showcase/mollywallet.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/community/showcase/mollywallet.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/community/showcase/mollywallet.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/community/showcase/optimus.mdx b/website/versioned_docs/version-v2.0.0-beta.37/community/showcase/optimus.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/community/showcase/optimus.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/community/showcase/optimus.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/community/showcase/portfall.mdx b/website/versioned_docs/version-v2.0.0-beta.37/community/showcase/portfall.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/community/showcase/portfall.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/community/showcase/portfall.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/community/showcase/riftshare.mdx b/website/versioned_docs/version-v2.0.0-beta.37/community/showcase/riftshare.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/community/showcase/riftshare.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/community/showcase/riftshare.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/community/showcase/surge.mdx b/website/versioned_docs/version-v2.0.0-beta.37/community/showcase/surge.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/community/showcase/surge.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/community/showcase/surge.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/community/showcase/wally.mdx b/website/versioned_docs/version-v2.0.0-beta.37/community/showcase/wally.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/community/showcase/wally.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/community/showcase/wally.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/community/showcase/wombat.mdx b/website/versioned_docs/version-v2.0.0-beta.37/community/showcase/wombat.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/community/showcase/wombat.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/community/showcase/wombat.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/community/showcase/ytd.mdx b/website/versioned_docs/version-v2.0.0-beta.37/community/showcase/ytd.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/community/showcase/ytd.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/community/showcase/ytd.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/community/templates.mdx b/website/versioned_docs/version-v2.0.0-beta.37/community/templates.mdx
similarity index 81%
rename from website/versioned_docs/version-v2.0.0-beta.34/community/templates.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/community/templates.mdx
index 4dee08cd1..2ed94f04e 100644
--- a/website/versioned_docs/version-v2.0.0-beta.34/community/templates.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.37/community/templates.mdx
@@ -5,7 +5,7 @@ sidebar_position: 1
# Templates
This page serves as a list for community supported templates. Please submit a PR (click `Edit this page` at the bottom)
-to include your templates. To build your own template, please see the [Templates](../guides/templates) guide.
+to include your templates. To build your own template, please see the [Templates](../guides/templates.mdx) guide.
To use these templates, run `wails init -n "Your Project Name" -t [the link below[@version]]`
@@ -35,10 +35,17 @@ If you are unsure about a template, inspect `package.json` and `wails.json` for
- [wails-react-template](https://github.com/AlienRecall/wails-react-template) - A template using reactjs
- [wails-react-template](https://github.com/flin7/wails-react-template) - A minimal template for React that supports live development
-- [wails-vite-react-ts](https://github.com/lontten/wails-vite-react-ts) - A template with Vite + React + TypeScript
+- [wails-template-nextjs](https://github.com/LGiki/wails-template-nextjs) - A template using Next.js and TypeScript
+
+# Solid
+- [wails-solid-template](https://github.com/sidwebworks/wails-solid-template) - A template using Solid JS
## Svelte
- [wails-svelte-template](https://github.com/raitonoberu/wails-svelte-template) - A template using Svelte
- [wails-vite-svelte-template](https://github.com/BillBuilt/wails-vite-svelte-template) - A template using Svelte and Vite
- [wails-vite-svelte-tailwind-template](https://github.com/BillBuilt/wails-vite-svelte-tailwind-template) - A template using Svelte and Vite with TailwindCSS v3
+
+## Elm
+
+- [wails-elm-template](https://github.com/benjamin-thomas/wails-elm-template) - Develop your GUI app with functional programming and a **snappy** hot-reload setup :tada: :rocket:
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/gettingstarted/_category_.json b/website/versioned_docs/version-v2.0.0-beta.37/gettingstarted/_category_.json
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/gettingstarted/_category_.json
rename to website/versioned_docs/version-v2.0.0-beta.37/gettingstarted/_category_.json
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/gettingstarted/building.mdx b/website/versioned_docs/version-v2.0.0-beta.37/gettingstarted/building.mdx
similarity index 92%
rename from website/versioned_docs/version-v2.0.0-beta.34/gettingstarted/building.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/gettingstarted/building.mdx
index 6709a026a..8c6957117 100644
--- a/website/versioned_docs/version-v2.0.0-beta.34/gettingstarted/building.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.37/gettingstarted/building.mdx
@@ -15,5 +15,5 @@ If you run the binary, you should see the default application:
-For more details on compilation options, please refer to the [CLI Reference](../reference/cli#build).
+For more details on compilation options, please refer to the [CLI Reference](../reference/cli.mdx#build).
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/gettingstarted/development.mdx b/website/versioned_docs/version-v2.0.0-beta.37/gettingstarted/development.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/gettingstarted/development.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/gettingstarted/development.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/gettingstarted/firstproject.mdx b/website/versioned_docs/version-v2.0.0-beta.37/gettingstarted/firstproject.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/gettingstarted/firstproject.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/gettingstarted/firstproject.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/gettingstarted/installation.mdx b/website/versioned_docs/version-v2.0.0-beta.37/gettingstarted/installation.mdx
similarity index 92%
rename from website/versioned_docs/version-v2.0.0-beta.34/gettingstarted/installation.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/gettingstarted/installation.mdx
index a48364ce4..3b4cd33cc 100644
--- a/website/versioned_docs/version-v2.0.0-beta.34/gettingstarted/installation.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.37/gettingstarted/installation.mdx
@@ -22,7 +22,7 @@ Wails has a number of common dependencies that are required before installation:
Download Go from the [Go Downloads Page](https://golang.org/dl/).
-Ensure that you follow the official [Go installation instructions](https://golang.org/doc/install#install). You will also need to ensure that your `PATH` environment variable also includes the path to your `~/go/bin` directory. Restart your terminal and do the following checks:
+Ensure that you follow the official [Go installation instructions](https://golang.org/doc/install.mdx#install). You will also need to ensure that your `PATH` environment variable also includes the path to your `~/go/bin` directory. Restart your terminal and do the following checks:
- Check Go is installed correctly: `go version`
- Check "~/go/bin" is in your PATH variable: `echo $PATH | grep go/bin`
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/guides/_category_.json b/website/versioned_docs/version-v2.0.0-beta.37/guides/_category_.json
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/guides/_category_.json
rename to website/versioned_docs/version-v2.0.0-beta.37/guides/_category_.json
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/guides/application-development.mdx b/website/versioned_docs/version-v2.0.0-beta.37/guides/application-development.mdx
similarity index 89%
rename from website/versioned_docs/version-v2.0.0-beta.34/guides/application-development.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/guides/application-development.mdx
index 639cc089c..039cb227d 100644
--- a/website/versioned_docs/version-v2.0.0-beta.34/guides/application-development.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.37/guides/application-development.mdx
@@ -30,7 +30,7 @@ func (a *App) shutdown(ctx context.Context) {
- The startup method is called as soon as Wails allocates the resources it needs and is a good place for creating resources,
setting up event listeners and anything else the application needs at startup.
It is given a `context.Context` which is usually saved in a struct field. This context is needed for calling the
- [runtime](../reference/runtime/intro). If this method returns an error, the application will terminate.
+ [runtime](../reference/runtime/intro.mdx). If this method returns an error, the application will terminate.
In dev mode, the error will be output to the console.
- The shutdown method will be called by Wails right at the end of the shutdown process. This is a good place to deallocate
@@ -59,7 +59,7 @@ func main() {
```
-More information on application lifecycle hooks can be found [here](../howdoesitwork#application-lifecycle-callbacks).
+More information on application lifecycle hooks can be found [here](../howdoesitwork.mdx#application-lifecycle-callbacks).
## Binding Methods
@@ -113,7 +113,7 @@ func main() {
This will bind all public methods in our `App` struct (it will never bind the startup and shutdown methods).
-More information on Binding can be found [here](../howdoesitwork#method-binding).
+More information on Binding can be found [here](../howdoesitwork.mdx#method-binding).
## Application Menu
@@ -161,6 +161,15 @@ The second, if given, will be executed in the `frontend` directory to build the
If these 2 keys aren't given, then Wails does absolutely nothing with the frontend. It is only expecting that `embed.FS`.
+### AssetsHandler
+
+A Wails v2 app can optionally define a `http.Handler` in the `options.App`, which allows hooking into the AssetServer to
+create files on the fly or process POST/PUT requests.
+GET requests are always first handled by the `assets` FS. If the FS doesn't find the requested file the request will be
+forwarded to the `http.Handler` for serving. Any requests other than GET will be directly processed by the `AssetsHandler`
+if specified.
+It's also possible to only use the `AssetsHandler` by specifiy `nil` as the `Assets` option.
+
## Built in Dev Server
Running `wails dev` will start the built in dev server which will start a file watcher in your project directory. By
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/guides/bleeding-edge.mdx b/website/versioned_docs/version-v2.0.0-beta.37/guides/bleeding-edge.mdx
similarity index 74%
rename from website/versioned_docs/version-v2.0.0-beta.34/guides/bleeding-edge.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/guides/bleeding-edge.mdx
index 65a486918..292b9d523 100644
--- a/website/versioned_docs/version-v2.0.0-beta.34/guides/bleeding-edge.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.37/guides/bleeding-edge.mdx
@@ -35,7 +35,20 @@ To revert back to a stable version, run:
If you want to test a branch, follow the instructions above, but ensure you switch the branch you want to test before installing:
- `git clone https://github.com/wailsapp/wails`
+- `cd wails`
- `git checkout -b branch-to-test --track origin/branch-to-test`
-- `cd wails/v2/cmd/wails`
+- `cd v2/cmd/wails`
- `go install`
+## Testing a PR
+
+If you want to test a PR, follow the instructions above, but ensure you fetch the PR and switch the branch before installing.
+Please replace `[IDofThePR]` with the ID of the PR shown on github.com:
+
+- `git clone https://github.com/wailsapp/wails`
+- `cd wails`
+- `git fetch -u origin pull/[IDofThePR]/head:test/pr-[IDofThePR]`
+- `git checkout test/pr-[IDofThePR]`
+- `git reset --hard HEAD`
+- `cd v2/cmd/wails`
+- `go install`
diff --git a/website/docs/guides/developing-wails.mdx b/website/versioned_docs/version-v2.0.0-beta.37/guides/developing-wails.mdx
similarity index 100%
rename from website/docs/guides/developing-wails.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/guides/developing-wails.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/guides/frameless.mdx b/website/versioned_docs/version-v2.0.0-beta.37/guides/frameless.mdx
similarity index 88%
rename from website/versioned_docs/version-v2.0.0-beta.34/guides/frameless.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/guides/frameless.mdx
index 9a2adc12a..cd78d3937 100644
--- a/website/versioned_docs/version-v2.0.0-beta.34/guides/frameless.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.37/guides/frameless.mdx
@@ -1,8 +1,8 @@
# Frameless Applications
-Wails supports applications with no frame. This can be achieved by using the [frameless](../reference/options#frameless)
-field in [Application Options](../reference/options#application-options).
+Wails supports applications with no frame. This can be achieved by using the [frameless](../reference/options.mdx#frameless)
+field in [Application Options](../reference/options.mdx#application-options).
Wails offers a simple solution for dragging the window: Any HTML element that has the attribute "data-wails-drag" will
act as a "drag handle". This property applies to all nested elements. If you need to indicate that a nested element
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/guides/frontend.mdx b/website/versioned_docs/version-v2.0.0-beta.37/guides/frontend.mdx
similarity index 97%
rename from website/versioned_docs/version-v2.0.0-beta.34/guides/frontend.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/guides/frontend.mdx
index 84489cd99..6c9d0cf27 100644
--- a/website/versioned_docs/version-v2.0.0-beta.34/guides/frontend.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.37/guides/frontend.mdx
@@ -3,7 +3,7 @@
## Script Injection
-When Wails serves your `index.html`, by default, it will inject 2 script entries into the `` tag to load `/wails/bindings.js`
+When Wails serves your `index.html`, by default, it will inject 2 script entries into the `` tag to load `/wails/ipc.js`
and `/wails/runtime.js`. These files install the bindings and runtime respectively.
The code below shows where these are injected by default:
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/guides/ides.mdx b/website/versioned_docs/version-v2.0.0-beta.37/guides/ides.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/guides/ides.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/guides/ides.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/guides/linux-distro-support.mdx b/website/versioned_docs/version-v2.0.0-beta.37/guides/linux-distro-support.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/guides/linux-distro-support.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/guides/linux-distro-support.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/guides/manual-builds.mdx b/website/versioned_docs/version-v2.0.0-beta.37/guides/manual-builds.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/guides/manual-builds.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/guides/manual-builds.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/guides/migrating.mdx b/website/versioned_docs/version-v2.0.0-beta.37/guides/migrating.mdx
similarity index 89%
rename from website/versioned_docs/version-v2.0.0-beta.34/guides/migrating.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/guides/migrating.mdx
index 9c3d92933..1474131f8 100644
--- a/website/versioned_docs/version-v2.0.0-beta.34/guides/migrating.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.37/guides/migrating.mdx
@@ -25,7 +25,7 @@ Example:
app.Run()
```
-In v2, there is just a single method, `wails.Run()`, that accepts [application options](../reference/options#application-options).
+In v2, there is just a single method, `wails.Run()`, that accepts [application options](../reference/options.mdx#application-options).
```go title="v2"
err := wails.Run(&options.App{
@@ -43,7 +43,7 @@ In v2, there is just a single method, `wails.Run()`, that accepts [application o
In v1, it was possible to bind both arbitrary functions and structs. In v2, this has been simplified to only binding structs.
The struct instances that were previously passed to the `Bind()` method in v1, are now specified in the `Bind` field of
-the [application options](../reference/options#application-options):
+the [application options](../reference/options.mdx#application-options):
```go title="v1"
app := wails.CreateApp(/* options */)
@@ -64,13 +64,13 @@ In v1, bound methods were available to the frontend at `window.backend`. This ha
### Application Lifecycle
In v1, there were 2 special methods in a bound struct: `WailsInit()` and `WailsShutdown()`. These have
-been replaced with 3 lifecycle hooks as part of the [application options](../reference/options#application-options):
+been replaced with 3 lifecycle hooks as part of the [application options](../reference/options.mdx#application-options):
-- [OnStartup](../reference/options#onstartup)
-- [OnShutdown](../reference/options#onshutdown)
-- [OnDomReady](../reference/options#ondomready)
+- [OnStartup](../reference/options.mdx#onstartup)
+- [OnShutdown](../reference/options.mdx#onshutdown)
+- [OnDomReady](../reference/options.mdx#ondomready)
-Note: [OnDomReady](../reference/options#ondomready) replaces the `wails:ready` system event in v1.
+Note: [OnDomReady](../reference/options.mdx#ondomready) replaces the `wails:ready` system event in v1.
These methods can be standard functions, but a common practice is to have them part of a struct:
@@ -96,11 +96,11 @@ func (b *Basic) startup(ctx context.Context) {
The runtime in v2 is much richer than v1 with support for menus, window manipulation
and better dialogs. The signature of the methods has changed slightly - please refer
-the the [Runtime Reference](../reference/runtime/intro).
+the the [Runtime Reference](../reference/runtime/intro.mdx).
-In v1, the [runtime](../reference/runtime/intro) was available via a struct passed to `WailsInit()`.
+In v1, the [runtime](../reference/runtime/intro.mdx) was available via a struct passed to `WailsInit()`.
In v2, the runtime has been moved out to its own package. Each method in the runtime takes the
-`context.Context` that is passed to the [OnStartup](../reference/options#onstartup) method.
+`context.Context` that is passed to the [OnStartup](../reference/options.mdx#onstartup) method.
```go title="Runtime Example"
package main
@@ -173,7 +173,7 @@ func main() {
Of course, bundlers can be used if you wish to. The only requirement is to pass
the final application assets directory to Wails using an `embed.FS` in the `Assets`
-key of the [application options](../reference/options#application-options).
+key of the [application options](../reference/options.mdx#application-options).
### Project Configuration
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/guides/overscroll.mdx b/website/versioned_docs/version-v2.0.0-beta.37/guides/overscroll.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/guides/overscroll.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/guides/overscroll.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/guides/routing.mdx b/website/versioned_docs/version-v2.0.0-beta.37/guides/routing.mdx
similarity index 94%
rename from website/versioned_docs/version-v2.0.0-beta.34/guides/routing.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/guides/routing.mdx
index 7551e110f..3e1f255d8 100644
--- a/website/versioned_docs/version-v2.0.0-beta.34/guides/routing.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.37/guides/routing.mdx
@@ -20,7 +20,7 @@ const router = createRouter({
## Angular
-The recommended approach for routing in Angular is [HashLocationStrategy](https://codecraft.tv/courses/angular/routing/routing-strategies/#_hashlocationstrategy):
+The recommended approach for routing in Angular is [HashLocationStrategy](https://codecraft.tv/courses/angular/routing/routing-strategies#_hashlocationstrategy):
```ts
RouterModule.forRoot(routes, {useHash: true})
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/guides/signing.mdx b/website/versioned_docs/version-v2.0.0-beta.37/guides/signing.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/guides/signing.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/guides/signing.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/guides/templates.mdx b/website/versioned_docs/version-v2.0.0-beta.37/guides/templates.mdx
similarity index 98%
rename from website/versioned_docs/version-v2.0.0-beta.34/guides/templates.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/guides/templates.mdx
index 824fb6eb9..090cf8a9e 100644
--- a/website/versioned_docs/version-v2.0.0-beta.34/guides/templates.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.37/guides/templates.mdx
@@ -4,7 +4,7 @@
Wails generates projects from pre-created templates. In v1, this was a difficult to maintain set of projects that were
subject to going out of date. In v2, to empower the community, a couple of new features have been added for templates:
-- Ability to generate projects from [Remote Templates](../reference/cli#remote-templates)
+- Ability to generate projects from [Remote Templates](../reference/cli.mdx#remote-templates)
- Tooling to help create your own templates
## Creating Templates
@@ -91,5 +91,5 @@ Publishing a template is simply pushing the files to GitHub. The following best
- Remove any unwanted files and directories (such as `.git`) from your frontend directory
- Ensure that `template.json` is complete, especially `helpurl`
- Push the files to GitHub
-- Create a PR on the [Community Templates](../community/templates) page
+- Create a PR on the [Community Templates](../community/templates.mdx) page
- Announce the template on the [Template Announcement](https://github.com/wailsapp/wails/discussions/825) discussion board
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/guides/troubleshooting.mdx b/website/versioned_docs/version-v2.0.0-beta.37/guides/troubleshooting.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/guides/troubleshooting.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/guides/troubleshooting.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/guides/windows-installer.mdx b/website/versioned_docs/version-v2.0.0-beta.37/guides/windows-installer.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/guides/windows-installer.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/guides/windows-installer.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/guides/windows.mdx b/website/versioned_docs/version-v2.0.0-beta.37/guides/windows.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/guides/windows.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/guides/windows.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/howdoesitwork.mdx b/website/versioned_docs/version-v2.0.0-beta.37/howdoesitwork.mdx
similarity index 57%
rename from website/versioned_docs/version-v2.0.0-beta.34/howdoesitwork.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/howdoesitwork.mdx
index 4a0872cd3..a66e8cb9a 100644
--- a/website/versioned_docs/version-v2.0.0-beta.34/howdoesitwork.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.37/howdoesitwork.mdx
@@ -83,7 +83,7 @@ This example has the following options set:
- `OnShutdown` - A callback for when the application is about to quit
- `Bind` - A slice of struct instances that we wish to expose to the frontend
-A full list of application options can be found in the [Options Reference](./reference/options).
+A full list of application options can be found in the [Options Reference](reference/options).
#### Assets
@@ -108,24 +108,25 @@ the application.
When running in development mode using the `wails dev` command, the assets are loaded off disk, and any changes result
in a "live reload". The location of the assets will be inferred from the `embed.FS`.
-More details can be found in the [Application Development Guide](./guides/application-development).
+More details can be found in the [Application Development Guide](guides/application-development.mdx).
#### Application Lifecycle Callbacks
-Just before the frontend is about to load `index.html`, a callback is made to the function provided in [OnStartup](./reference/options#OnStartup).
+Just before the frontend is about to load `index.html`, a callback is made to the function provided in [OnStartup](reference/options.mdx#onstartup).
A standard Go context is passed to this method. This context is required when calling the runtime so a standard pattern is to save
-a reference to in this method. Just before the application shuts down, the [OnShutdown](./reference/options#OnShutdown) callback is called in the same way,
-again with the context. There is also an [OnDomReady](./reference/options#OnDomReady) callback for when the frontend
+a reference to in this method. Just before the application shuts down, the [OnShutdown](reference/options.mdx#onshutdown) callback is called in the same way,
+again with the context. There is also an [OnDomReady](reference/options.mdx#ondomready) callback for when the frontend
has completed loading all assets in `index.html` and is equivalent of the [`body onload`](https://www.w3schools.com/jsref/event_onload.asp) event in Javascript.
It is also possible to hook into the window close (or application quit) event by setting the
-option [OnBeforeClose](./reference/options#OnBeforeClose).
+option [OnBeforeClose](reference/options.mdx#onbeforeclose).
#### Method Binding
The `Bind` option is one of the most important options in a Wails application. It specifies which struct methods
-to expose to the frontend. When the application starts, it examines the struct instances listed in the `Bind` field in
-the options, determines which methods are public (starts with an uppercase letter) and will generate Javascript versions
-of those methods that can be called by the frontend code.
+to expose to the frontend. Think of structs like "controllers" in a traditional web application. When the application
+starts, it examines the struct instances listed in the `Bind` field in the options, determines which methods are
+public (starts with an uppercase letter) and will generate Javascript versions of those methods that can be called
+by the frontend code.
:::info Note
@@ -135,7 +136,7 @@ of those methods that can be called by the frontend code.
In this example, we create a new `App` instance and then add this instance to the `Bind` option in `wails.Run`:
-```go {16,26} title="main.go"
+```go {16,24} title="main.go"
package main
import (
@@ -158,8 +159,6 @@ func main() {
Width: 1024,
Height: 768,
Assets: &assets,
- OnStartup: app.startup,
- OnShutdown: app.shutdown,
Bind: []interface{}{
app,
},
@@ -174,67 +173,41 @@ type App struct {
ctx context.Context
}
-func (b *App) startup(ctx context.Context) {
- b.ctx = ctx
-}
-
-func (b *App) shutdown(ctx context.Context) {}
-
-func (b *App) Greet(name string) string {
+func (a *App) Greet(name string) string {
return fmt.Sprintf("Hello %s!", name)
}
```
You may bind as many structs as you like. Just make sure you create an instance of it and pass it in `Bind`:
-```go {10-12}
-...
+```go {8-10}
+ //...
err := wails.Run(&options.App{
Title: "Basic Demo",
Width: 1024,
Height: 768,
Assets: &assets,
- OnStartup: app.startup,
- OnShutdown: app.shutdown,
Bind: []interface{}{
app,
&mystruct1{},
&mystruct2{},
},
})
-...
+
```
-The bound methods are located in the frontend at `window.go...`.
-In the example above, we bind `app`, which has one public method `Greet`.
-This can be called in Javascript by calling `window.go.main.App.Greet`.
-These methods return a Promise. A successful call will result in the first return value from the Go call to be passed
-to the `resolve` handler. An unsuccessful call is when a Go method that has an error type as it's second return value,
-passes an error instance back to the caller. This is passed back via the `reject` handler.
-In the example above, `Greet` only returns a `string` so the Javascript call will never reject - unless invalid data
-is passed to it.
+When you run `wails dev` (or `wails generate module`), a frontend module will be generated containing the following:
+ - Javascript bindings for all bound methods
+ - Typescript declarations for all bound methods
+ - Typescript definitions for all Go structs used as inputs or outputs by the bound methods
-All data types are correctly translated between Go and Javascript. Even structs. If you return a struct from a Go call,
-it will be returned to your frontend as a Javascript map. Note: If you wish to use structs, you **must** define `json` struct
-tags for your fields!
-
-:::info Note
-Anonymous nested structs are not supported at this time.
-:::
-
-It is also possible to send structs back to Go. Any Javascript map passed as an argument that
-is expecting a struct, will be converted to that struct type. To make this process a lot easier, in `dev` mode,
-a TypeScript module is generated, defining all the struct types used in bound methods. Using this module, it's possible
-to construct and send native Javascript objects to the Go code.
-
-More information on Binding can be found in the [Binding Methods](./guides/application-development#binding-methods)
-section of the [Application Development Guide](./guides/application-development).
+This makes it incredibly simple to call Go code from the frontend, using the same strongly typed datastructures.
## The Frontend
### Overview
-The frontend is a collection of files rendered by webkit. It's like a browser and webserver in one.
+The frontend is a collection of files rendered by webkit. It''s like a browser and webserver in one.
There is virtually[^1] no limit to which frameworks or libraries you can use. The main points of interaction between
the frontend and your Go code are:
@@ -247,48 +220,61 @@ the frontend and your Go code are:
### Calling bound Go methods
-All bound Go methods are available at `window.go...`. As stated in
-the previous section, these return a Promise where a successful call returns a value to the
-resolve handler and an error returns a value to the reject handler.
+When you run your application with `wails dev`, it will automatically generate Javascript bindings for your structs in a
+directory called `wailsjs/go` (You can also do this by running `wails generate module`). The generated files mirror the
+package names in your application. In the example above, we bind `app`, which has one public method `Greet`. This will
+lead to the generation of the following files:
-```go title="mycode.js"
-window.go.main.App.Greet("Bill").then((result) => {
- console.log("The greeting is: " + result);
-})
+```bash
+wailsjs
+ └─go
+ └─main
+ ├─App.d.ts
+ └─App.js
+```
+Here we can see that there is a `main` package that contains the Javascript bindings for the bound `App` struct, as well
+as the Typescript declaration file for those methods. To call `Greet` from our frontend, we simply import the method and
+call it like a regular Javascript function:
+
+```javascript
+ // ...
+ import {Greet} from '../wailsjs/go/main/App'
+
+ function doGreeting(name) {
+ Greet(name).then((result) => {
+ // Do something with result
+ })
+ }
+```
+The Typescript declaration file gives you the correct types for the bound methods:
+
+```ts
+export function Greet(arg1:string):Promise;
```
-When running the application in `dev` mode, a javascript module is generated that wraps these
-methods with JSDoc annotations. This really help with development, especially as most
-IDEs will process JSDoc to provide code completion and type hinting. This module is called `go`
-and is generated in the directory specified by the `wailsjsdir` flag. In this module is a file
-called `bindings.js` containing these wrappers. For the above example, the file contains the
-following code:
+The generated methods return a Promise. A successful call will result in the first return value from the Go call to be passed
+to the `resolve` handler. An unsuccessful call is when a Go method that has an error type as it''s second return value,
+passes an error instance back to the caller. This is passed back via the `reject` handler.
+In the example above, `Greet` only returns a `string` so the Javascript call will never reject - unless invalid data
+is passed to it.
-```js title="bindings.js"
-const go = {
- main: {
- App: {
- /**
- * Greet
- * @param {Person} arg1 - Go Type: string
- * @returns {Promise} - Go Type: string
- */
- Greet: (arg1) => {
- return window.go.main.App.Greet(arg1);
- },
- },
- },
-};
-export default go;
-```
+All data types are correctly translated between Go and Javascript. Even structs. If you return a struct from a Go call,
+it will be returned to your frontend as a Javascript class. Note: If you wish to use structs, you **must** define
+`json` struct tags for your fields!
-#### Support for structs
+:::info Note
+Anonymous nested structs are not supported at this time.
+:::
-There is also additional support for Go methods that use structs in their signature. All Go structs
-specified by bound method (either as parameters or return types) will have Typescript versions auto
-generated as part of the Go code wrapper module. Using these, it's possible to share the same data
-model between Go and Javascript. These models align with the JSDoc annotations, empowering IDE code
-completion.
+It is possible to send structs back to Go. Any Javascript map/class passed as an argument that
+is expecting a struct, will be converted to that struct type. To make this process a lot easier, in `dev` mode,
+a TypeScript module is generated, defining all the struct types used in bound methods. Using this module, it''s possible
+to construct and send native Javascript objects to the Go code.
+
+There is also support for Go methods that use structs in their signature. All Go structs
+specified by a bound method (either as parameters or return types) will have Typescript versions auto
+generated as part of the Go code wrapper module. Using these, it''s possible to share the same data
+model between Go and Javascript.
Example: We update our `Greet` method to accept a `Person` instead of a string:
@@ -309,76 +295,77 @@ func (a *App) Greet(p Person) string {
}
```
-Our `bindings.js` file has now been updated to reflect the change:
+The `wailsjs/go/main/App.js` file will still have the following code:
-```js title="bindings.js"
-const go = {
- main: {
- App: {
- /**
- * Greet
- * @param {Person} arg1 - Go Type: main.Person
- * @returns {Promise} - Go Type: string
- */
- Greet: (arg1) => {
- return window.go.main.App.Greet(arg1);
- },
- },
- },
-};
-export default go;
+```js title="App.js"
+export function Greet(arg1) {
+ return window['go']['main']['App']['Greet'](arg1);
+}
```
-Alongside `bindings.js`, there is a file called `models.ts`. This contains our Go structs in TypeScript form:
+But the `wailsjs/go/main/App.d.ts` file will be updated with the following code:
+
+```ts title="App.d.ts"
+import {main} from '../models';
+
+export function Greet(arg1:main.Person):Promise;
+```
+
+As we can see, the "main" namespace is imported from a new "models.ts" file. This file contains all the struct definitions
+used by our bound methods. In this example, this is a `Person` struct. If we look at `models.ts`, we can see how the models
+are defined:
```ts title="models.ts"
-export class Address {
- street: string;
- postcode: string;
+export namespace main {
- static createFrom(source: any = {}) {
- return new Address(source);
- }
+ export class Address {
+ street: string;
+ postcode: string;
- constructor(source: any = {}) {
- if ("string" === typeof source) source = JSON.parse(source);
- this.street = source["street"];
- this.postcode = source["postcode"];
- }
-}
-export class Person {
- name: string;
- age: number;
- address?: Address;
+ static createFrom(source: any = {}) {
+ return new Address(source);
+ }
- static createFrom(source: any = {}) {
- return new Person(source);
- }
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.street = source["street"];
+ this.postcode = source["postcode"];
+ }
+ }
+ export class Person {
+ name: string;
+ age: number;
+ address?: Address;
- constructor(source: any = {}) {
- if ("string" === typeof source) source = JSON.parse(source);
- this.name = source["name"];
- this.age = source["age"];
- this.address = this.convertValues(source["address"], Address);
- }
+ static createFrom(source: any = {}) {
+ return new Person(source);
+ }
- convertValues(a: any, classs: any, asMap: boolean = false): any {
- if (!a) {
- return a;
- }
- if (a.slice) {
- return (a as any[]).map((elem) => this.convertValues(elem, classs));
- } else if ("object" === typeof a) {
- if (asMap) {
- for (const key of Object.keys(a)) {
- a[key] = new classs(a[key]);
- }
- return a;
- }
- return new classs(a);
- }
- return a;
- }
+ constructor(source: any = {}) {
+ if ('string' === typeof source) source = JSON.parse(source);
+ this.name = source["name"];
+ this.age = source["age"];
+ this.address = this.convertValues(source["address"], Address);
+ }
+
+ convertValues(a: any, classs: any, asMap: boolean = false): any {
+ if (!a) {
+ return a;
+ }
+ if (a.slice) {
+ return (a as any[]).map(elem => this.convertValues(elem, classs));
+ } else if ("object" === typeof a) {
+ if (asMap) {
+ for (const key of Object.keys(a)) {
+ a[key] = new classs(a[key]);
+ }
+ return a;
+ }
+ return new classs(a);
+ }
+ return a;
+ }
+ }
}
```
@@ -386,22 +373,23 @@ So long as you have TypeScript as part of your frontend build configuration, you
the following way:
```js title="mycode.js"
-import go from "./wailsjs/go/bindings";
-import { Person } from "./wailsjs/go/models";
+ import {Greet} from '../wailsjs/go/main/App'
+ import {main} from '../wailsjs/go/models'
-let name = "";
-
-function greet(name) {
- let p = new Person();
- p.name = name;
- p.age = 42;
- go.main.App.Greet(p).then((result) => {
- console.log(result);
- });
-}
+ function generate() {
+ let person = new main.Person()
+ person.name = "Peter"
+ person.age = 27
+ Greet(person).then((result) => {
+ console.log(result)
+ })
+ }
```
-The combination of JSDoc and TypeScript generated models makes for a powerful development environment.
+The combination of generated bindings and TypeScript models makes for a powerful development environment.
+
+More information on Binding can be found in the [Binding Methods](guides/application-development.mdx#binding-methods)
+section of the [Application Development Guide](guides/application-development.mdx).
### Calling runtime methods
@@ -412,4 +400,4 @@ tasks such as emit an event or perform logging operations:
window.runtime.EventsEmit("my-event", 1);
```
-More details about the JS runtime can be found in the [Runtime Reference](./reference/runtime/intro).
+More details about the JS runtime can be found in the [Runtime Reference](reference/runtime/intro).
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/introduction.mdx b/website/versioned_docs/version-v2.0.0-beta.37/introduction.mdx
similarity index 91%
rename from website/versioned_docs/version-v2.0.0-beta.34/introduction.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/introduction.mdx
index 7663f46a0..846b21e1d 100644
--- a/website/versioned_docs/version-v2.0.0-beta.34/introduction.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.37/introduction.mdx
@@ -21,6 +21,12 @@ gives it that 'frosty' effect of a native app.
+## Quick Start Templates
+
+Wails comes with a number of pre-configured templates that allow you to get your application up and running quickly.
+There are templates for the following frameworks: Svelte, React, Vue, Preact, Lit and Vanilla. There are both Javascript
+and Typescript versions for each template.
+
## Native Elements
Wails uses a purpose built library for handling native elements such as Window, Menus, Dialogs, etc, so you can build
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/reference/_category_.json b/website/versioned_docs/version-v2.0.0-beta.37/reference/_category_.json
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/reference/_category_.json
rename to website/versioned_docs/version-v2.0.0-beta.37/reference/_category_.json
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/reference/cli.mdx b/website/versioned_docs/version-v2.0.0-beta.37/reference/cli.mdx
similarity index 88%
rename from website/versioned_docs/version-v2.0.0-beta.34/reference/cli.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/reference/cli.mdx
index 30a6466c3..4dcc55931 100644
--- a/website/versioned_docs/version-v2.0.0-beta.34/reference/cli.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.37/reference/cli.mdx
@@ -29,7 +29,7 @@ Example:
This will generate a a project called "test" in the "mytestproject" directory, initialise git,
generate vscode project files and do so silently.
-More information on using IDEs with Wails can be found [here](/docs/guides/ides).
+More information on using IDEs with Wails can be found [here](../guides/ides.mdx).
### Remote Templates
@@ -38,7 +38,7 @@ Remote templates (hosted on GitHub) are supported and can be installed by using
Example:
`wails init -n test -t https://github.com/leaanthony/testtemplate[@v1.0.0]`
-A list of community maintained templates can be found [here](/docs/community/templates)
+A list of community maintained templates can be found [here](../community/templates.mdx)
:::warning Attention
@@ -54,7 +54,7 @@ A list of community maintained templates can be found [here](/docs/community/tem
| Flag | Description | Default |
| :------------------- | :-------------------------------------- | :------------------------- |
-| -platform | Build for the given (comma delimited) [platforms](/docs/reference/cli#platforms) eg. `windows/arm64`. Note, if you do not give the architecture, `runtime.GOARCH` is used. | runtime.GOOS/runtime.GOARCH |
+| -platform | Build for the given (comma delimited) [platforms](../reference/cli.mdx#platforms) eg. `windows/arm64`. Note, if you do not give the architecture, `runtime.GOARCH` is used. | runtime.GOOS/runtime.GOARCH |
| -clean | Cleans the `build/bin` directory | |
| -compiler "compiler"| Use a different go compiler to build, eg go1.15beta1 | go |
| -ldflags "flags" | Additional ldflags to pass to the compiler | |
@@ -69,10 +69,11 @@ A list of community maintained templates can be found [here](/docs/community/tem
| -webview2 | WebView2 installer strategy: download,embed,browser,error | download |
| -u | Updates your project's `go.mod` to use the same version of Wails as the CLI | |
| -debug | Retains debug information in the application | false |
+| -trimpath | Remove all file system paths from the resulting executable. | false |
-For a detailed description of the `webview2` flag, please refer to the [Windows](/docs/guides/windows) Guide.
+For a detailed description of the `webview2` flag, please refer to the [Windows](../guides/windows.mdx) Guide.
-If you prefer to build using standard Go tooling, please consult the [Manual Builds](/docs/guides/manual-builds)
+If you prefer to build using standard Go tooling, please consult the [Manual Builds](../guides/manual-builds.mdx)
guide.
Example:
@@ -169,12 +170,12 @@ Your system is ready for Wails development!
| -noreload | Disable automatic reload when assets change | |
| -v | Verbosity level (0 - silent, 1 - standard, 2 - verbose) | 1 |
| -wailsjsdir | The directory to generate the generated Wails JS modules | Value in `wails.json` |
-| -debounce | The time to wait for reload after an asset change is detected | 100 (milliseconds) |
-| -devserverurl "url" | Use 3rd party dev server url, EG Vite | "http://localhost:34115" |
+| -debounce | The time to wait for reload after an asset change is detected | 100 (milliseconds) |
+| -devserver "host:port" | The address to bind the wails dev server to | "localhost:34115" |
+| -frontenddevserverurl "url" | Use 3rd party dev server url to serve assets, EG Vite | "" |
| -appargs "args" | Arguments passed to the application in shell style | |
| -platform "platform" | Platform/Arch to target | `runtime.GOOS` |
-| -save | Saves the given `assetdir`, `reloaddirs`, `wailsjsdir`, `debounce` and `devserverurl` flags in
- `wails.json` to become the defaults for subsequent invocations. | |
+| -save | Saves the given `assetdir`, `reloaddirs`, `wailsjsdir`, `debounce`, `devserver` and `frontenddevserverurl` flags in `wails.json` to become the defaults for subsequent invocations. | |
Example:
@@ -182,12 +183,12 @@ Example:
This command will do the following:
- - Build the application and run it (more details [here](/docs/guides/manual-builds)
+ - Build the application and run it (more details [here](../guides/manual-builds.mdx)
- Generate the Wails JS modules in `./frontend/src`
- Watch for updates to files in `./frontend/dist` and reload on any change
- Open a browser and connect to the application
-There is more information on using this feature with existing framework scripts [here](/docs/guides/application-development#live-reloading).
+There is more information on using this feature with existing framework scripts [here](../guides/application-development.mdx#live-reloading).
## generate
@@ -201,7 +202,7 @@ it may be used for generating projects.
| -name | The template name (Mandatory) |
| -frontend "path" | Path to frontend project to use in template |
-For more details on creating templates, consult the [Templates guide](/docs/guides/templates).
+For more details on creating templates, consult the [Templates guide](../guides/templates.mdx).
## update
@@ -215,4 +216,4 @@ For more details on creating templates, consult the [Templates guide](/docs/guid
## version
-`wails version` will simply output the current CLI version.
\ No newline at end of file
+`wails version` will simply output the current CLI version.
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/reference/menus.mdx b/website/versioned_docs/version-v2.0.0-beta.37/reference/menus.mdx
similarity index 99%
rename from website/versioned_docs/version-v2.0.0-beta.35/reference/menus.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/reference/menus.mdx
index cfbdbe440..bab623586 100644
--- a/website/versioned_docs/version-v2.0.0-beta.35/reference/menus.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.37/reference/menus.mdx
@@ -254,7 +254,7 @@ using radio groups that may share a callback.
:::info Roles
-Roles are currently supported on Mac only.
+ Roles are currently supported on Mac only.
:::
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/reference/options.mdx b/website/versioned_docs/version-v2.0.0-beta.37/reference/options.mdx
similarity index 98%
rename from website/versioned_docs/version-v2.0.0-beta.35/reference/options.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/reference/options.mdx
index 23de4e51e..eb3177633 100644
--- a/website/versioned_docs/version-v2.0.0-beta.35/reference/options.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.37/reference/options.mdx
@@ -649,16 +649,14 @@ func main() {
The "About" menu item will appear in the app menu:
-
+
When clicked, that will open an about message box:
-
+
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/reference/project-config.mdx b/website/versioned_docs/version-v2.0.0-beta.37/reference/project-config.mdx
similarity index 94%
rename from website/versioned_docs/version-v2.0.0-beta.35/reference/project-config.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/reference/project-config.mdx
index 178504a63..de612d5f7 100644
--- a/website/versioned_docs/version-v2.0.0-beta.35/reference/project-config.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.37/reference/project-config.mdx
@@ -19,7 +19,7 @@ The project config resides in the `wails.json` file in the project directory. Th
"wailsjsdir": "[Relative path to the directory that the auto-generated JS modules will be created]",
"version": "[Project config version]",
"outputfilename": "[The name of the binary]",
- "debounceMS": 100, // The default time the dev server waits to reload when it detects a vhange in assets
+ "debounceMS": 100, // The default time the dev server waits to reload when it detects a change in assets
"devServer": "[Address to bind the wails dev sever to. Default: localhost:34115]",
"appargs": "[Arguments passed to the application in shell style when in dev mode]",
"runNonNativeBuildHooks": false, // Defines if build hooks should be run though they are defined for an OS other than the host OS.
@@ -35,7 +35,7 @@ The project config resides in the `wails.json` file in the project directory. Th
"copyright": "[The copyright of the product. Default: 'Copyright.........']",
"comments": "[A short comment of the app. Default: 'Built using Wails (https://wails.app)']"
},
- "nsisType": "['multiple': One installer per achitecture. 'single': Single universal installer for all architectures being built. Default: 'multiple']"
+ "nsisType": "['multiple': One installer per architecture. 'single': Single universal installer for all architectures being built. Default: 'multiple']"
}
```
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/reference/runtime/_category_.json b/website/versioned_docs/version-v2.0.0-beta.37/reference/runtime/_category_.json
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/reference/runtime/_category_.json
rename to website/versioned_docs/version-v2.0.0-beta.37/reference/runtime/_category_.json
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/reference/runtime/browser.mdx b/website/versioned_docs/version-v2.0.0-beta.37/reference/runtime/browser.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/reference/runtime/browser.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/reference/runtime/browser.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/reference/runtime/dialog.mdx b/website/versioned_docs/version-v2.0.0-beta.37/reference/runtime/dialog.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/reference/runtime/dialog.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/reference/runtime/dialog.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/reference/runtime/events.mdx b/website/versioned_docs/version-v2.0.0-beta.37/reference/runtime/events.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.34/reference/runtime/events.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/reference/runtime/events.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/reference/runtime/intro.mdx b/website/versioned_docs/version-v2.0.0-beta.37/reference/runtime/intro.mdx
similarity index 95%
rename from website/versioned_docs/version-v2.0.0-beta.35/reference/runtime/intro.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/reference/runtime/intro.mdx
index b3616f689..583c84791 100644
--- a/website/versioned_docs/version-v2.0.0-beta.35/reference/runtime/intro.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.37/reference/runtime/intro.mdx
@@ -32,7 +32,7 @@ Quits the application.
### Environment
-Go Signature: `Enviromnent(ctx context.Context) EnvironmentInfo`
+Go Signature: `Environment(ctx context.Context) EnvironmentInfo`
Returns details of the current environment.
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/reference/runtime/log.mdx b/website/versioned_docs/version-v2.0.0-beta.37/reference/runtime/log.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/reference/runtime/log.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/reference/runtime/log.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/reference/runtime/menu.mdx b/website/versioned_docs/version-v2.0.0-beta.37/reference/runtime/menu.mdx
similarity index 87%
rename from website/versioned_docs/version-v2.0.0-beta.34/reference/runtime/menu.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/reference/runtime/menu.mdx
index 6180577ec..7d2d01783 100644
--- a/website/versioned_docs/version-v2.0.0-beta.34/reference/runtime/menu.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.37/reference/runtime/menu.mdx
@@ -15,7 +15,7 @@ These methods are related to the application menu.
### MenuSetApplicationMenu
Go Signature: `MenuSetApplicationMenu(ctx context.Context, menu *menu.Menu)`
-Sets the application menu to the given [menu](../../reference/menus) .
+Sets the application menu to the given [menu](../menus.mdx) .
### MenuUpdateApplicationMenu
Go Signature: `MenuUpdateApplicationMenu(ctx context.Context)`
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/reference/runtime/window.mdx b/website/versioned_docs/version-v2.0.0-beta.37/reference/runtime/window.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/reference/runtime/window.mdx
rename to website/versioned_docs/version-v2.0.0-beta.37/reference/runtime/window.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/appendix/_category_.json b/website/versioned_docs/version-v2.0.0-beta.38/appendix/_category_.json
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/appendix/_category_.json
rename to website/versioned_docs/version-v2.0.0-beta.38/appendix/_category_.json
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/community/_category_.json b/website/versioned_docs/version-v2.0.0-beta.38/community/_category_.json
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/community/_category_.json
rename to website/versioned_docs/version-v2.0.0-beta.38/community/_category_.json
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/community/links.mdx b/website/versioned_docs/version-v2.0.0-beta.38/community/links.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/community/links.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/community/links.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/community/showcase/_category_.json b/website/versioned_docs/version-v2.0.0-beta.38/community/showcase/_category_.json
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/community/showcase/_category_.json
rename to website/versioned_docs/version-v2.0.0-beta.38/community/showcase/_category_.json
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/community/showcase/encrypteasy.mdx b/website/versioned_docs/version-v2.0.0-beta.38/community/showcase/encrypteasy.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/community/showcase/encrypteasy.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/community/showcase/encrypteasy.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/community/showcase/filehound.mdx b/website/versioned_docs/version-v2.0.0-beta.38/community/showcase/filehound.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/community/showcase/filehound.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/community/showcase/filehound.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/community/showcase/mollywallet.mdx b/website/versioned_docs/version-v2.0.0-beta.38/community/showcase/mollywallet.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/community/showcase/mollywallet.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/community/showcase/mollywallet.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.38/community/showcase/october.mdx b/website/versioned_docs/version-v2.0.0-beta.38/community/showcase/october.mdx
new file mode 100644
index 000000000..83bc64672
--- /dev/null
+++ b/website/versioned_docs/version-v2.0.0-beta.38/community/showcase/october.mdx
@@ -0,0 +1,11 @@
+# October
+
+
+
+
+
+[October](https://october.utf9k.net) is a small Wails application that makes it really easy to extract highlights from [Kobo eReaders](https://en.wikipedia.org/wiki/Kobo_eReader) and then forward them to [Readwise](https://readwise.io).
+
+It has a relatively small scope with all platform versions weighing in under 10MB, and that's without enabling [UPX compression](https://upx.github.io/)!
+
+In contrast, the author's previous attempts with Electron quickly bloated to several hundred megabytes.
\ No newline at end of file
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/community/showcase/optimus.mdx b/website/versioned_docs/version-v2.0.0-beta.38/community/showcase/optimus.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/community/showcase/optimus.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/community/showcase/optimus.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/community/showcase/portfall.mdx b/website/versioned_docs/version-v2.0.0-beta.38/community/showcase/portfall.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/community/showcase/portfall.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/community/showcase/portfall.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/community/showcase/riftshare.mdx b/website/versioned_docs/version-v2.0.0-beta.38/community/showcase/riftshare.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/community/showcase/riftshare.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/community/showcase/riftshare.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.38/community/showcase/surge.mdx b/website/versioned_docs/version-v2.0.0-beta.38/community/showcase/surge.mdx
new file mode 100644
index 000000000..e2facf648
--- /dev/null
+++ b/website/versioned_docs/version-v2.0.0-beta.38/community/showcase/surge.mdx
@@ -0,0 +1,8 @@
+# Surge
+
+
+
+
+
+[Surge](https://getsurge.io/) is a p2p filesharing app designed to utilize blockchain technologies to enable 100% anonymous file transfers. Surge is end-to-end encrypted, decentralized and open source.
+
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/community/showcase/wally.mdx b/website/versioned_docs/version-v2.0.0-beta.38/community/showcase/wally.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/community/showcase/wally.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/community/showcase/wally.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/community/showcase/wombat.mdx b/website/versioned_docs/version-v2.0.0-beta.38/community/showcase/wombat.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/community/showcase/wombat.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/community/showcase/wombat.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/community/showcase/ytd.mdx b/website/versioned_docs/version-v2.0.0-beta.38/community/showcase/ytd.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/community/showcase/ytd.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/community/showcase/ytd.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/community/templates.mdx b/website/versioned_docs/version-v2.0.0-beta.38/community/templates.mdx
similarity index 95%
rename from website/versioned_docs/version-v2.0.0-beta.35/community/templates.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/community/templates.mdx
index 076a6b041..6d090bb3d 100644
--- a/website/versioned_docs/version-v2.0.0-beta.35/community/templates.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.38/community/templates.mdx
@@ -35,6 +35,7 @@ If you are unsure about a template, inspect `package.json` and `wails.json` for
- [wails-react-template](https://github.com/AlienRecall/wails-react-template) - A template using reactjs
- [wails-react-template](https://github.com/flin7/wails-react-template) - A minimal template for React that supports live development
+- [wails-template-nextjs](https://github.com/LGiki/wails-template-nextjs) - A template using Next.js and TypeScript
## Svelte
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/gettingstarted/_category_.json b/website/versioned_docs/version-v2.0.0-beta.38/gettingstarted/_category_.json
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/gettingstarted/_category_.json
rename to website/versioned_docs/version-v2.0.0-beta.38/gettingstarted/_category_.json
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/gettingstarted/building.mdx b/website/versioned_docs/version-v2.0.0-beta.38/gettingstarted/building.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/gettingstarted/building.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/gettingstarted/building.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/gettingstarted/development.mdx b/website/versioned_docs/version-v2.0.0-beta.38/gettingstarted/development.mdx
similarity index 64%
rename from website/versioned_docs/version-v2.0.0-beta.34/gettingstarted/development.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/gettingstarted/development.mdx
index 67a9a6443..323e90ba9 100644
--- a/website/versioned_docs/version-v2.0.0-beta.34/gettingstarted/development.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.38/gettingstarted/development.mdx
@@ -7,9 +7,10 @@ sidebar_position: 5
You can run your application in development mode by running `wails dev` from your project directory. This will do the following things:
- Build your application and run it
- - Watch for modifications in your Go files and rebuild/re-run on change
- - Sets up a [webserver](http://localhost:34115) that will serve your application over a browser. This allows you to use your favourite browser extensions. You can even call your Go code from the console.
+ - Bind your Go code to the frontend so it can be called from Javascript
+ - Using the power of [vite](https://vitejs.dev/), will watch for modifications in your Go files and rebuild/re-run on change
+ - Sets up a [webserver](http://localhost:34115) that will serve your application over a browser. This allows you to use your favourite browser extensions. You can even call your Go code from the console
-To get started, run `wails dev` in the project directory. More information on this can be found [here](../reference/cli#dev).
+To get started, run `wails dev` in the project directory. More information on this can be found [here](../reference/cli.mdx#dev).
Coming soon: Tutorial
\ No newline at end of file
diff --git a/website/versioned_docs/version-v2.0.0-beta.38/gettingstarted/firstproject.mdx b/website/versioned_docs/version-v2.0.0-beta.38/gettingstarted/firstproject.mdx
new file mode 100644
index 000000000..b5ee1fa46
--- /dev/null
+++ b/website/versioned_docs/version-v2.0.0-beta.38/gettingstarted/firstproject.mdx
@@ -0,0 +1,127 @@
+---
+sidebar_position: 2
+---
+
+# Creating a Project
+
+## Project Generation
+
+Now that the CLI is installed, you can generate a new project by using the `wails init` command.
+
+Pick your favourite framework:
+
+
+
+
+import Tabs from "@theme/Tabs";
+import TabItem from "@theme/TabItem";
+
+
+
+ Generate a Svelte project using Javascript with:
+
+ wails init -n myproject -t svelte
+
+ If you would rather use Typescript:
+
+ wails init -n myproject -t svelte-ts
+
+
+ Generate a React project using Javascript with:
+
+ wails init -n myproject -t react
+
+ If you would rather use Typescript:
+
+ wails init -n myproject -t react-ts
+
+
+ Generate a Vue project using Javascript with:
+
+ wails init -n myproject -t vue
+
+ If you would rather use Typescript:
+
+ wails init -n myproject -t vue-ts
+
+
+ Generate a Preact project using Javascript with:
+
+ wails init -n myproject -t preact
+
+ If you would rather use Typescript:
+
+ wails init -n myproject -t preact-ts
+
+
+ Generate a Lit project using Javascript with:
+
+ wails init -n myproject -t lit
+
+ If you would rather use Typescript:
+
+ wails init -n myproject -t lit-ts
+
+
+ Generate a Vanilla project using Javascript with:
+
+ wails init -n myproject -t vanilla
+
+ If you would rather use Typescript:
+
+ wails init -n myproject -t vanilla-ts
+
+
+
+
+
+There are also [community templates](../community/templates.mdx) available that offer different capabilities and frameworks.
+
+To see the other options available, you can run `wails init -help`.
+More details can be found in the [CLI Reference](../reference/cli.mdx#init).
+
+## Project Layout
+
+Wails projects have the following layout:
+
+```
+.
+├── build/
+│ ├── appicon.png
+│ ├── darwin/
+│ └── windows/
+├── frontend/
+├── go.mod
+├── go.sum
+├── main.go
+└── wails.json
+```
+
+### Project structure rundown
+
+- `/main.go` - The main application
+- `/frontend/` - Frontend project files
+- `/build/` - Project build directory
+- `/build/appicon.png` - The application icon
+- `/build/darwin/` - Mac specific project files
+- `/build/windows/` - Windows specific project files
+- `/wails.json` - The project configuration
+- `/go.mod` - Go module file
+- `/go.sum` - Go module checksum file
+
+The `frontend` directory has nothing specific to Wails and can be any frontend project of your choosing.
+
+The `build` directory is used during the build process. These files may be updated to customise your builds. If
+files are removed from the build directory, default versions will be regenerated.
+
+The default module name in `go.mod` is "changeme". You should change this to something more appropriate.
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/gettingstarted/installation.mdx b/website/versioned_docs/version-v2.0.0-beta.38/gettingstarted/installation.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/gettingstarted/installation.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/gettingstarted/installation.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/guides/_category_.json b/website/versioned_docs/version-v2.0.0-beta.38/guides/_category_.json
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/guides/_category_.json
rename to website/versioned_docs/version-v2.0.0-beta.38/guides/_category_.json
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/guides/application-development.mdx b/website/versioned_docs/version-v2.0.0-beta.38/guides/application-development.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/guides/application-development.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/guides/application-development.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/guides/bleeding-edge.mdx b/website/versioned_docs/version-v2.0.0-beta.38/guides/bleeding-edge.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/guides/bleeding-edge.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/guides/bleeding-edge.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/guides/developing-wails.mdx b/website/versioned_docs/version-v2.0.0-beta.38/guides/developing-wails.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/guides/developing-wails.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/guides/developing-wails.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/guides/frameless.mdx b/website/versioned_docs/version-v2.0.0-beta.38/guides/frameless.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/guides/frameless.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/guides/frameless.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/guides/frontend.mdx b/website/versioned_docs/version-v2.0.0-beta.38/guides/frontend.mdx
similarity index 97%
rename from website/versioned_docs/version-v2.0.0-beta.35/guides/frontend.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/guides/frontend.mdx
index 2ace49c4e..7b94345ad 100644
--- a/website/versioned_docs/version-v2.0.0-beta.35/guides/frontend.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.38/guides/frontend.mdx
@@ -2,7 +2,7 @@
## Script Injection
-When Wails serves your `index.html`, by default, it will inject 2 script entries into the `` tag to load `/wails/bindings.js`
+When Wails serves your `index.html`, by default, it will inject 2 script entries into the `` tag to load `/wails/ipc.js`
and `/wails/runtime.js`. These files install the bindings and runtime respectively.
The code below shows where these are injected by default:
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/guides/ides.mdx b/website/versioned_docs/version-v2.0.0-beta.38/guides/ides.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/guides/ides.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/guides/ides.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/guides/linux-distro-support.mdx b/website/versioned_docs/version-v2.0.0-beta.38/guides/linux-distro-support.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/guides/linux-distro-support.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/guides/linux-distro-support.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/guides/manual-builds.mdx b/website/versioned_docs/version-v2.0.0-beta.38/guides/manual-builds.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/guides/manual-builds.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/guides/manual-builds.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/guides/migrating.mdx b/website/versioned_docs/version-v2.0.0-beta.38/guides/migrating.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/guides/migrating.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/guides/migrating.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/guides/overscroll.mdx b/website/versioned_docs/version-v2.0.0-beta.38/guides/overscroll.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/guides/overscroll.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/guides/overscroll.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/guides/routing.mdx b/website/versioned_docs/version-v2.0.0-beta.38/guides/routing.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/guides/routing.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/guides/routing.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/guides/signing.mdx b/website/versioned_docs/version-v2.0.0-beta.38/guides/signing.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/guides/signing.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/guides/signing.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/guides/templates.mdx b/website/versioned_docs/version-v2.0.0-beta.38/guides/templates.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/guides/templates.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/guides/templates.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/guides/troubleshooting.mdx b/website/versioned_docs/version-v2.0.0-beta.38/guides/troubleshooting.mdx
similarity index 77%
rename from website/versioned_docs/version-v2.0.0-beta.35/guides/troubleshooting.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/guides/troubleshooting.mdx
index 83b6b9972..4aa119ee9 100644
--- a/website/versioned_docs/version-v2.0.0-beta.35/guides/troubleshooting.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.38/guides/troubleshooting.mdx
@@ -21,7 +21,7 @@ If your built application looks like this in finder:
-it's likely that your application's `info.plist` is invalid. Update the file in `build/.app/Contents/info.plist`
+it''s likely that your application''s `info.plist` is invalid. Update the file in `build/.app/Contents/info.plist`
and check if the data is valid, EG check the binary name is correct. To persist the changes, copy the file back to
the `build/darwin` directory.
@@ -55,7 +55,7 @@ window.go.main.App.TestFunc(msg, args).then((result) => { //without the 3 dots
```
Credit: https://github.com/wailsapp/wails/issues/1186
-## I'm having getting proxy errors when trying to install Wails
+## I''m having getting proxy errors when trying to install Wails
If you are getting errors like this:
```
@@ -67,4 +67,10 @@ The solution is to set up the proxy manually, eg:
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct
```
-Source: https://github.com/wailsapp/wails/issues/1233
\ No newline at end of file
+Source: https://github.com/wailsapp/wails/issues/1233
+
+## The generated Typescript doesn''t have the correct types
+
+Sometimes the generated Typescript doesn''t have the correct types. To mitigate this,
+it is possible to specify what types should be generated using the `ts_type` struct tag. For
+more details, please read [this](https://github.com/tkrajina/typescriptify-golang-structs#custom-types).
\ No newline at end of file
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/guides/windows-installer.mdx b/website/versioned_docs/version-v2.0.0-beta.38/guides/windows-installer.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/guides/windows-installer.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/guides/windows-installer.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/guides/windows.mdx b/website/versioned_docs/version-v2.0.0-beta.38/guides/windows.mdx
similarity index 70%
rename from website/versioned_docs/version-v2.0.0-beta.35/guides/windows.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/guides/windows.mdx
index 53e456825..e3c2ee027 100644
--- a/website/versioned_docs/version-v2.0.0-beta.35/guides/windows.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.38/guides/windows.mdx
@@ -34,3 +34,20 @@ up to the user.
### Error
If no suitable runtime is found, an error is given to the user and no further action taken.
+
+## Fixed version runtime
+
+Another way of dealing with webview2 dependency is shipping it yourself.
+You can download [fixed version runtime](https://developer.microsoft.com/ru-ru/microsoft-edge/webview2/#download-section) and bundle or download it with your application.
+
+Also, you should specify path to fixed version of webview2 runtime in the `windows.Options` structure when launching wails.
+
+```go
+ wails.Run(&options.App{
+ Windows: &windows.Options{
+ WebviewBrowserPath: "",
+ },
+ })
+```
+
+Note: When `WebviewBrowserPath` is specified, `error` strategy will be forced in case of minimal required version mismatch or invalid path to a runtime.
\ No newline at end of file
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/howdoesitwork.mdx b/website/versioned_docs/version-v2.0.0-beta.38/howdoesitwork.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/howdoesitwork.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/howdoesitwork.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/introduction.mdx b/website/versioned_docs/version-v2.0.0-beta.38/introduction.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/introduction.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/introduction.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/reference/_category_.json b/website/versioned_docs/version-v2.0.0-beta.38/reference/_category_.json
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/reference/_category_.json
rename to website/versioned_docs/version-v2.0.0-beta.38/reference/_category_.json
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/reference/cli.mdx b/website/versioned_docs/version-v2.0.0-beta.38/reference/cli.mdx
similarity index 96%
rename from website/versioned_docs/version-v2.0.0-beta.35/reference/cli.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/reference/cli.mdx
index e6abde76a..f83c210da 100644
--- a/website/versioned_docs/version-v2.0.0-beta.35/reference/cli.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.38/reference/cli.mdx
@@ -70,6 +70,7 @@ If you are unsure about a template, inspect `package.json` and `wails.json` for
| -u | Updates your project's `go.mod` to use the same version of Wails as the CLI | |
| -debug | Retains debug information in the application | false |
| -trimpath | Remove all file system paths from the resulting executable. | false |
+| -race | Build with Go's race detector | false |
For a detailed description of the `webview2` flag, please refer to the [Windows](../guides/windows.mdx) Guide.
@@ -168,6 +169,7 @@ Your system is ready for Wails development!
| -tags "extra tags" | Build tags to pass to compiler (quoted and space separated) | |
| -loglevel "loglevel"| Loglevel to use - Trace, Debug, Info, Warning, Error | Debug |
| -noreload | Disable automatic reload when assets change | |
+| -nogen | Disable generate module | |
| -v | Verbosity level (0 - silent, 1 - standard, 2 - verbose) | 1 |
| -wailsjsdir | The directory to generate the generated Wails JS modules | Value in `wails.json` |
| -debounce | The time to wait for reload after an asset change is detected | 100 (milliseconds) |
@@ -175,8 +177,8 @@ Your system is ready for Wails development!
| -frontenddevserverurl "url" | Use 3rd party dev server url to serve assets, EG Vite | "" |
| -appargs "args" | Arguments passed to the application in shell style | |
| -platform "platform" | Platform/Arch to target | `runtime.GOOS` |
-| -save | Saves the given `assetdir`, `reloaddirs`, `wailsjsdir`, `debounce`, `devserver` and `frontenddevserverurl` flags in
-`wails.json` to become the defaults for subsequent invocations. | |
+| -save | Saves the given `assetdir`, `reloaddirs`, `wailsjsdir`, `debounce`, `devserver` and `frontenddevserverurl` flags in `wails.json` to become the defaults for subsequent invocations. | |
+| -race | Build with Go's race detector | false |
Example:
@@ -217,4 +219,4 @@ For more details on creating templates, consult the [Templates guide](../guides/
## version
-`wails version` will simply output the current CLI version.
\ No newline at end of file
+`wails version` will simply output the current CLI version.
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/reference/menus.mdx b/website/versioned_docs/version-v2.0.0-beta.38/reference/menus.mdx
similarity index 81%
rename from website/versioned_docs/version-v2.0.0-beta.34/reference/menus.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/reference/menus.mdx
index ea5e47367..94f08b2e2 100644
--- a/website/versioned_docs/version-v2.0.0-beta.34/reference/menus.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.38/reference/menus.mdx
@@ -5,27 +5,38 @@ sidebar_position: 4
# Menus
It is possible to add an application menu to Wails projects. This is achieved by defining a [Menu](#menu) struct and
-setting the [`Menu`](../reference/options#menu) option, or by calling the runtime method [MenuSetApplicationMenu](../reference/runtime/menu#menusetapplicationmenu).
+setting it in the [`Menu`](../reference/options.mdx#menu) application config, or by calling the runtime method
+[MenuSetApplicationMenu](../reference/runtime/menu.mdx#menusetapplicationmenu).
-It is also possible to dynamically update the menu, by updating the menu struct and calling
-[MenuUpdateApplicationMenu](../reference/runtime/menu#menuupdateapplicationmenu).
-
-Example:
+An example of how to create a menu:
```go
- myMenu := menu.NewMenuFromItems(
- menu.SubMenu("File", menu.NewMenuFromItems(
- menu.Text("&Open", keys.CmdOrCtrl("o"), openFile),
- menu.Separator(),
- menu.Text("Quit", keys.CmdOrCtrl("q"), func(_ *menu.CallbackData) {
- runtime.Quit()
- }),
- )),
+ AppMenu := menu.NewMenu()
+ FileMenu := AppMenu.AddSubmenu("File")
+ FileMenu.AddText("&Open", keys.CmdOrCtrl("o"), openFile)
+ FileMenu.AddSeparator()
+ FileMenu.AddText("Quit", keys.CmdOrCtrl("q"), func(_ *menu.CallbackData) {
+ runtime.Quit()
+ })
+
+ if runtime.GOOS == "darwin" {
+ AppMenu.Append(menu.EditMenu()) // on macos platform, we should append EditMenu to enable Cmd+C,Cmd+V,Cmd+Z... shortcut
+ }
+
+ err := wails.Run(&options.App{
+ Title: "Menus Demo",
+ Width: 800,
+ Height: 600,
+ Menu: AppMenu,
+ Bind: []interface{}{
+ app,
+ },
)
+ // ...
+````
- runtime.MenuSetApplicationMenu(myMenu)
-
-```
+It is also possible to dynamically update the menu, by updating the menu struct and calling
+[MenuUpdateApplicationMenu](../reference/runtime/menu.mdx#menuupdateapplicationmenu).
The example above uses helper methods, however it's possible to build the menu structs manually.
@@ -211,8 +222,18 @@ func Text(label string, accelerator *keys.Accelerator, click Callback) *MenuItem
func Separator() *MenuItem
func Radio(label string, selected bool, accelerator *keys.Accelerator, click Callback) *MenuItem
func Checkbox(label string, checked bool, accelerator *keys.Accelerator, click Callback) *MenuItem
-func SubMenu(label string, menu *Menu) *MenuItem
+func SubMenu(label string, menu *Menu) *Menu
```
+You can also create menu items directly on a menu by using the "Add" helpers:
+
+```go title="Package: github.com/wailsapp/wails/v2/pkg/menu"
+func (m *Menu) AddText(label string, accelerator *keys.Accelerator, click Callback) *MenuItem
+func (m *Menu) AddSeparator() *MenuItem
+func (m *Menu) AddRadio(label string, selected bool, accelerator *keys.Accelerator, click Callback) *MenuItem
+func (m *Menu) AddCheckbox(label string, checked bool, accelerator *keys.Accelerator, click Callback) *MenuItem
+func (m *Menu) AddSubMenu(label string, menu *Menu) *MenuI
+```
+
A note on radio groups: A radio group is defined as a number of radio menu items that are next to each other in the menu.
This means that you do not need to group items together as it is automatic. However, that also means you cannot have 2
@@ -237,7 +258,7 @@ using radio groups that may share a callback.
:::info Roles
- Roles are currently supported on Mac only.
+Roles are currently supported on Mac only.
:::
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/reference/options.mdx b/website/versioned_docs/version-v2.0.0-beta.38/reference/options.mdx
similarity index 66%
rename from website/versioned_docs/version-v2.0.0-beta.34/reference/options.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/reference/options.mdx
index 4b55ead0e..b946f6d52 100644
--- a/website/versioned_docs/version-v2.0.0-beta.34/reference/options.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.38/reference/options.mdx
@@ -27,9 +27,10 @@ func main() {
MaxHeight: 1024,
StartHidden: false,
HideWindowOnClose: false,
- RGBA: &options.RGBA{R: 0, G: 0, B: 0, A: 255},
+ BackgroundColour: &options.RGBA{R: 0, G: 0, B: 0, A: 255},
AlwaysOnTop: false,
Assets: assets,
+ AssetsHandler: assetsHandler,
Menu: app.applicationMenu(),
Logger: nil,
LogLevel: logger.DEBUG,
@@ -47,6 +48,7 @@ func main() {
DisableWindowIcon: false,
DisableFramelessWindowDecorations: false,
WebviewUserDataPath: "",
+ WebviewBrowserPath: "",
Theme: windows.SystemDefault,
CustomTheme: &windows.ThemeSettings{
DarkModeTitleBar: windows.RGB(20, 20, 20),
@@ -56,6 +58,8 @@ func main() {
LightModeTitleText: windows.RGB(20, 20, 20),
LightModeBorder: windows.RGB(200, 200, 200),
},
+ // User messages that can be customised
+ Messages *windows.Messages
},
Mac: &mac.Options{
TitleBar: &mac.TitleBar{
@@ -75,6 +79,9 @@ func main() {
Icon: icon,
},
},
+ Linux: &linux.Options{
+ Icon: icon,
+ },
})
if err != nil {
log.Fatal(err)
@@ -134,7 +141,7 @@ Name: Frameless
Type: bool
When set to `true`, the window will have no borders or title bar.
-Also see [Frameless Windows](../guides/frameless).
+Also see [Frameless Windows](../guides/frameless.mdx).
### MinWidth
@@ -178,7 +185,7 @@ Name: StartHidden
Type: bool
-When set to `true`, the application will be hidden until [WindowShow](../reference/runtime/window#WindowShow)
+When set to `true`, the application will be hidden until [WindowShow](../reference/runtime/window.mdx#windowshow)
is called.
### HideWindowOnClose
@@ -190,14 +197,14 @@ Type: bool
By default, closing the window will close the application. Setting this to `true` means closing the window will
hide the window instead.
-### RGBA
+### BackgroundColour
-Name: RGBA
+Name: BackgroundColour
Type: int (0xRRGGBBAA)
Example: 0xFF000088 - Red at 50% transparency
-This value is the RGBA value to set the window by default.
+This value is the default background colour of the window.
Default: 0xFFFFFFFF.
### AlwaysOnTop
@@ -212,17 +219,49 @@ Indicates that the window should stay above other windows when losing focus.
Name: Assets
-Type: \*embed.FS
+Type: embed.FS
The frontend assets to be used by the application. Requires an `index.html` file.
+### AssetsHandler
+
+
+Name: AssetsHandler
+
+Type: http.Handler
+
+
+The assets handler is a generic `http.Handler` which will be called for any non GET request on the assets server
+and for GET requests which can not be served from the `assets` because the file is not found.
+
+| Value | Win | Mac | Lin |
+| ----------------------------- | --- | --- | --- |
+| GET | ✅ | ✅ | ✅ |
+| POST | ✅ | ✅ | ❌ |
+| PUT | ✅ | ✅ | ❌ |
+| PATCH | ✅ | ✅ | ❌ |
+| DELETE | ✅ | ✅ | ❌ |
+| Request Headers | ✅ | ✅ | ❌ |
+| Request Body | ✅ | ✅ | ❌ |
+| Request Body Streaming | ❌ | ❌ | ❌ |
+| Response StatusCodes | ✅ | ✅ | ❌ |
+| Response Headers | ✅ | ✅ | ❌ |
+| Response Body | ✅ | ✅ | ✅ |
+| Response Body Streaming | ❌ | ❌ | ✅ |
+
+NOTE: Linux is currently very limited due to targeting a WebKit2GTK Version < 2.36.0. In the future some features will be
+supported by the introduction of WebKit2GTK 2.36.0+ support.
+
+NOTE: When used in combination with a Frontend DevServer there might be limitations, eg. Vite serves the index.html
+on every path, that does not contain a file extension.
+
### Menu
Name: Menu
Type: \*menu.Menu
-The menu to be used by the application. More details about Menus in the [Menu Reference](../reference/runtime/menu).
+The menu to be used by the application. More details about Menus in the [Menu Reference](../reference/runtime/menu.mdx).
NOTE: On Mac, if no menu is specified, a default menu will be created.
@@ -234,7 +273,7 @@ Type: logger.Logger
Default: Logger to Stdout
-The logger to be used by the application. More details about logging in the [Log Reference](../reference/runtime/log).
+The logger to be used by the application. More details about logging in the [Log Reference](../reference/runtime/log.mdx).
### LogLevel
@@ -244,7 +283,7 @@ Type: logger.LogLevel
Default: `Info` in dev mode, `Error` in production mode
-The default log level. More details about logging in the [Log Reference](../reference/runtime/log).
+The default log level. More details about logging in the [Log Reference](../reference/runtime/log.mdx).
### OnStartup
@@ -311,7 +350,7 @@ Defines how the window should present itself at startup.
| --------------- | --- | --- | --- |
| Fullscreen | ✅ | ✅ | ✅ |
| Maximised | ✅ | ✅ | ✅ |
-| Minimised | ✅ | | ✅ |
+| Minimised | ✅ | ❌ | ✅ |
### Bind
@@ -337,6 +376,14 @@ Type: \*mac.Options
This defines [Mac specific options](#mac-specific-options).
+### Linux
+
+Name: Linux
+
+Type: \*linux.Options
+
+This defines [Linux specific options](#linux-specific-options).
+
## Windows Specific Options
### WebviewIsTransparent
@@ -346,7 +393,7 @@ Name: WebviewIsTransparent
Type: bool
Setting this to `true` will make the webview background transparent when an alpha value of `0` is used.
-This means that if you use `rgba(0,0,0,0)`, the host window will show through.
+This means that if you use `rgba(0,0,0,0)` for `background-color` in your CSS, the host window will show through.
Often combined with [WindowIsTranslucent](#WindowIsTranslucent) to make frosty-looking applications.
### WindowIsTranslucent
@@ -384,6 +431,127 @@ Type: string
This defines the path where the WebView2 stores the user data. If empty `%APPDATA%\[BinaryName.exe]` will be used.
+### WebviewBrowserPath
+
+Name: WebviewBrowserPath
+
+Type: string
+
+This defines the path to a directory with WebView2 executable files and libraries. If empty, webview2 installed in the system will be used.
+
+Important information about distribution of fixed version runtime:
+- [How to get and extract runtime](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#details-about-the-fixed-version-runtime-distribution-mode)
+- [Known issues for fixed version](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#known-issues-for-fixed-version)
+- [The path of fixed version of the WebView2 Runtime should not contain \Edge\Application\.](https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.1245.22#createcorewebview2environmentwithoptions)
+
+### Theme
+
+Name: Theme
+
+Type: `windows.Theme`
+
+Minimum Windows Version: Windows 10 2004/20H1
+
+This defines the theme that the application should use:
+
+| Value | Description |
+| --------------- | ----------- |
+| SystemDefault | *Default*. The theme will be based on the system default. If the user changes their theme, the application will update to use the new setting |
+| Dark | The application will use a dark theme exclusively |
+| Light | The application will use a light theme exclusively |
+
+
+### CustomTheme
+
+Name: CustomTheme
+
+Type: `windows.CustomTheme`
+
+Minimum Windows Version: Windows 10/11 2009/21H2 Build 22000
+
+Allows you to specify custom colours for TitleBar, TitleText and Border for both light and dark mode, as well as
+when the window is active or inactive.
+
+#### CustomTheme
+
+The CustomTheme struct uses `int32` to specify the colour values. These are in the standard(!) Windows format of:
+`0x00BBGGAA`. A helper function is provided to do RGB conversions into this format: `windows.RGB(r,g,b uint8)`.
+
+NOTE: Any value not provided will default to black.
+
+```go
+type ThemeSettings struct {
+ DarkModeTitleBar int32
+ DarkModeTitleBarInactive int32
+ DarkModeTitleText int32
+ DarkModeTitleTextInactive int32
+ DarkModeBorder int32
+ DarkModeBorderInactive int32
+ LightModeTitleBar int32
+ LightModeTitleBarInactive int32
+ LightModeTitleText int32
+ LightModeTitleTextInactive int32
+ LightModeBorder int32
+ LightModeBorderInactive int32
+}
+```
+
+Example:
+```go
+ CustomTheme: &windows.ThemeSettings{
+ // Theme to use when window is active
+ DarkModeTitleBar: windows.RGB(255, 0, 0), // Red
+ DarkModeTitleText: windows.RGB(0, 255, 0), // Green
+ DarkModeBorder: windows.RGB(0, 0, 255), // Blue
+ LightModeTitleBar: windows.RGB(200, 200, 200),
+ LightModeTitleText: windows.RGB(20, 20, 20),
+ LightModeBorder: windows.RGB(200, 200, 200),
+ // Theme to use when window is inactive
+ DarkModeTitleBarInactive: windows.RGB(128, 0, 0),
+ DarkModeTitleTextInactive: windows.RGB(0, 128, 0),
+ DarkModeBorderInactive: windows.RGB(0, 0, 128),
+ LightModeTitleBarInactive: windows.RGB(100, 100, 100),
+ LightModeTitleTextInactive: windows.RGB(10, 10, 10),
+ LightModeBorderInactive: windows.RGB(100, 100, 100),
+ },
+```
+
+### Messages
+
+Name: Messages
+
+Type: `*windows.Messages`
+
+A struct of strings used by the webview2 installer if a valid webview2 runtime is not found.
+Customise this for any language you choose to support.
+
+### ResizeDebounceMS
+
+Name: ResizeDebounceMS
+
+Type: uint16
+
+ResizeDebounceMS is the amount of time to debounce redraws of webview2 when resizing the window.
+The default value (0) will perform redraws as fast as it can.
+
+### OnSuspend
+
+Name: OnSuspend
+
+Type: func()
+
+If set, this function will be called when windows initiates a switch to low power mode (suspend/hibernate)
+
+### OnResume
+
+Name: OnResume
+
+Type: func()
+
+If set, this function will be called when windows resumes from low power mode (suspend/hibernate)
+
+
+
## Mac Specific Options
### TitleBar
@@ -409,7 +577,7 @@ Name: WebviewIsTransparent
Type: bool
Setting this to `true` will make the webview background transparent when an alpha value of `0` is used.
-This means that if you use `rgba(0,0,0,0)`, the host window will show through.
+This means that if you use `rgba(0,0,0,0)` for `background-color` in your CSS, the host window will show through.
Often combined with [WindowIsTranslucent](#WindowIsTranslucent) to make frosty-looking applications.
### WindowIsTranslucent
@@ -446,7 +614,7 @@ type TitleBar struct {
| Name | Description |
| ---- | ----------- |
-| TitlebarAppearsTransparent | Makes the titlebar transparent. [Apple Docs](https://developer.apple.com/documentation/appkit/nswindow/1419167-titlebarappearstransparent?language=objc) |
+| TitlebarAppearsTransparent | Makes the titlebar transparent. This has the effect of hiding the titlebar and the content fill the window. [Apple Docs](https://developer.apple.com/documentation/appkit/nswindow/1419167-titlebarappearstransparent?language=objc) |
| HideTitle | Hides the title of the window. [Apple Docs](https://developer.apple.com/documentation/appkit/nswindowtitlevisibility?language=objc) |
| HideTitleBar | Removes [NSWindowStyleMaskTitled](https://developer.apple.com/documentation/appkit/nswindowstylemask/nswindowstylemasktitled/) from the style mask |
| FullSizeContent | Makes the webview fill the entire window. [Apple Docs](https://developer.apple.com/documentation/appkit/nswindowstylemask/nswindowstylemaskfullsizecontentview)|
@@ -522,14 +690,16 @@ func main() {
The "About" menu item will appear in the app menu:
-
+
When clicked, that will open an about message box:
-
+
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/reference/project-config.mdx b/website/versioned_docs/version-v2.0.0-beta.38/reference/project-config.mdx
similarity index 80%
rename from website/versioned_docs/version-v2.0.0-beta.34/reference/project-config.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/reference/project-config.mdx
index 88dab6047..de612d5f7 100644
--- a/website/versioned_docs/version-v2.0.0-beta.34/reference/project-config.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.38/reference/project-config.mdx
@@ -14,12 +14,13 @@ The project config resides in the `wails.json` file in the project directory. Th
"frontend:install": "[The command to install node dependencies, run in the frontend directory - often `npm install`]",
"frontend:build": "[The command to build the assets, run in the frontend directory - often `npm run build`]",
"frontend:dev": "[This command is the dev equivalent of frontend:build. If not specified falls back to frontend:build]",
- "frontend:dev:watcher": "[This command is run in a separate process on `wails dev`. Useful for 3rd party watchers]",
+ "frontend:dev:watcher": "[This command is run in a separate process on `wails dev`. Useful for 3rd party watchers or starting 3d party dev servers]",
+ "frontend:dev:serverUrl": "[URL to a 3rd party dev server to be used to serve assets, EG Vite",
"wailsjsdir": "[Relative path to the directory that the auto-generated JS modules will be created]",
"version": "[Project config version]",
"outputfilename": "[The name of the binary]",
- "debounceMS": 100, // The default time the dev server waits to reload when it detects a vhange in assets
- "devserverurl": "[URL to the dev server serving local assets. Default: http://localhost:34115]",
+ "debounceMS": 100, // The default time the dev server waits to reload when it detects a change in assets
+ "devServer": "[Address to bind the wails dev sever to. Default: localhost:34115]",
"appargs": "[Arguments passed to the application in shell style when in dev mode]",
"runNonNativeBuildHooks": false, // Defines if build hooks should be run though they are defined for an OS other than the host OS.
"postBuildHooks": {
@@ -34,11 +35,11 @@ The project config resides in the `wails.json` file in the project directory. Th
"copyright": "[The copyright of the product. Default: 'Copyright.........']",
"comments": "[A short comment of the app. Default: 'Built using Wails (https://wails.app)']"
},
- "nsisType": "['multiple': One installer per achitecture. 'single': Single universal installer for all architectures being built. Default: 'multiple']"
+ "nsisType": "['multiple': One installer per architecture. 'single': Single universal installer for all architectures being built. Default: 'multiple']"
}
```
This file is read by the Wails CLI when running `wails build` or `wails dev`.
-The `assetdir`, `reloaddirs`, `wailsjsdir`, `debounceMS` and `devserverurl` flags in `wails build/dev` will update the project config
+The `assetdir`, `reloaddirs`, `wailsjsdir`, `debounceMS`, `devserver` and `frontenddevserverurl` flags in `wails build/dev` will update the project config
and thus become defaults for subsequent runs.
\ No newline at end of file
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/reference/runtime/_category_.json b/website/versioned_docs/version-v2.0.0-beta.38/reference/runtime/_category_.json
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/reference/runtime/_category_.json
rename to website/versioned_docs/version-v2.0.0-beta.38/reference/runtime/_category_.json
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/reference/runtime/browser.mdx b/website/versioned_docs/version-v2.0.0-beta.38/reference/runtime/browser.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/reference/runtime/browser.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/reference/runtime/browser.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/reference/runtime/dialog.mdx b/website/versioned_docs/version-v2.0.0-beta.38/reference/runtime/dialog.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/reference/runtime/dialog.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/reference/runtime/dialog.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/reference/runtime/events.mdx b/website/versioned_docs/version-v2.0.0-beta.38/reference/runtime/events.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/reference/runtime/events.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/reference/runtime/events.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/reference/runtime/intro.mdx b/website/versioned_docs/version-v2.0.0-beta.38/reference/runtime/intro.mdx
similarity index 77%
rename from website/versioned_docs/version-v2.0.0-beta.34/reference/runtime/intro.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/reference/runtime/intro.mdx
index 0e07084b8..583c84791 100644
--- a/website/versioned_docs/version-v2.0.0-beta.34/reference/runtime/intro.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.38/reference/runtime/intro.mdx
@@ -8,15 +8,15 @@ The runtime is a library that provides utility methods for your application. The
and the aim is to try and keep them at parity where possible.
The Go Runtime is available through importing `github.com/wailsapp/wails/v2/pkg/runtime`. All methods in this package
-take a context as the first parameter. This context should be obtained from the [OnStartup](../../reference/options#onstartup)
-or [OnDomReady](../../reference/options#ondomready) hooks.
+take a context as the first parameter. This context should be obtained from the [OnStartup](../options.mdx#onstartup)
+or [OnDomReady](../options.mdx#ondomready) hooks.
:::info Note
Whilst the context will be provided to the
-[OnStartup](../../reference/options#onstartup) method, there's no guarantee the runtime will work in this method as
+[OnStartup](../options.mdx#onstartup) method, there's no guarantee the runtime will work in this method as
the window is initialising in a different thread. If
-you wish to call runtime methods at startup, use [OnDomReady](../../reference/options#ondomready).
+you wish to call runtime methods at startup, use [OnDomReady](../options.mdx#ondomready).
:::
@@ -32,7 +32,7 @@ Quits the application.
### Environment
-Go Signature: `Enviromnent(ctx context.Context) EnvironmentInfo`
+Go Signature: `Environment(ctx context.Context) EnvironmentInfo`
Returns details of the current environment.
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/reference/runtime/log.mdx b/website/versioned_docs/version-v2.0.0-beta.38/reference/runtime/log.mdx
similarity index 69%
rename from website/versioned_docs/version-v2.0.0-beta.34/reference/runtime/log.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/reference/runtime/log.mdx
index 50576587c..713838008 100644
--- a/website/versioned_docs/version-v2.0.0-beta.34/reference/runtime/log.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.38/reference/runtime/log.mdx
@@ -27,6 +27,12 @@ JS Signature: `LogPrint(message: string)`
Logs the given message as a raw message.
+### LogPrintf
+
+Go Signature: `LogPrintf(ctx context.Context, format string, args ...interface{})`
+
+Logs the given message as a raw message.
+
### LogTrace
Go Signature: `LogTrace(ctx context.Context, message string)`
@@ -35,6 +41,12 @@ JS Signature: `LogTrace(message: string)`
Logs the given message at the `Trace` log level.
+### LogTracef
+
+Go Signature: `LogTracef(ctx context.Context, format string, args ...interface{})`
+
+Logs the given message at the `Trace` log level.
+
### LogDebug
Go Signature: `LogDebug(ctx context.Context, message string)`
@@ -43,6 +55,11 @@ JS Signature: `LogDebug(message: string)`
Logs the given message at the `Debug` log level.
+### LogDebugf
+
+Go Signature: `LogDebugf(ctx context.Context, format string, args ...interface{})`
+
+Logs the given message at the `Debug` log level.
### LogInfo
@@ -52,6 +69,11 @@ JS Signature: `LogInfo(message: string)`
Logs the given message at the `Info` log level.
+### LogInfof
+
+Go Signature: `LogInfof(ctx context.Context, format string, args ...interface{})`
+
+Logs the given message at the `Info` log level.
### LogWarning
@@ -61,6 +83,11 @@ JS Signature: `LogWarning(message: string)`
Logs the given message at the `Warning` log level.
+### LogWarningf
+
+Go Signature: `LogWarningf(ctx context.Context, format string, args ...interface{})`
+
+Logs the given message at the `Warning` log level.
### LogError
@@ -70,14 +97,26 @@ JS Signature: `LogError(message: string)`
Logs the given message at the `Error` log level.
+### LogErrorf
+
+Go Signature: `LogErrorf(ctx context.Context, format string, args ...interface{})`
+
+Logs the given message at the `Error` log level.
### LogFatal
+
Go Signature: `LogFatal(ctx context.Context, message string)`
JS Signature: `LogFatal(message: string)`
Logs the given message at the `Fatal` log level.
+### LogFatalf
+
+Go Signature: `LogFatalf(ctx context.Context, format string, args ...interface{})`
+
+Logs the given message at the `Fatal` log level.
+
### LogSetLogLevel
Go Signature: `LogSetLogLevel(ctx context.Context, level logger.LogLevel)`
@@ -96,7 +135,7 @@ Sets the log level. In Javascript, the number relates to the following log level
## Using a Custom Logger
-A custom logger may be used by providing it using the [Logger](../../reference/options#logger)
+A custom logger may be used by providing it using the [Logger](../options.mdx#logger)
application option. The only requirement is that the logger implements the `logger.Logger` interface
defined in `github.com/wailsapp/wails/v2/pkg/logger`:
diff --git a/website/versioned_docs/version-v2.0.0-beta.35/reference/runtime/menu.mdx b/website/versioned_docs/version-v2.0.0-beta.38/reference/runtime/menu.mdx
similarity index 100%
rename from website/versioned_docs/version-v2.0.0-beta.35/reference/runtime/menu.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/reference/runtime/menu.mdx
diff --git a/website/versioned_docs/version-v2.0.0-beta.34/reference/runtime/window.mdx b/website/versioned_docs/version-v2.0.0-beta.38/reference/runtime/window.mdx
similarity index 81%
rename from website/versioned_docs/version-v2.0.0-beta.34/reference/runtime/window.mdx
rename to website/versioned_docs/version-v2.0.0-beta.38/reference/runtime/window.mdx
index cef929ad6..c3a493d2e 100644
--- a/website/versioned_docs/version-v2.0.0-beta.34/reference/runtime/window.mdx
+++ b/website/versioned_docs/version-v2.0.0-beta.38/reference/runtime/window.mdx
@@ -41,7 +41,43 @@ Go Signature: `WindowReload(ctx context.Context)`
JS Signature: `WindowReload()`
-Performs a "reload" (Reloads index.html)
+Performs a "reload" (Reloads current page).
+
+### WindowReloadApp
+Go Signature: `WindowReloadApp(ctx context.Context)`
+
+JS Signature: `WindowReloadApp()`
+
+Reloads the application frontend.
+
+### WindowSetSy
+
+### WindowSetSystemDefaultTheme
+Go Signature: `WindowSetSystemDefaultTheme(ctx context.Context)`
+
+JS Signature: `WindowSetSystemDefaultTheme()`
+
+Windows only.
+
+Sets window theme to system default (dark/light).
+
+### WindowSetLightTheme
+Go Signature: `WindowSetLightTheme(ctx context.Context)`
+
+JS Signature: `WindowSetLightTheme()`
+
+Windows only.
+
+Sets window theme to light.
+
+### WindowSetDarkTheme
+Go Signature: `WindowSetDarkTheme(ctx context.Context)`
+
+JS Signature: `WindowSetDarkTheme()`
+
+Windows only.
+
+Sets window theme to dark.
### WindowShow
Go Signature: `WindowShow(ctx context.Context)`
@@ -91,6 +127,14 @@ Will resize the window if the window is currently larger than the given dimensio
Setting a size of `0,0` will disable this constraint.
+### WindowSetAlwaysOnTop
+Go Signature: `WindowSetAlwaysOnTop(ctx context.Context, b bool)`
+
+JS Signature: `WindowSetAlwaysOnTop(b: Boolen)`
+
+Sets the window AlwaysOnTop or not on top.
+
+
### WindowSetPosition
Go Signature: `WindowSetPosition(ctx context.Context, x int, y int)`
diff --git a/website/versioned_sidebars/version-v2.0.0-beta.34-sidebars.json b/website/versioned_sidebars/version-v2.0.0-beta.37-sidebars.json
similarity index 100%
rename from website/versioned_sidebars/version-v2.0.0-beta.34-sidebars.json
rename to website/versioned_sidebars/version-v2.0.0-beta.37-sidebars.json
diff --git a/website/versioned_sidebars/version-v2.0.0-beta.35-sidebars.json b/website/versioned_sidebars/version-v2.0.0-beta.38-sidebars.json
similarity index 100%
rename from website/versioned_sidebars/version-v2.0.0-beta.35-sidebars.json
rename to website/versioned_sidebars/version-v2.0.0-beta.38-sidebars.json
diff --git a/website/versions.json b/website/versions.json
index b6fd4043d..3b9e55047 100644
--- a/website/versions.json
+++ b/website/versions.json
@@ -1,4 +1,4 @@
[
- "v2.0.0-beta.35",
- "v2.0.0-beta.34"
-]
+ "v2.0.0-beta.38",
+ "v2.0.0-beta.37"
+]
\ No newline at end of file