From 5a37091bb0a699a86ab6a3f1d634bdd057a11123 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 7 Dec 2022 21:55:09 +1100 Subject: [PATCH 01/85] Initial play around --- exp/.gitignore | 2 + exp/cmd/wails/main.go | 20 ++++ exp/examples/basic/main.go | 50 ++++++++++ exp/go.mod | 5 + exp/go.sum | 2 + exp/internal/commands/build.go | 8 ++ exp/internal/commands/init.go | 8 ++ exp/pkg/application/app_delegate.h | 8 ++ exp/pkg/application/app_delegate.m | 35 +++++++ exp/pkg/application/application.go | 24 +++++ exp/pkg/application/application.h | 5 + exp/pkg/application/application.m | 22 +++++ exp/pkg/application/application_darwin.go | 60 ++++++++++++ exp/pkg/application/events.go | 3 + exp/pkg/application/window.go | 51 ++++++++++ exp/pkg/application/window_darwin.go | 109 ++++++++++++++++++++++ exp/pkg/application/window_delegate.h | 16 ++++ exp/pkg/application/window_delegate.m | 23 +++++ exp/pkg/events/events.go | 15 +++ exp/pkg/events/events.h | 12 +++ exp/pkg/events/events.txt | 2 + exp/pkg/options/application.go | 27 ++++++ exp/tasks/Taskfile.yml | 7 ++ exp/tasks/events/generate.go | 85 +++++++++++++++++ 24 files changed, 599 insertions(+) create mode 100644 exp/.gitignore create mode 100644 exp/cmd/wails/main.go create mode 100644 exp/examples/basic/main.go create mode 100644 exp/go.mod create mode 100644 exp/go.sum create mode 100644 exp/internal/commands/build.go create mode 100644 exp/internal/commands/init.go create mode 100644 exp/pkg/application/app_delegate.h create mode 100644 exp/pkg/application/app_delegate.m create mode 100644 exp/pkg/application/application.go create mode 100644 exp/pkg/application/application.h create mode 100644 exp/pkg/application/application.m create mode 100644 exp/pkg/application/application_darwin.go create mode 100644 exp/pkg/application/events.go create mode 100644 exp/pkg/application/window.go create mode 100644 exp/pkg/application/window_darwin.go create mode 100644 exp/pkg/application/window_delegate.h create mode 100644 exp/pkg/application/window_delegate.m create mode 100644 exp/pkg/events/events.go create mode 100644 exp/pkg/events/events.h create mode 100644 exp/pkg/events/events.txt create mode 100644 exp/pkg/options/application.go create mode 100644 exp/tasks/Taskfile.yml create mode 100644 exp/tasks/events/generate.go diff --git a/exp/.gitignore b/exp/.gitignore new file mode 100644 index 000000000..3fa7f363f --- /dev/null +++ b/exp/.gitignore @@ -0,0 +1,2 @@ +examples/basic/basic +cmd/wails/wails \ No newline at end of file diff --git a/exp/cmd/wails/main.go b/exp/cmd/wails/main.go new file mode 100644 index 000000000..f531802d4 --- /dev/null +++ b/exp/cmd/wails/main.go @@ -0,0 +1,20 @@ +package main + +import ( + "log" + + "github.com/leaanthony/clir" + "github.com/wailsapp/wails/exp/internal/commands" +) + +func main() { + + app := clir.NewCli("wails", "The Wails CLI", "v3") + app.NewSubCommandFunction("init", "Initialise a new project", commands.Init) + app.NewSubCommandFunction("build", "Build the project", commands.Build) + + err := app.Run() + if err != nil { + log.Fatalln(err) + } +} diff --git a/exp/examples/basic/main.go b/exp/examples/basic/main.go new file mode 100644 index 000000000..c6c354fe0 --- /dev/null +++ b/exp/examples/basic/main.go @@ -0,0 +1,50 @@ +package main + +import ( + "log" + "time" + + "github.com/wailsapp/wails/exp/pkg/application" + "github.com/wailsapp/wails/exp/pkg/events" + "github.com/wailsapp/wails/exp/pkg/options" +) + +func main() { + app := application.New(&options.Application{ + Mac: &options.Mac{ + //ActivationPolicy: options.ActivationPolicyAccessory, + }, + }) + app.On(events.Mac.ApplicationDidFinishLaunching, func() { + println("WOOOOO!") + }) + app.On(events.Mac.ApplicationWillTerminate, func() { + println("TERMINATION!!") + }) + myWindow := app.NewWindow(&options.Window{ + Title: "Basic", + Width: 600, + Height: 400, + AlwaysOnTop: false, + }) + + myWindow2 := app.NewWindow(&options.Window{ + Title: "#2", + Width: 1024, + Height: 768, + AlwaysOnTop: false, + }) + + go func() { + time.Sleep(5 * time.Second) + myWindow.SetTitle("Wooooo") + myWindow.SetAlwaysOnTop(true) + myWindow2.SetTitle("OMFG") + }() + + err := app.Run() + + if err != nil { + log.Fatal(err) + } +} diff --git a/exp/go.mod b/exp/go.mod new file mode 100644 index 000000000..1969eb348 --- /dev/null +++ b/exp/go.mod @@ -0,0 +1,5 @@ +module github.com/wailsapp/wails/exp + +go 1.19 + +require github.com/leaanthony/clir v1.3.0 diff --git a/exp/go.sum b/exp/go.sum new file mode 100644 index 000000000..ec90627a4 --- /dev/null +++ b/exp/go.sum @@ -0,0 +1,2 @@ +github.com/leaanthony/clir v1.3.0 h1:L9nPDWrmc/qU9UWZZvRaFajWYuO0np9V5p+5gxyYno0= +github.com/leaanthony/clir v1.3.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= diff --git a/exp/internal/commands/build.go b/exp/internal/commands/build.go new file mode 100644 index 000000000..66fde3150 --- /dev/null +++ b/exp/internal/commands/build.go @@ -0,0 +1,8 @@ +package commands + +type BuildOptions struct { +} + +func Build(options *BuildOptions) error { + return nil +} diff --git a/exp/internal/commands/init.go b/exp/internal/commands/init.go new file mode 100644 index 000000000..14248a4f3 --- /dev/null +++ b/exp/internal/commands/init.go @@ -0,0 +1,8 @@ +package commands + +type InitOptions struct { +} + +func Init(options *InitOptions) error { + return nil +} diff --git a/exp/pkg/application/app_delegate.h b/exp/pkg/application/app_delegate.h new file mode 100644 index 000000000..0a318f4ae --- /dev/null +++ b/exp/pkg/application/app_delegate.h @@ -0,0 +1,8 @@ +//go:build darwin + +#import + +@interface AppDelegate : NSObject +@property NSApplicationActivationPolicy activationPolicy; +- (void)setApplicationActivationPolicy:(NSApplicationActivationPolicy)policy; +@end \ No newline at end of file diff --git a/exp/pkg/application/app_delegate.m b/exp/pkg/application/app_delegate.m new file mode 100644 index 000000000..921feb0d4 --- /dev/null +++ b/exp/pkg/application/app_delegate.m @@ -0,0 +1,35 @@ +//go:build darwin + +#import "app_delegate.h" +#import "../events/events.h" + +@implementation AppDelegate + +- (void)dealloc +{ + [super dealloc]; +} + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification +{ + [NSApp setActivationPolicy:self.activationPolicy]; + [NSApp activateIgnoringOtherApps:YES]; + + //callOnApplicationDidFinishLaunchingHandler(); + systemEventHandler(EventApplicationDidFinishLaunching); + +} + +- (void)setApplicationActivationPolicy:(NSApplicationActivationPolicy)policy +{ + self.activationPolicy = policy; +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification +{ + systemEventHandler(EventApplicationWillTerminate); +} + + + +@end \ No newline at end of file diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go new file mode 100644 index 000000000..7b03bf82f --- /dev/null +++ b/exp/pkg/application/application.go @@ -0,0 +1,24 @@ +package application + +import "github.com/wailsapp/wails/exp/pkg/options" + +type Application interface { + Run() error +} + +type App struct { + options *options.Application + systemEventListeners map[string][]func() + + windows []*Window +} + +func (a *App) On(s string, callback func()) { + a.systemEventListeners[s] = append(a.systemEventListeners[s], callback) +} + +func (a *App) NewWindow(options *options.Window) *Window { + newWindow := NewWindow(options) + a.windows = append(a.windows, newWindow) + return newWindow +} diff --git a/exp/pkg/application/application.h b/exp/pkg/application/application.h new file mode 100644 index 000000000..93f931fb5 --- /dev/null +++ b/exp/pkg/application/application.h @@ -0,0 +1,5 @@ +//go:build darwin + +void Init(void); +void Run(void); +void SetActivationPolicy(int policy); \ No newline at end of file diff --git a/exp/pkg/application/application.m b/exp/pkg/application/application.m new file mode 100644 index 000000000..3833b8deb --- /dev/null +++ b/exp/pkg/application/application.m @@ -0,0 +1,22 @@ +//go:build darwin + +#import "app_delegate.h" + +AppDelegate *appDelegate = nil; + +void Init(void) { + [NSApplication sharedApplication]; + appDelegate = [[AppDelegate alloc] init]; + [NSApp setDelegate:appDelegate]; +} + +void SetActivationPolicy(int policy) { + [appDelegate setApplicationActivationPolicy:policy]; +} + +void Run(void) { + @autoreleasepool { + [NSApp run]; + [appDelegate release]; + } +} diff --git a/exp/pkg/application/application_darwin.go b/exp/pkg/application/application_darwin.go new file mode 100644 index 000000000..b26a518e3 --- /dev/null +++ b/exp/pkg/application/application_darwin.go @@ -0,0 +1,60 @@ +//go:build darwin + +package application + +/* + +#cgo CFLAGS: -x objective-c +#cgo LDFLAGS: -framework Cocoa -mmacosx-version-min=10.13 +#include "application.h" +*/ +import "C" +import "github.com/wailsapp/wails/exp/pkg/options" + +func New(options *options.Application) *App { + C.Init() + if options.Mac != nil { + C.SetActivationPolicy(C.int(options.Mac.ActivationPolicy)) + } + return &App{ + options: options, + systemEventListeners: make(map[string][]func()), + } +} + +func (a *App) Run() error { + + go func() { + for { + event := <-systemEvents + a.handleSystemEvent(event) + } + }() + + // Run windows + for _, window := range a.windows { + err := window.Run() + if err != nil { + return err + } + } + + C.Run() + return nil +} + +func (a *App) handleSystemEvent(event string) { + listeners, ok := a.systemEventListeners[event] + if !ok { + return + } + for _, listener := range listeners { + go listener() + } +} + +//export systemEventHandler +func systemEventHandler(name *C.char) { + goString := C.GoString(name) + systemEvents <- goString +} diff --git a/exp/pkg/application/events.go b/exp/pkg/application/events.go new file mode 100644 index 000000000..cd3d7cd4e --- /dev/null +++ b/exp/pkg/application/events.go @@ -0,0 +1,3 @@ +package application + +var systemEvents = make(chan string) diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go new file mode 100644 index 000000000..1b9902b11 --- /dev/null +++ b/exp/pkg/application/window.go @@ -0,0 +1,51 @@ +package application + +import "github.com/wailsapp/wails/exp/pkg/options" + +type windowImpl interface { + setTitle(title string) + setSize(width, height int) + setAlwaysOnTop(alwaysOnTop bool) + Run() error +} + +type Window struct { + options *options.Window + impl windowImpl +} + +func NewWindow(options *options.Window) *Window { + return &Window{ + options: options, + } +} + +func (w *Window) SetTitle(title string) { + if w.impl == nil { + w.options.Title = title + return + } + w.impl.setTitle(title) +} + +func (w *Window) SetSize(width, height int) { + if w.impl == nil { + w.options.Width = width + w.options.Height = height + return + } + w.impl.setSize(width, height) +} + +func (w *Window) Run() error { + w.impl = newWindowImpl(w.options) + return w.impl.Run() +} + +func (w *Window) SetAlwaysOnTop(b bool) { + if w.impl == nil { + w.options.AlwaysOnTop = b + return + } + w.impl.setAlwaysOnTop(b) +} diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go new file mode 100644 index 000000000..a8d81af85 --- /dev/null +++ b/exp/pkg/application/window_darwin.go @@ -0,0 +1,109 @@ +//go:build darwin + +package application + +/* +#cgo CFLAGS: -mmacosx-version-min=10.10 -x objective-c +#cgo LDFLAGS: -framework Cocoa + +#include "application.h" +#include "window_delegate.h" +#include +#include "Cocoa/Cocoa.h" + +// Create a new Window +void* windowNew(int width, int height) { + NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, width-1, height-1) + styleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask + backing:NSBackingStoreBuffered + defer:NO]; + // Create delegate + WindowDelegate* delegate = [[WindowDelegate alloc] init]; + // Set delegate + [window setDelegate:delegate]; + + delegate.hideOnClose = false; + return window; +} + +// Set the title of the NSWindow +void windowSetTitle(void* nsWindow, char* title) { + // Set window title on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + NSString* nsTitle = [NSString stringWithUTF8String:title]; + [(NSWindow*)nsWindow setTitle:nsTitle]; + free(title); + }); +} + +// Set the size of the NSWindow +void windowSetSize(void* nsWindow, int width, int height) { + // Set window size on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + [(NSWindow*)nsWindow setContentSize:NSMakeSize(width, height)]; + NSRect frame = [(NSWindow*)nsWindow frame]; + frame.size.width = width; + frame.size.height = height; + [(NSWindow*)nsWindow setFrame:frame display:YES]; + }); + +} + +// Show the NSWindow +void windowShow(void* nsWindow) { + [(NSWindow*)nsWindow makeKeyAndOrderFront:nil]; +} + +// Hide the NSWindow +void windowHide(void* nsWindow) { + [(NSWindow*)nsWindow orderOut:nil]; +} + +// Set NSWindow always on top +void windowSetAlwaysOnTop(void* nsWindow, bool alwaysOnTop) { + // Set window always on top on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + [(NSWindow*)nsWindow setLevel:alwaysOnTop ? NSStatusWindowLevel : NSNormalWindowLevel]; + }); +} + +*/ +import "C" +import ( + "unsafe" + + "github.com/wailsapp/wails/exp/pkg/options" +) + +type macosWindow struct { + nsWindow unsafe.Pointer + options *options.Window +} + +func (w *macosWindow) setAlwaysOnTop(alwaysOnTop bool) { + C.windowSetAlwaysOnTop(w.nsWindow, C.bool(alwaysOnTop)) +} + +func newWindowImpl(options *options.Window) *macosWindow { + result := &macosWindow{ + options: options, + } + return result +} + +func (w *macosWindow) setTitle(title string) { + cTitle := C.CString(title) + C.windowSetTitle(w.nsWindow, cTitle) +} + +func (w *macosWindow) setSize(width, height int) { + C.windowSetSize(w.nsWindow, C.int(width), C.int(height)) +} + +func (w *macosWindow) Run() error { + w.nsWindow = C.windowNew(C.int(w.options.Width), C.int(w.options.Height)) + w.setTitle(w.options.Title) + w.setAlwaysOnTop(w.options.AlwaysOnTop) + C.windowShow(w.nsWindow) + return nil +} diff --git a/exp/pkg/application/window_delegate.h b/exp/pkg/application/window_delegate.h new file mode 100644 index 000000000..27937938e --- /dev/null +++ b/exp/pkg/application/window_delegate.h @@ -0,0 +1,16 @@ +//go:build darwin + + +#ifndef WindowDelegate_h +#define WindowDelegate_h + +#import + +@interface WindowDelegate : NSObject + +@property bool hideOnClose; + +@end + + +#endif /* WindowDelegate_h */ diff --git a/exp/pkg/application/window_delegate.m b/exp/pkg/application/window_delegate.m new file mode 100644 index 000000000..2bf7e2324 --- /dev/null +++ b/exp/pkg/application/window_delegate.m @@ -0,0 +1,23 @@ +//go:build darwin +// +// WindowDelegate.m +// test +// +// Created by Lea Anthony on 10/10/21. +// + +#import +#import +#import "window_delegate.h" + +@implementation WindowDelegate +- (BOOL)windowShouldClose:(NSWindow *)sender { + if( self.hideOnClose ) { + [NSApp hide:nil]; + return false; + } + return true; +} + + +@end diff --git a/exp/pkg/events/events.go b/exp/pkg/events/events.go new file mode 100644 index 000000000..d172559e5 --- /dev/null +++ b/exp/pkg/events/events.go @@ -0,0 +1,15 @@ +package events + +var Mac = newMacEvents() + +type macEvents struct { + ApplicationDidFinishLaunching string + ApplicationWillTerminate string +} + +func newMacEvents() macEvents { + return macEvents{ + ApplicationDidFinishLaunching: "mac:ApplicationDidFinishLaunching", + ApplicationWillTerminate: "mac:ApplicationWillTerminate", + } +} diff --git a/exp/pkg/events/events.h b/exp/pkg/events/events.h new file mode 100644 index 000000000..f6cbc5f55 --- /dev/null +++ b/exp/pkg/events/events.h @@ -0,0 +1,12 @@ +//go:build darwin + +#ifndef _events_h +#define _events_h + +extern void systemEventHandler(char*); + +#define EventApplicationDidFinishLaunching "mac:ApplicationDidFinishLaunching" +#define EventApplicationWillTerminate "mac:ApplicationWillTerminate" + + +#endif \ No newline at end of file diff --git a/exp/pkg/events/events.txt b/exp/pkg/events/events.txt new file mode 100644 index 000000000..0f7fd4f70 --- /dev/null +++ b/exp/pkg/events/events.txt @@ -0,0 +1,2 @@ +mac:ApplicationDidFinishLaunching +mac:ApplicationWillTerminate \ No newline at end of file diff --git a/exp/pkg/options/application.go b/exp/pkg/options/application.go new file mode 100644 index 000000000..40d1c6e97 --- /dev/null +++ b/exp/pkg/options/application.go @@ -0,0 +1,27 @@ +package options + +type Application struct { + Mac *Mac +} + +// Mac contains macOS specific options + +type ActivationPolicy int + +const ( + ActivationPolicyRegular ActivationPolicy = iota + ActivationPolicyAccessory + ActivationPolicyProhibited +) + +type Mac struct { + // ActivationPolicy is the activation policy for the application. Defaults to + // applicationActivationPolicyRegular. + ActivationPolicy ActivationPolicy +} + +type Window struct { + Title string + Width, Height int + AlwaysOnTop bool +} diff --git a/exp/tasks/Taskfile.yml b/exp/tasks/Taskfile.yml new file mode 100644 index 000000000..1949fb8f9 --- /dev/null +++ b/exp/tasks/Taskfile.yml @@ -0,0 +1,7 @@ +version: '3' + +tasks: + generate: + dir: ./events + cmds: + - go run generate.go diff --git a/exp/tasks/events/generate.go b/exp/tasks/events/generate.go new file mode 100644 index 000000000..040f8acee --- /dev/null +++ b/exp/tasks/events/generate.go @@ -0,0 +1,85 @@ +package main + +import ( + "bytes" + "os" + "strings" +) + +var eventsGo = `package events + +var Mac = newMacEvents() + +type macEvents struct { +$$MACEVENTSDECL} + +func newMacEvents() macEvents { + return macEvents{ +$$MACEVENTSVALUES } +} +` + +var eventsH = `//go:build darwin + +#ifndef _events_h +#define _events_h + +extern void systemEventHandler(char*); + +$$CHEADEREVENTS + +#endif` + +func main() { + + eventNames, err := os.ReadFile("../../pkg/events/events.txt") + if err != nil { + panic(err) + } + + macEventsDecl := bytes.NewBufferString("") + macEventsValues := bytes.NewBufferString("") + cHeaderEvents := bytes.NewBufferString("") + + // Loop over each line in the file + for _, line := range bytes.Split(eventNames, []byte{'\n'}) { + + // Skip empty lines + if len(line) == 0 { + continue + } + + // split on the colon + split := bytes.Split(line, []byte{':'}) + platform := strings.TrimSpace(string(split[0])) + event := strings.TrimSpace(string(split[1])) + + // Title case the event name + eventTitle := string(bytes.ToUpper([]byte{event[0]})) + event[1:] + + // Add to buffer + switch platform { + case "mac": + macEventsDecl.WriteString("\t" + eventTitle + " string\n") + macEventsValues.WriteString("\t\t" + event + ": \"" + platform + ":" + event + "\",\n") + cHeaderEvents.WriteString("#define Event" + eventTitle + " \"" + platform + ":" + event + "\"\n") + } + + } + + // Save the eventsGo template substituting the values and decls + templateToWrite := strings.ReplaceAll(eventsGo, "$$MACEVENTSDECL", macEventsDecl.String()) + templateToWrite = strings.ReplaceAll(templateToWrite, "$$MACEVENTSVALUES", macEventsValues.String()) + err = os.WriteFile("../../pkg/events/events.go", []byte(templateToWrite), 0644) + if err != nil { + panic(err) + } + + // Save the eventsH template substituting the values and decls + templateToWrite = strings.ReplaceAll(eventsH, "$$CHEADEREVENTS", cHeaderEvents.String()) + err = os.WriteFile("../../pkg/events/events.h", []byte(templateToWrite), 0644) + if err != nil { + panic(err) + } + +} From 05803fb5d5b583ee27370c7c29da10df85e69f4b Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 7 Dec 2022 23:30:20 +1100 Subject: [PATCH 02/85] Add more Window API --- app.go | 2 +- exp/examples/basic/main.go | 21 ++++++----- exp/pkg/application/application_darwin.go | 2 +- exp/pkg/application/window.go | 22 ++++++++++-- exp/pkg/application/window_darwin.go | 43 +++++++++++++++++++++-- exp/pkg/application/window_delegate.h | 2 ++ exp/pkg/options/application.go | 3 ++ 7 files changed, 81 insertions(+), 14 deletions(-) diff --git a/app.go b/app.go index 95a8a7e82..ca9ca004e 100644 --- a/app.go +++ b/app.go @@ -141,7 +141,7 @@ func (a *App) start() error { // Defer the shutdown defer a.shutdown() - // Run the renderer + // run the renderer err = a.renderer.Run() if err != nil { return err diff --git a/exp/examples/basic/main.go b/exp/examples/basic/main.go index c6c354fe0..a89e11f0f 100644 --- a/exp/examples/basic/main.go +++ b/exp/examples/basic/main.go @@ -22,17 +22,21 @@ func main() { println("TERMINATION!!") }) myWindow := app.NewWindow(&options.Window{ - Title: "Basic", - Width: 600, - Height: 400, - AlwaysOnTop: false, + Title: "Basic", + Width: 600, + Height: 400, + AlwaysOnTop: false, + URL: "https://google.com", + DisableResize: false, }) myWindow2 := app.NewWindow(&options.Window{ - Title: "#2", - Width: 1024, - Height: 768, - AlwaysOnTop: false, + Title: "#2", + Width: 1024, + Height: 768, + AlwaysOnTop: false, + URL: "https://google.com", + DisableResize: true, }) go func() { @@ -40,6 +44,7 @@ func main() { myWindow.SetTitle("Wooooo") myWindow.SetAlwaysOnTop(true) myWindow2.SetTitle("OMFG") + myWindow2.NavigateToURL("https://wails.io") }() err := app.Run() diff --git a/exp/pkg/application/application_darwin.go b/exp/pkg/application/application_darwin.go index b26a518e3..c30a60864 100644 --- a/exp/pkg/application/application_darwin.go +++ b/exp/pkg/application/application_darwin.go @@ -31,7 +31,7 @@ func (a *App) Run() error { } }() - // Run windows + // run windows for _, window := range a.windows { err := window.Run() if err != nil { diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index 1b9902b11..dc6e58ad5 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -6,7 +6,9 @@ type windowImpl interface { setTitle(title string) setSize(width, height int) setAlwaysOnTop(alwaysOnTop bool) - Run() error + run() error + navigateToURL(url string) + setResizable(resizable bool) } type Window struct { @@ -39,7 +41,7 @@ func (w *Window) SetSize(width, height int) { func (w *Window) Run() error { w.impl = newWindowImpl(w.options) - return w.impl.Run() + return w.impl.run() } func (w *Window) SetAlwaysOnTop(b bool) { @@ -49,3 +51,19 @@ func (w *Window) SetAlwaysOnTop(b bool) { } w.impl.setAlwaysOnTop(b) } + +func (w *Window) NavigateToURL(s string) { + if w.impl == nil { + w.options.URL = s + return + } + w.impl.navigateToURL(s) +} + +func (w *Window) SetResizable(b bool) { + if w.impl == nil { + w.options.DisableResize = !b + return + } + w.impl.setResizable(b) +} diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index a8d81af85..2f229f8dc 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -4,12 +4,14 @@ package application /* #cgo CFLAGS: -mmacosx-version-min=10.10 -x objective-c -#cgo LDFLAGS: -framework Cocoa +#cgo LDFLAGS: -framework Cocoa -framework WebKit #include "application.h" #include "window_delegate.h" #include #include "Cocoa/Cocoa.h" +#import + // Create a new Window void* windowNew(int width, int height) { @@ -22,6 +24,13 @@ void* windowNew(int width, int height) { // Set delegate [window setDelegate:delegate]; + // Embed wkwebview in window + NSRect frame = NSMakeRect(0, 0, width, height); + WKWebViewConfiguration* config = [[WKWebViewConfiguration alloc] init]; + WKWebView* webView = [[WKWebView alloc] initWithFrame:frame configuration:config]; + [window setContentView:webView]; + delegate.webView = webView; + delegate.hideOnClose = false; return window; } @@ -67,6 +76,26 @@ void windowSetAlwaysOnTop(void* nsWindow, bool alwaysOnTop) { }); } +// Load URL in NSWindow +void navigationLoadURL(void* nsWindow, char* url) { + // Load URL on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + NSURL* nsURL = [NSURL URLWithString:[NSString stringWithUTF8String:url]]; + NSURLRequest* request = [NSURLRequest requestWithURL:nsURL]; + [[(WindowDelegate*)[(NSWindow*)nsWindow delegate] webView] loadRequest:request]; + free(url); + }); +} + +// Set NSWindow resizable +void windowSetResizable(void* nsWindow, bool resizable) { + // Set window resizable on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + [(NSWindow*)nsWindow setStyleMask:resizable ? NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask : NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask]; + }); +} + + */ import "C" import ( @@ -80,6 +109,10 @@ type macosWindow struct { options *options.Window } +func (w *macosWindow) navigateToURL(url string) { + C.navigationLoadURL(w.nsWindow, C.CString(url)) +} + func (w *macosWindow) setAlwaysOnTop(alwaysOnTop bool) { C.windowSetAlwaysOnTop(w.nsWindow, C.bool(alwaysOnTop)) } @@ -100,10 +133,16 @@ func (w *macosWindow) setSize(width, height int) { C.windowSetSize(w.nsWindow, C.int(width), C.int(height)) } -func (w *macosWindow) Run() error { +func (w *macosWindow) setResizable(resizable bool) { + C.windowSetResizable(w.nsWindow, C.bool(resizable)) +} + +func (w *macosWindow) run() error { w.nsWindow = C.windowNew(C.int(w.options.Width), C.int(w.options.Height)) w.setTitle(w.options.Title) w.setAlwaysOnTop(w.options.AlwaysOnTop) + w.setResizable(!w.options.DisableResize) C.windowShow(w.nsWindow) + C.navigationLoadURL(w.nsWindow, C.CString(w.options.URL)) return nil } diff --git a/exp/pkg/application/window_delegate.h b/exp/pkg/application/window_delegate.h index 27937938e..26ca44643 100644 --- a/exp/pkg/application/window_delegate.h +++ b/exp/pkg/application/window_delegate.h @@ -5,10 +5,12 @@ #define WindowDelegate_h #import +#import @interface WindowDelegate : NSObject @property bool hideOnClose; +@property (retain) WKWebView* webView; @end diff --git a/exp/pkg/options/application.go b/exp/pkg/options/application.go index 40d1c6e97..8c178bce7 100644 --- a/exp/pkg/options/application.go +++ b/exp/pkg/options/application.go @@ -24,4 +24,7 @@ type Window struct { Title string Width, Height int AlwaysOnTop bool + URL string + DisableResize bool + Resizable bool } From af6daa273e8f83d59f4262c5389f6fb50fa99295 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 7 Dec 2022 23:44:19 +1100 Subject: [PATCH 03/85] Support min/max window size --- exp/examples/basic/main.go | 6 ++++ exp/pkg/application/window.go | 33 +++++++++++++++++++++ exp/pkg/application/window_darwin.go | 43 +++++++++++++++++++++++++++- exp/pkg/options/application.go | 4 +++ 4 files changed, 85 insertions(+), 1 deletion(-) diff --git a/exp/examples/basic/main.go b/exp/examples/basic/main.go index a89e11f0f..ef301dc00 100644 --- a/exp/examples/basic/main.go +++ b/exp/examples/basic/main.go @@ -28,6 +28,10 @@ func main() { AlwaysOnTop: false, URL: "https://google.com", DisableResize: false, + MinWidth: 100, + MinHeight: 100, + MaxWidth: 1000, + MaxHeight: 1000, }) myWindow2 := app.NewWindow(&options.Window{ @@ -45,6 +49,8 @@ func main() { myWindow.SetAlwaysOnTop(true) myWindow2.SetTitle("OMFG") myWindow2.NavigateToURL("https://wails.io") + myWindow.SetMinSize(600, 600) + myWindow.SetMaxSize(650, 650) }() err := app.Run() diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index dc6e58ad5..5c70c4439 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -9,6 +9,8 @@ type windowImpl interface { run() error navigateToURL(url string) setResizable(resizable bool) + setMinSize(width, height int) + setMaxSize(width, height int) } type Window struct { @@ -67,3 +69,34 @@ func (w *Window) SetResizable(b bool) { } w.impl.setResizable(b) } + +func (w *Window) SetMinSize(minWidth, minHeight int) { + if w.impl == nil { + w.options.MinWidth = minWidth + if w.options.Width < minWidth { + w.options.Width = minWidth + } + w.options.MinHeight = minHeight + if w.options.Height < minHeight { + w.options.Height = minHeight + } + return + } + w.impl.setSize(w.options.Width, w.options.Height) + w.impl.setMinSize(minWidth, minHeight) +} +func (w *Window) SetMaxSize(maxWidth, maxHeight int) { + if w.impl == nil { + w.options.MinWidth = maxWidth + if w.options.Width > maxWidth { + w.options.Width = maxWidth + } + w.options.MinHeight = maxHeight + if w.options.Height > maxHeight { + w.options.Height = maxHeight + } + return + } + w.impl.setSize(w.options.Width, w.options.Height) + w.impl.setMaxSize(maxWidth, maxHeight) +} diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index 2f229f8dc..c3a0f823c 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -95,6 +95,36 @@ void windowSetResizable(void* nsWindow, bool resizable) { }); } +// Set NSWindow min size +void windowSetMinSize(void* nsWindow, int width, int height) { + // Set window min size on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + [(NSWindow*)nsWindow setContentMinSize:NSMakeSize(width, height)]; + }); +} + +// Set NSWindow max size +void windowSetMaxSize(void* nsWindow, int width, int height) { + // Set window max size on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + [(NSWindow*)nsWindow setContentMaxSize:NSMakeSize(width, height)]; + }); +} + +// Reset NSWindow min and max size +void windowResetMinSize(void* nsWindow) { + // Reset window min size on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + [(NSWindow*)nsWindow setContentMinSize:NSMakeSize(0, 0)]; + }); +} + +void windowResetMaxSize(void* nsWindow) { + // Reset window max size on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + [(NSWindow*)nsWindow setContentMaxSize:NSMakeSize(0, 0)]; + }); +} */ import "C" @@ -133,6 +163,13 @@ func (w *macosWindow) setSize(width, height int) { C.windowSetSize(w.nsWindow, C.int(width), C.int(height)) } +func (w *macosWindow) setMinSize(width, height int) { + C.windowSetMinSize(w.nsWindow, C.int(width), C.int(height)) +} +func (w *macosWindow) setMaxSize(width, height int) { + C.windowSetMaxSize(w.nsWindow, C.int(width), C.int(height)) +} + func (w *macosWindow) setResizable(resizable bool) { C.windowSetResizable(w.nsWindow, C.bool(resizable)) } @@ -142,7 +179,11 @@ func (w *macosWindow) run() error { w.setTitle(w.options.Title) w.setAlwaysOnTop(w.options.AlwaysOnTop) w.setResizable(!w.options.DisableResize) + w.setMinSize(w.options.MinWidth, w.options.MinHeight) + w.setMaxSize(w.options.MaxWidth, w.options.MaxHeight) + if w.options.URL != "" { + w.navigateToURL(w.options.URL) + } C.windowShow(w.nsWindow) - C.navigationLoadURL(w.nsWindow, C.CString(w.options.URL)) return nil } diff --git a/exp/pkg/options/application.go b/exp/pkg/options/application.go index 8c178bce7..a223ec367 100644 --- a/exp/pkg/options/application.go +++ b/exp/pkg/options/application.go @@ -27,4 +27,8 @@ type Window struct { URL string DisableResize bool Resizable bool + MinWidth int + MinHeight int + MaxWidth int + MaxHeight int } From df1cc2ee0be2660d67a595c8220e5cacb60b4019 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 7 Dec 2022 23:52:16 +1100 Subject: [PATCH 04/85] Support EnableDevTools --- exp/examples/basic/main.go | 22 ++++++++++++---------- exp/pkg/application/window.go | 9 +++++++++ exp/pkg/application/window_darwin.go | 16 ++++++++++++++++ exp/pkg/options/application.go | 21 +++++++++++---------- 4 files changed, 48 insertions(+), 20 deletions(-) diff --git a/exp/examples/basic/main.go b/exp/examples/basic/main.go index ef301dc00..f85aceaf2 100644 --- a/exp/examples/basic/main.go +++ b/exp/examples/basic/main.go @@ -22,16 +22,17 @@ func main() { println("TERMINATION!!") }) myWindow := app.NewWindow(&options.Window{ - Title: "Basic", - Width: 600, - Height: 400, - AlwaysOnTop: false, - URL: "https://google.com", - DisableResize: false, - MinWidth: 100, - MinHeight: 100, - MaxWidth: 1000, - MaxHeight: 1000, + Title: "Basic", + Width: 600, + Height: 400, + AlwaysOnTop: false, + URL: "https://google.com", + DisableResize: false, + MinWidth: 100, + MinHeight: 100, + MaxWidth: 1000, + MaxHeight: 1000, + EnableDevTools: true, }) myWindow2 := app.NewWindow(&options.Window{ @@ -47,6 +48,7 @@ func main() { time.Sleep(5 * time.Second) myWindow.SetTitle("Wooooo") myWindow.SetAlwaysOnTop(true) + myWindow2.EnableDevTools() myWindow2.SetTitle("OMFG") myWindow2.NavigateToURL("https://wails.io") myWindow.SetMinSize(600, 600) diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index 5c70c4439..f275ad03e 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -11,6 +11,7 @@ type windowImpl interface { setResizable(resizable bool) setMinSize(width, height int) setMaxSize(width, height int) + enableDevTools() } type Window struct { @@ -100,3 +101,11 @@ func (w *Window) SetMaxSize(maxWidth, maxHeight int) { w.impl.setSize(w.options.Width, w.options.Height) w.impl.setMaxSize(maxWidth, maxHeight) } + +func (w *Window) EnableDevTools() { + if w.impl == nil { + w.options.EnableDevTools = true + return + } + w.impl.enableDevTools() +} diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index c3a0f823c..145dc142d 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -126,6 +126,16 @@ void windowResetMaxSize(void* nsWindow) { }); } +// Enable NSWindow devtools +void windowEnableDevTools(void* nsWindow) { + // Enable devtools on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + // Get window delegate + WindowDelegate* delegate = (WindowDelegate*)[(NSWindow*)nsWindow delegate]; + // Enable devtools in webview + [delegate.webView.configuration.preferences setValue:@YES forKey:@"developerExtrasEnabled"]; + }); +} */ import "C" import ( @@ -173,6 +183,9 @@ func (w *macosWindow) setMaxSize(width, height int) { func (w *macosWindow) setResizable(resizable bool) { C.windowSetResizable(w.nsWindow, C.bool(resizable)) } +func (w *macosWindow) enableDevTools() { + C.windowEnableDevTools(w.nsWindow) +} func (w *macosWindow) run() error { w.nsWindow = C.windowNew(C.int(w.options.Width), C.int(w.options.Height)) @@ -184,6 +197,9 @@ func (w *macosWindow) run() error { if w.options.URL != "" { w.navigateToURL(w.options.URL) } + if w.options.EnableDevTools { + w.enableDevTools() + } C.windowShow(w.nsWindow) return nil } diff --git a/exp/pkg/options/application.go b/exp/pkg/options/application.go index a223ec367..624087bb7 100644 --- a/exp/pkg/options/application.go +++ b/exp/pkg/options/application.go @@ -21,14 +21,15 @@ type Mac struct { } type Window struct { - Title string - Width, Height int - AlwaysOnTop bool - URL string - DisableResize bool - Resizable bool - MinWidth int - MinHeight int - MaxWidth int - MaxHeight int + Title string + Width, Height int + AlwaysOnTop bool + URL string + DisableResize bool + Resizable bool + MinWidth int + MinHeight int + MaxWidth int + MaxHeight int + EnableDevTools bool } From ab976e56af6480659b88af9c552c93b5d3299405 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 7 Dec 2022 23:58:45 +1100 Subject: [PATCH 05/85] Support ExecJS --- exp/examples/basic/main.go | 3 +++ exp/pkg/application/window.go | 8 ++++++++ exp/pkg/application/window_darwin.go | 17 +++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/exp/examples/basic/main.go b/exp/examples/basic/main.go index f85aceaf2..7008e0564 100644 --- a/exp/examples/basic/main.go +++ b/exp/examples/basic/main.go @@ -53,6 +53,9 @@ func main() { myWindow2.NavigateToURL("https://wails.io") myWindow.SetMinSize(600, 600) myWindow.SetMaxSize(650, 650) + time.Sleep(3 * time.Second) + myWindow.ExecJS("window.location.href = 'https://duckduckgo.com'") + }() err := app.Run() diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index f275ad03e..aa62f07ed 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -12,6 +12,7 @@ type windowImpl interface { setMinSize(width, height int) setMaxSize(width, height int) enableDevTools() + execJS(js string) } type Window struct { @@ -109,3 +110,10 @@ func (w *Window) EnableDevTools() { } w.impl.enableDevTools() } + +func (w *Window) ExecJS(js string) { + if w.impl == nil { + return + } + w.impl.execJS(js) +} diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index 145dc142d..3bb7b1a57 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -136,6 +136,19 @@ void windowEnableDevTools(void* nsWindow) { [delegate.webView.configuration.preferences setValue:@YES forKey:@"developerExtrasEnabled"]; }); } + +// Execute JS in NSWindow +void windowExecJS(void* nsWindow, char* js) { + // Execute JS on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + // Get window delegate + WindowDelegate* delegate = (WindowDelegate*)[(NSWindow*)nsWindow delegate]; + // Execute JS in webview + [delegate.webView evaluateJavaScript:[NSString stringWithUTF8String:js] completionHandler:nil]; + free(js); + }); +} + */ import "C" import ( @@ -149,6 +162,10 @@ type macosWindow struct { options *options.Window } +func (w *macosWindow) execJS(js string) { + C.windowExecJS(w.nsWindow, C.CString(js)) +} + func (w *macosWindow) navigateToURL(url string) { C.navigationLoadURL(w.nsWindow, C.CString(url)) } From cb9df61a98c9aad5d984d79d67c7e68e405302aa Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Thu, 8 Dec 2022 07:47:04 +1100 Subject: [PATCH 06/85] Support MacBackdrop type Fix devtools window error --- exp/examples/basic/main.go | 6 +-- exp/pkg/application/window_darwin.go | 73 ++++++++++++++++++++++++++-- exp/pkg/options/application.go | 14 ++++++ 3 files changed, 87 insertions(+), 6 deletions(-) diff --git a/exp/examples/basic/main.go b/exp/examples/basic/main.go index 7008e0564..38bf8da09 100644 --- a/exp/examples/basic/main.go +++ b/exp/examples/basic/main.go @@ -26,13 +26,15 @@ func main() { Width: 600, Height: 400, AlwaysOnTop: false, - URL: "https://google.com", DisableResize: false, MinWidth: 100, MinHeight: 100, MaxWidth: 1000, MaxHeight: 1000, EnableDevTools: true, + Mac: &options.MacWindow{ + Backdrop: options.MacBackdropNormal, + }, }) myWindow2 := app.NewWindow(&options.Window{ @@ -53,8 +55,6 @@ func main() { myWindow2.NavigateToURL("https://wails.io") myWindow.SetMinSize(600, 600) myWindow.SetMaxSize(650, 650) - time.Sleep(3 * time.Second) - myWindow.ExecJS("window.location.href = 'https://duckduckgo.com'") }() diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index 3bb7b1a57..5b9552e04 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -19,22 +19,38 @@ void* windowNew(int width, int height) { styleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask backing:NSBackingStoreBuffered defer:NO]; + // Create delegate WindowDelegate* delegate = [[WindowDelegate alloc] init]; // Set delegate [window setDelegate:delegate]; + // Add NSView to window + NSView* view = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, width-1, height-1)]; + [view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + [window setContentView:view]; + // Embed wkwebview in window NSRect frame = NSMakeRect(0, 0, width, height); WKWebViewConfiguration* config = [[WKWebViewConfiguration alloc] init]; WKWebView* webView = [[WKWebView alloc] initWithFrame:frame configuration:config]; - [window setContentView:webView]; + [view addSubview:webView]; delegate.webView = webView; delegate.hideOnClose = false; return window; } +// Make NSWindow transparent +void windowSetTransparent(void* nsWindow) { + // On main thread + dispatch_async(dispatch_get_main_queue(), ^{ + NSWindow* window = (NSWindow*)nsWindow; + [window setOpaque:NO]; + [window setBackgroundColor:[NSColor clearColor]]; + }); +} + // Set the title of the NSWindow void windowSetTitle(void* nsWindow, char* title) { // Set window title on main thread @@ -60,12 +76,18 @@ void windowSetSize(void* nsWindow, int width, int height) { // Show the NSWindow void windowShow(void* nsWindow) { - [(NSWindow*)nsWindow makeKeyAndOrderFront:nil]; + // Show window on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + [(NSWindow*)nsWindow makeKeyAndOrderFront:nil]; + }); } // Hide the NSWindow void windowHide(void* nsWindow) { - [(NSWindow*)nsWindow orderOut:nil]; + // Hide window on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + [(NSWindow*)nsWindow orderOut:nil]; + }); } // Set NSWindow always on top @@ -149,6 +171,41 @@ void windowExecJS(void* nsWindow, char* js) { }); } +// Make NSWindow backdrop translucent +void windowSetTranslucent(void* nsWindow) { + // Set window transparent on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + + // Get window + NSWindow* window = (NSWindow*)nsWindow; + + // Get window delegate + WindowDelegate* delegate = (WindowDelegate*)[(NSWindow*)nsWindow delegate]; + + id contentView = [window contentView]; + NSVisualEffectView *effectView = [NSVisualEffectView alloc]; + NSRect bounds = [contentView bounds]; + [effectView initWithFrame:bounds]; + [effectView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + [effectView setBlendingMode:NSVisualEffectBlendingModeBehindWindow]; + [effectView setState:NSVisualEffectStateActive]; + [contentView addSubview:effectView positioned:NSWindowBelow relativeTo:nil]; + }); +} + +// Make webview background transparent +void webviewSetTransparent(void* nsWindow) { + // Set webview transparent on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + // Get window delegate + WindowDelegate* delegate = (WindowDelegate*)[(NSWindow*)nsWindow delegate]; + // Set webview background transparent + [delegate.webView setValue:@YES forKey:@"drawsTransparentBackground"]; + }); +} + + + */ import "C" import ( @@ -217,6 +274,16 @@ func (w *macosWindow) run() error { if w.options.EnableDevTools { w.enableDevTools() } + if w.options.Mac != nil { + switch w.options.Mac.Backdrop { + case options.MacBackdropTransparent: + C.windowSetTransparent(w.nsWindow) + C.webviewSetTransparent(w.nsWindow) + case options.MacBackdropTranslucent: + C.windowSetTranslucent(w.nsWindow) + C.webviewSetTransparent(w.nsWindow) + } + } C.windowShow(w.nsWindow) return nil } diff --git a/exp/pkg/options/application.go b/exp/pkg/options/application.go index 624087bb7..a06a305d3 100644 --- a/exp/pkg/options/application.go +++ b/exp/pkg/options/application.go @@ -32,4 +32,18 @@ type Window struct { MaxWidth int MaxHeight int EnableDevTools bool + Mac *MacWindow +} + +type MacBackdrop int + +const ( + MacBackdropNormal MacBackdrop = iota + MacBackdropTransparent + MacBackdropTranslucent +) + +// MacWindow contains macOS specific options +type MacWindow struct { + Backdrop MacBackdrop } From 508bbb4fb432d54810500065c4036c39fac55f64 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Thu, 8 Dec 2022 17:25:39 +1100 Subject: [PATCH 07/85] Support Min/Max/Fullscreen, BackgroundColour --- exp/examples/basic/main.go | 27 +++-- exp/go.mod | 5 +- exp/go.sum | 2 + exp/pkg/application/application.go | 33 +++++ exp/pkg/application/application.h | 7 +- exp/pkg/application/application_darwin.go | 18 +-- exp/pkg/application/window.go | 79 +++++++++++- exp/pkg/application/window_darwin.go | 140 +++++++++++++++++++++- exp/pkg/options/application.go | 39 ++++-- 9 files changed, 307 insertions(+), 43 deletions(-) diff --git a/exp/examples/basic/main.go b/exp/examples/basic/main.go index 38bf8da09..864d536f7 100644 --- a/exp/examples/basic/main.go +++ b/exp/examples/basic/main.go @@ -22,18 +22,25 @@ func main() { println("TERMINATION!!") }) myWindow := app.NewWindow(&options.Window{ - Title: "Basic", - Width: 600, - Height: 400, - AlwaysOnTop: false, - DisableResize: false, - MinWidth: 100, - MinHeight: 100, - MaxWidth: 1000, - MaxHeight: 1000, + Title: "Basic", + Width: 600, + Height: 400, + AlwaysOnTop: false, + DisableResize: false, + //MinWidth: 100, + //MinHeight: 100, + //MaxWidth: 1000, + //MaxHeight: 1000, EnableDevTools: true, + BackgroundColour: &options.RGBA{ + Red: 255, + Green: 255, + Blue: 255, + Alpha: 30, + }, + StartState: options.WindowStateMaximised, Mac: &options.MacWindow{ - Backdrop: options.MacBackdropNormal, + Backdrop: options.MacBackdropTranslucent, }, }) diff --git a/exp/go.mod b/exp/go.mod index 1969eb348..6b99bc397 100644 --- a/exp/go.mod +++ b/exp/go.mod @@ -2,4 +2,7 @@ module github.com/wailsapp/wails/exp go 1.19 -require github.com/leaanthony/clir v1.3.0 +require ( + github.com/gofrs/uuid v4.3.1+incompatible + github.com/leaanthony/clir v1.3.0 +) diff --git a/exp/go.sum b/exp/go.sum index ec90627a4..119fea365 100644 --- a/exp/go.sum +++ b/exp/go.sum @@ -1,2 +1,4 @@ +github.com/gofrs/uuid v4.3.1+incompatible h1:0/KbAdpx3UXAx1kEOWHJeOkpbgRFGHVgv+CFIY7dBJI= +github.com/gofrs/uuid v4.3.1+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/leaanthony/clir v1.3.0 h1:L9nPDWrmc/qU9UWZZvRaFajWYuO0np9V5p+5gxyYno0= github.com/leaanthony/clir v1.3.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index 7b03bf82f..39474eeb8 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -1,5 +1,6 @@ package application +import "C" import "github.com/wailsapp/wails/exp/pkg/options" type Application interface { @@ -11,6 +12,9 @@ type App struct { systemEventListeners map[string][]func() windows []*Window + + // Running + running bool } func (a *App) On(s string, callback func()) { @@ -20,5 +24,34 @@ func (a *App) On(s string, callback func()) { func (a *App) NewWindow(options *options.Window) *Window { newWindow := NewWindow(options) a.windows = append(a.windows, newWindow) + + if a.running { + err := newWindow.Run() + if err != nil { + panic(err) + } + } + return newWindow } + +func (a *App) Run() error { + + a.running = true + go func() { + for { + event := <-systemEvents + a.handleSystemEvent(event) + } + }() + + // run windows + for _, window := range a.windows { + err := window.Run() + if err != nil { + return err + } + } + + return a.run() +} diff --git a/exp/pkg/application/application.h b/exp/pkg/application/application.h index 93f931fb5..6efc1825a 100644 --- a/exp/pkg/application/application.h +++ b/exp/pkg/application/application.h @@ -1,5 +1,10 @@ //go:build darwin +#ifndef application_h +#define application_h + void Init(void); void Run(void); -void SetActivationPolicy(int policy); \ No newline at end of file +void SetActivationPolicy(int policy); + +#endif \ No newline at end of file diff --git a/exp/pkg/application/application_darwin.go b/exp/pkg/application/application_darwin.go index c30a60864..fdef9c4b2 100644 --- a/exp/pkg/application/application_darwin.go +++ b/exp/pkg/application/application_darwin.go @@ -22,23 +22,7 @@ func New(options *options.Application) *App { } } -func (a *App) Run() error { - - go func() { - for { - event := <-systemEvents - a.handleSystemEvent(event) - } - }() - - // run windows - for _, window := range a.windows { - err := window.Run() - if err != nil { - return err - } - } - +func (a *App) run() error { C.Run() return nil } diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index aa62f07ed..0db8cfbd5 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -1,6 +1,10 @@ package application -import "github.com/wailsapp/wails/exp/pkg/options" +import ( + "sync/atomic" + + "github.com/wailsapp/wails/exp/pkg/options" +) type windowImpl interface { setTitle(title string) @@ -13,15 +17,29 @@ type windowImpl interface { setMaxSize(width, height int) enableDevTools() execJS(js string) + setMaximised() + setMinimised() + setFullscreen() + isMinimised() bool + isMaximised() bool + isFullscreen() bool + restore() + setBackgroundColor(color *options.RGBA) } type Window struct { options *options.Window impl windowImpl + id uint64 } +var windowID atomic.Uint64 + func NewWindow(options *options.Window) *Window { + id := windowID.Load() + windowID.Add(1) return &Window{ + id: id, options: options, } } @@ -117,3 +135,62 @@ func (w *Window) ExecJS(js string) { } w.impl.execJS(js) } + +// Set Maximized +func (w *Window) SetMaximized() { + if w.impl == nil { + w.options.StartState = options.WindowStateMaximised + return + } + w.impl.setMaximised() +} + +// Set Minimized +func (w *Window) SetMinimized() { + if w.impl == nil { + w.options.StartState = options.WindowStateMinimised + return + } + w.impl.setMinimised() +} + +// Set Fullscreen +func (w *Window) SetFullscreen() { + if w.impl == nil { + w.options.StartState = options.WindowStateFullscreen + return + } + w.impl.setFullscreen() +} + +// IsMinimised returns true if the window is minimised +func (w *Window) IsMinimised() bool { + if w.impl == nil { + return false + } + return w.impl.isMinimised() +} + +// IsMaximised returns true if the window is maximised +func (w *Window) IsMaximised() bool { + if w.impl == nil { + return false + } + return w.impl.isMaximised() +} + +// IsFullscreen returns true if the window is fullscreen +func (w *Window) IsFullscreen() bool { + if w.impl == nil { + return false + } + return w.impl.isFullscreen() +} + +func (w *Window) SetBackgroundColor(color *options.RGBA) { + if w.impl == nil { + w.options.BackgroundColour = color + return + } + w.impl.setBackgroundColor(color) +} diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index 5b9552e04..1241b4024 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -200,10 +200,94 @@ void webviewSetTransparent(void* nsWindow) { // Get window delegate WindowDelegate* delegate = (WindowDelegate*)[(NSWindow*)nsWindow delegate]; // Set webview background transparent - [delegate.webView setValue:@YES forKey:@"drawsTransparentBackground"]; + [delegate.webView setValue:@NO forKey:@"drawsBackground"]; }); } +// Set webview background color +void webviewSetBackgroundColor(void* nsWindow, int r, int g, int b, int alpha) { + // Set webview background color on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + // Get window delegate + WindowDelegate* delegate = (WindowDelegate*)[(NSWindow*)nsWindow delegate]; + // Set webview background color + [delegate.webView setValue:[NSColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:alpha/255.0] forKey:@"backgroundColor"]; + }); +} + +// Set Window maximised +void windowSetMaximised(void* nsWindow) { + // Set window maximized on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + [(NSWindow*)nsWindow zoom:nil]; + }); +} + +// Set Window fullscreen +void windowSetFullscreen(void* nsWindow) { + // Set window fullscreen on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + [(NSWindow*)nsWindow toggleFullScreen:nil]; + }); +} + +// Set Window Minimised +void windowSetMinimised(void* nsWindow) { + // Set window minimised on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + // Get screen that the window is on + NSScreen* screen = [(NSWindow*)nsWindow screen]; + NSRect screenRect = [screen frame]; + // Set window to top left corner + [(NSWindow*)nsWindow setFrame:NSMakeRect(0, screenRect.size.height, 0, 0) display:YES]; + }); +} + +// restore window to normal size +void windowRestore(void* nsWindow) { + // Set window normal on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + // If window is fullscreen + if([(NSWindow*)nsWindow styleMask] & NSFullScreenWindowMask) { + [(NSWindow*)nsWindow toggleFullScreen:nil]; + } + // If window is maximised + if([(NSWindow*)nsWindow isZoomed]) { + [(NSWindow*)nsWindow zoom:nil]; + } + // If window in minimised + if([(NSWindow*)nsWindow isMiniaturized]) { + [(NSWindow*)nsWindow deminiaturize:nil]; + } + }); +} + +bool windowIsMaximised(void* nsWindow) { + // Get window maximized on main thread + __block bool maximized = false; + dispatch_sync(dispatch_get_main_queue(), ^{ + maximized = [(NSWindow*)nsWindow isZoomed]; + }); + return maximized; +} + +bool windowIsFullscreen(void* nsWindow) { + // Get window fullscreen on main thread + __block bool fullscreen = false; + dispatch_sync(dispatch_get_main_queue(), ^{ + fullscreen = [(NSWindow*)nsWindow styleMask] & NSFullScreenWindowMask; + }); + return fullscreen; +} + +bool windowIsMinimised(void* nsWindow) { + // Get window minimised on main thread + __block bool minimised = false; + dispatch_sync(dispatch_get_main_queue(), ^{ + minimised = [(NSWindow*)nsWindow isMiniaturized]; + }); + return minimised; +} */ @@ -215,10 +299,44 @@ import ( ) type macosWindow struct { + id uint64 nsWindow unsafe.Pointer options *options.Window } +func (w *macosWindow) isMinimised() bool { + return C.windowIsMinimised(w.nsWindow) == C.bool(true) +} + +func (w *macosWindow) isMaximised() bool { + return C.windowIsMaximised(w.nsWindow) == C.bool(true) +} + +func (w *macosWindow) isFullscreen() bool { + return C.windowIsFullscreen(w.nsWindow) == C.bool(true) +} + +func (w *macosWindow) restore() { + //TODO implement me + panic("implement me") +} + +func (w *macosWindow) setMaximised() { + C.windowSetMaximised(w.nsWindow) +} + +func (w *macosWindow) setMinimised() { + C.windowSetMinimised(w.nsWindow) +} + +func (w *macosWindow) setFullscreen() { + C.windowSetFullscreen(w.nsWindow) +} + +func (w *macosWindow) restoreWindow() { + C.windowRestore(w.nsWindow) +} + func (w *macosWindow) execJS(js string) { C.windowExecJS(w.nsWindow, C.CString(js)) } @@ -274,6 +392,7 @@ func (w *macosWindow) run() error { if w.options.EnableDevTools { w.enableDevTools() } + w.setBackgroundColor(w.options.BackgroundColour) if w.options.Mac != nil { switch w.options.Mac.Backdrop { case options.MacBackdropTransparent: @@ -283,7 +402,26 @@ func (w *macosWindow) run() error { C.windowSetTranslucent(w.nsWindow) C.webviewSetTransparent(w.nsWindow) } + + switch w.options.StartState { + case options.WindowStateMaximised: + w.setMaximised() + case options.WindowStateMinimised: + w.setMinimised() + case options.WindowStateFullscreen: + w.setFullscreen() + + } + } C.windowShow(w.nsWindow) + return nil } + +func (w *macosWindow) setBackgroundColor(colour *options.RGBA) { + if colour == nil { + return + } + C.webviewSetBackgroundColor(w.nsWindow, C.int(colour.Red), C.int(colour.Green), C.int(colour.Blue), C.int(colour.Alpha)) +} diff --git a/exp/pkg/options/application.go b/exp/pkg/options/application.go index a06a305d3..c43b9ac42 100644 --- a/exp/pkg/options/application.go +++ b/exp/pkg/options/application.go @@ -21,18 +21,24 @@ type Mac struct { } type Window struct { - Title string - Width, Height int - AlwaysOnTop bool - URL string - DisableResize bool - Resizable bool - MinWidth int - MinHeight int - MaxWidth int - MaxHeight int - EnableDevTools bool - Mac *MacWindow + Title string + Width, Height int + AlwaysOnTop bool + URL string + DisableResize bool + Resizable bool + MinWidth int + MinHeight int + MaxWidth int + MaxHeight int + EnableDevTools bool + StartState WindowState + Mac *MacWindow + BackgroundColour *RGBA +} + +type RGBA struct { + Red, Green, Blue, Alpha uint8 } type MacBackdrop int @@ -43,6 +49,15 @@ const ( MacBackdropTranslucent ) +type WindowState int + +const ( + WindowStateNormal WindowState = iota + WindowStateMinimised + WindowStateMaximised + WindowStateFullscreen +) + // MacWindow contains macOS specific options type MacWindow struct { Backdrop MacBackdrop From 644655662e311937e9a7e940f1f5c7b5509f9039 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Thu, 8 Dec 2022 18:09:02 +1100 Subject: [PATCH 08/85] Support toolbar config --- exp/examples/basic/main.go | 7 +- exp/pkg/application/window_darwin.go | 97 +++++++++++++++++++++++++++- exp/pkg/options/application.go | 54 ++++++++++++++++ 3 files changed, 156 insertions(+), 2 deletions(-) diff --git a/exp/examples/basic/main.go b/exp/examples/basic/main.go index 864d536f7..40c6fc5f4 100644 --- a/exp/examples/basic/main.go +++ b/exp/examples/basic/main.go @@ -25,7 +25,7 @@ func main() { Title: "Basic", Width: 600, Height: 400, - AlwaysOnTop: false, + AlwaysOnTop: true, DisableResize: false, //MinWidth: 100, //MinHeight: 100, @@ -41,6 +41,7 @@ func main() { StartState: options.WindowStateMaximised, Mac: &options.MacWindow{ Backdrop: options.MacBackdropTranslucent, + TitleBar: options.TitleBarHiddenInset(), }, }) @@ -51,6 +52,10 @@ func main() { AlwaysOnTop: false, URL: "https://google.com", DisableResize: true, + Mac: &options.MacWindow{ + Backdrop: options.MacBackdropTranslucent, + TitleBar: options.TitleBarHidden(), + }, }) go func() { diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index 1241b4024..52a6753f9 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -289,6 +289,90 @@ bool windowIsMinimised(void* nsWindow) { return minimised; } +// Set the titlebar style +void windowSetTitleBarAppearsTransparent(void* nsWindow, bool transparent) { + // Set window titlebar style on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + if( transparent ) { + [(NSWindow*)nsWindow setTitlebarAppearsTransparent:true]; + } else { + [(NSWindow*)nsWindow setTitlebarAppearsTransparent:false]; + } + }); +} + +// Set window fullsize content view +void windowSetFullSizeContent(void* nsWindow, bool fullSize) { + // Set window fullsize content view on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + if( fullSize ) { + [(NSWindow*)nsWindow setStyleMask:[(NSWindow*)nsWindow styleMask] | NSWindowStyleMaskFullSizeContentView]; + } else { + [(NSWindow*)nsWindow setStyleMask:[(NSWindow*)nsWindow styleMask] & ~NSWindowStyleMaskFullSizeContentView]; + } + }); +} + +// Set Hide Titlebar +void windowSetHideTitleBar(void* nsWindow, bool hideTitlebar) { + // Set window titlebar hidden on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + if( hideTitlebar ) { + [(NSWindow*)nsWindow setStyleMask:[(NSWindow*)nsWindow styleMask] & ~NSWindowStyleMaskTitled]; + } else { + [(NSWindow*)nsWindow setStyleMask:[(NSWindow*)nsWindow styleMask] | NSWindowStyleMaskTitled]; + } + }); +} + +// Set Hide Title in Titlebar +void windowSetHideTitle(void* nsWindow, bool hideTitle) { + // Set window titlebar hidden on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + if( hideTitle ) { + [(NSWindow*)nsWindow setTitleVisibility:NSWindowTitleHidden]; + } else { + [(NSWindow*)nsWindow setTitleVisibility:NSWindowTitleVisible]; + } + }); +} + +// Set Window use toolbar +void windowSetUseToolbar(void* nsWindow, bool useToolbar) { + // Set window use toolbar on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + // get main window + NSWindow* window = (NSWindow*)nsWindow; + if( useToolbar ) { + NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"wails.toolbar"]; + [toolbar autorelease]; + [window setToolbar:toolbar]; + } else { + [window setToolbar:nil]; + } + }); +} + +// Set Hide Toolbar Separator +void windowSetHideToolbarSeparator(void* nsWindow, bool hideSeparator) { + // Set window hide toolbar separator on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + // get main window + NSWindow* window = (NSWindow*)nsWindow; + // get toolbar + NSToolbar* toolbar = [window toolbar]; + // Return if toolbar nil + if( toolbar == nil ) { + return; + } + if( hideSeparator ) { + [toolbar setShowsBaselineSeparator:false]; + } else { + [toolbar setShowsBaselineSeparator:true]; + } + }); +} + */ import "C" @@ -394,7 +478,8 @@ func (w *macosWindow) run() error { } w.setBackgroundColor(w.options.BackgroundColour) if w.options.Mac != nil { - switch w.options.Mac.Backdrop { + macOptions := w.options.Mac + switch macOptions.Backdrop { case options.MacBackdropTransparent: C.windowSetTransparent(w.nsWindow) C.webviewSetTransparent(w.nsWindow) @@ -403,6 +488,16 @@ func (w *macosWindow) run() error { C.webviewSetTransparent(w.nsWindow) } + if macOptions.TitleBar != nil { + titleBarOptions := macOptions.TitleBar + C.windowSetTitleBarAppearsTransparent(w.nsWindow, C.bool(titleBarOptions.AppearsTransparent)) + C.windowSetHideTitleBar(w.nsWindow, C.bool(titleBarOptions.Hide)) + C.windowSetHideTitle(w.nsWindow, C.bool(titleBarOptions.HideTitle)) + C.windowSetFullSizeContent(w.nsWindow, C.bool(titleBarOptions.FullSizeContent)) + C.windowSetUseToolbar(w.nsWindow, C.bool(titleBarOptions.UseToolbar)) + C.windowSetHideToolbarSeparator(w.nsWindow, C.bool(titleBarOptions.HideToolbarSeparator)) + } + switch w.options.StartState { case options.WindowStateMaximised: w.setMaximised() diff --git a/exp/pkg/options/application.go b/exp/pkg/options/application.go index c43b9ac42..88a1cb597 100644 --- a/exp/pkg/options/application.go +++ b/exp/pkg/options/application.go @@ -61,4 +61,58 @@ const ( // MacWindow contains macOS specific options type MacWindow struct { Backdrop MacBackdrop + TitleBar *TitleBar +} + +// TitleBar contains options for the Mac titlebar +type TitleBar struct { + AppearsTransparent bool + Hide bool + HideTitle bool + FullSizeContent bool + UseToolbar bool + HideToolbarSeparator bool +} + +// TitleBarDefault results in the default Mac Titlebar +func TitleBarDefault() *TitleBar { + return &TitleBar{ + AppearsTransparent: false, + Hide: false, + HideTitle: false, + FullSizeContent: false, + UseToolbar: false, + HideToolbarSeparator: false, + } +} + +// Credit: Comments from Electron site + +// TitleBarHidden results in a hidden title bar and a full size content window, +// yet the title bar still has the standard window controls (“traffic lights”) +// in the top left. +func TitleBarHidden() *TitleBar { + return &TitleBar{ + AppearsTransparent: true, + Hide: false, + HideTitle: true, + FullSizeContent: true, + UseToolbar: false, + HideToolbarSeparator: false, + } +} + +// TitleBarHiddenInset results in a hidden title bar with an alternative look where +// the traffic light buttons are slightly more inset from the window edge. +func TitleBarHiddenInset() *TitleBar { + + return &TitleBar{ + AppearsTransparent: true, + Hide: false, + HideTitle: true, + FullSizeContent: true, + UseToolbar: true, + HideToolbarSeparator: true, + } + } From 1872672d0c0be5e849fbad2bcffeddc3b967dbda Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Thu, 8 Dec 2022 18:20:04 +1100 Subject: [PATCH 09/85] Support appearance --- exp/examples/basic/main.go | 5 +++-- exp/pkg/application/window_darwin.go | 19 +++++++++++++++++++ exp/pkg/options/application.go | 27 +++++++++++++++++++++++++-- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/exp/examples/basic/main.go b/exp/examples/basic/main.go index 40c6fc5f4..297cd7c8f 100644 --- a/exp/examples/basic/main.go +++ b/exp/examples/basic/main.go @@ -40,8 +40,9 @@ func main() { }, StartState: options.WindowStateMaximised, Mac: &options.MacWindow{ - Backdrop: options.MacBackdropTranslucent, - TitleBar: options.TitleBarHiddenInset(), + Backdrop: options.MacBackdropTranslucent, + TitleBar: options.TitleBarHiddenInset(), + Appearance: options.NSAppearanceNameDarkAqua, }, }) diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index 52a6753f9..c40eaf419 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -373,6 +373,21 @@ void windowSetHideToolbarSeparator(void* nsWindow, bool hideSeparator) { }); } +// Set Window appearance type +void windowSetAppearanceTypeByName(void* nsWindow, const char *appearanceName) { + // Set window appearance type on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + // get main window + NSWindow* window = (NSWindow*)nsWindow; + // set window appearance type by name + // Convert appearance name to NSString + NSString* appearanceNameString = [NSString stringWithUTF8String:appearanceName]; + // Set appearance + [window setAppearance:[NSAppearance appearanceNamed:appearanceNameString]]; + + free((void*)appearanceName); + }); +} */ import "C" @@ -498,6 +513,10 @@ func (w *macosWindow) run() error { C.windowSetHideToolbarSeparator(w.nsWindow, C.bool(titleBarOptions.HideToolbarSeparator)) } + if macOptions.Appearance != "" { + C.windowSetAppearanceTypeByName(w.nsWindow, C.CString(string(macOptions.Appearance))) + } + switch w.options.StartState { case options.WindowStateMaximised: w.setMaximised() diff --git a/exp/pkg/options/application.go b/exp/pkg/options/application.go index 88a1cb597..a8b17c21f 100644 --- a/exp/pkg/options/application.go +++ b/exp/pkg/options/application.go @@ -60,8 +60,9 @@ const ( // MacWindow contains macOS specific options type MacWindow struct { - Backdrop MacBackdrop - TitleBar *TitleBar + Backdrop MacBackdrop + TitleBar *TitleBar + Appearance MacAppearanceType } // TitleBar contains options for the Mac titlebar @@ -116,3 +117,25 @@ func TitleBarHiddenInset() *TitleBar { } } + +// MacAppearanceType is a type of Appearance for Cocoa windows +type MacAppearanceType string + +const ( + // DefaultAppearance uses the default system value + DefaultAppearance MacAppearanceType = "" + // NSAppearanceNameAqua - The standard light system appearance. + NSAppearanceNameAqua MacAppearanceType = "NSAppearanceNameAqua" + // NSAppearanceNameDarkAqua - The standard dark system appearance. + NSAppearanceNameDarkAqua MacAppearanceType = "NSAppearanceNameDarkAqua" + // NSAppearanceNameVibrantLight - The light vibrant appearance + NSAppearanceNameVibrantLight MacAppearanceType = "NSAppearanceNameVibrantLight" + // NSAppearanceNameAccessibilityHighContrastAqua - A high-contrast version of the standard light system appearance. + NSAppearanceNameAccessibilityHighContrastAqua MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastAqua" + // NSAppearanceNameAccessibilityHighContrastDarkAqua - A high-contrast version of the standard dark system appearance. + NSAppearanceNameAccessibilityHighContrastDarkAqua MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastDarkAqua" + // NSAppearanceNameAccessibilityHighContrastVibrantLight - A high-contrast version of the light vibrant appearance. + NSAppearanceNameAccessibilityHighContrastVibrantLight MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastVibrantLight" + // NSAppearanceNameAccessibilityHighContrastVibrantDark - A high-contrast version of the dark vibrant appearance. + NSAppearanceNameAccessibilityHighContrastVibrantDark MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastVibrantDark" +) From 0257362a868484eb3861906d0ba840d213677932 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Thu, 8 Dec 2022 23:06:27 +1100 Subject: [PATCH 10/85] Support per-window message dispatching --- exp/examples/basic/main.go | 2 -- exp/pkg/application/application.go | 41 ++++++++++++++++++++--- exp/pkg/application/application_darwin.go | 13 ++++++- exp/pkg/application/window.go | 29 ++++++++++++---- exp/pkg/application/window_darwin.go | 19 ++++++++--- exp/pkg/application/window_delegate.h | 5 ++- exp/pkg/application/window_delegate.m | 23 +++++++++++++ 7 files changed, 112 insertions(+), 20 deletions(-) diff --git a/exp/examples/basic/main.go b/exp/examples/basic/main.go index 297cd7c8f..ad1284142 100644 --- a/exp/examples/basic/main.go +++ b/exp/examples/basic/main.go @@ -41,7 +41,6 @@ func main() { StartState: options.WindowStateMaximised, Mac: &options.MacWindow{ Backdrop: options.MacBackdropTranslucent, - TitleBar: options.TitleBarHiddenInset(), Appearance: options.NSAppearanceNameDarkAqua, }, }) @@ -55,7 +54,6 @@ func main() { DisableResize: true, Mac: &options.MacWindow{ Backdrop: options.MacBackdropTranslucent, - TitleBar: options.TitleBarHidden(), }, }) diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index 39474eeb8..55668f494 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -1,7 +1,18 @@ package application -import "C" -import "github.com/wailsapp/wails/exp/pkg/options" +import ( + "log" + + "github.com/wailsapp/wails/exp/pkg/options" +) + +// Messages sent from javascript get routed here +type windowMessage struct { + windowId uint + message string +} + +var messageBuffer = make(chan *windowMessage) type Application interface { Run() error @@ -11,7 +22,7 @@ type App struct { options *options.Application systemEventListeners map[string][]func() - windows []*Window + windows map[uint]*Window // Running running bool @@ -23,8 +34,11 @@ func (a *App) On(s string, callback func()) { func (a *App) NewWindow(options *options.Window) *Window { newWindow := NewWindow(options) - a.windows = append(a.windows, newWindow) - + id := newWindow.id + if a.windows == nil { + a.windows = make(map[uint]*Window) + } + a.windows[id] = newWindow if a.running { err := newWindow.Run() if err != nil { @@ -44,6 +58,12 @@ func (a *App) Run() error { a.handleSystemEvent(event) } }() + go func() { + for { + event := <-messageBuffer + a.handleMessage(event) + } + }() // run windows for _, window := range a.windows { @@ -55,3 +75,14 @@ func (a *App) Run() error { return a.run() } + +func (a *App) handleMessage(event *windowMessage) { + // Get window from window map + window, ok := a.windows[event.windowId] + if !ok { + log.Printf("Window #%d not found", event.windowId) + return + } + // Get callback from window + window.handleMessage(event.message) +} diff --git a/exp/pkg/application/application_darwin.go b/exp/pkg/application/application_darwin.go index fdef9c4b2..19dc7e264 100644 --- a/exp/pkg/application/application_darwin.go +++ b/exp/pkg/application/application_darwin.go @@ -7,9 +7,12 @@ package application #cgo CFLAGS: -x objective-c #cgo LDFLAGS: -framework Cocoa -mmacosx-version-min=10.13 #include "application.h" +#include */ import "C" -import "github.com/wailsapp/wails/exp/pkg/options" +import ( + "github.com/wailsapp/wails/exp/pkg/options" +) func New(options *options.Application) *App { C.Init() @@ -42,3 +45,11 @@ func systemEventHandler(name *C.char) { goString := C.GoString(name) systemEvents <- goString } + +//export processMessage +func processMessage(windowID C.uint, message *C.char) { + messageBuffer <- &windowMessage{ + windowId: uint(windowID), + message: C.GoString(message), + } +} diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index 0db8cfbd5..ea785e6e0 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -1,7 +1,8 @@ package application import ( - "sync/atomic" + "fmt" + "sync" "github.com/wailsapp/wails/exp/pkg/options" ) @@ -30,16 +31,22 @@ type windowImpl interface { type Window struct { options *options.Window impl windowImpl - id uint64 + id uint } -var windowID atomic.Uint64 +var windowID uint +var windowIDLock sync.RWMutex + +func getWindowID() uint { + windowIDLock.Lock() + defer windowIDLock.Unlock() + windowID++ + return windowID +} func NewWindow(options *options.Window) *Window { - id := windowID.Load() - windowID.Add(1) return &Window{ - id: id, + id: getWindowID(), options: options, } } @@ -62,7 +69,7 @@ func (w *Window) SetSize(width, height int) { } func (w *Window) Run() error { - w.impl = newWindowImpl(w.options) + w.impl = newWindowImpl(w.id, w.options) return w.impl.run() } @@ -194,3 +201,11 @@ func (w *Window) SetBackgroundColor(color *options.RGBA) { } w.impl.setBackgroundColor(color) } + +func (w *Window) handleMessage(message string) { + fmt.Printf("[window %d] %s", w.id, message) + // Check for special messages + if message == "test" { + w.SetTitle("Hello World") + } +} diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index c40eaf419..f2ff9bd83 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -14,7 +14,7 @@ package application // Create a new Window -void* windowNew(int width, int height) { +void* windowNew(unsigned int id, int width, int height) { NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, width-1, height-1) styleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask backing:NSBackingStoreBuffered @@ -24,6 +24,7 @@ void* windowNew(int width, int height) { WindowDelegate* delegate = [[WindowDelegate alloc] init]; // Set delegate [window setDelegate:delegate]; + delegate.windowId = id; // Add NSView to window NSView* view = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, width-1, height-1)]; @@ -33,10 +34,19 @@ void* windowNew(int width, int height) { // Embed wkwebview in window NSRect frame = NSMakeRect(0, 0, width, height); WKWebViewConfiguration* config = [[WKWebViewConfiguration alloc] init]; + config.suppressesIncrementalRendering = true; + config.applicationNameForUserAgent = @"wails.io"; + + // Setup user content controller + WKUserContentController* userContentController = [WKUserContentController new]; + [userContentController addScriptMessageHandler:delegate name:@"external"]; + config.userContentController = userContentController; + WKWebView* webView = [[WKWebView alloc] initWithFrame:frame configuration:config]; [view addSubview:webView]; delegate.webView = webView; + delegate.hideOnClose = false; return window; } @@ -398,7 +408,7 @@ import ( ) type macosWindow struct { - id uint64 + id uint nsWindow unsafe.Pointer options *options.Window } @@ -448,8 +458,9 @@ func (w *macosWindow) setAlwaysOnTop(alwaysOnTop bool) { C.windowSetAlwaysOnTop(w.nsWindow, C.bool(alwaysOnTop)) } -func newWindowImpl(options *options.Window) *macosWindow { +func newWindowImpl(id uint, options *options.Window) *macosWindow { result := &macosWindow{ + id: id, options: options, } return result @@ -479,7 +490,7 @@ func (w *macosWindow) enableDevTools() { } func (w *macosWindow) run() error { - w.nsWindow = C.windowNew(C.int(w.options.Width), C.int(w.options.Height)) + w.nsWindow = C.windowNew(C.uint(w.id), C.int(w.options.Width), C.int(w.options.Height)) w.setTitle(w.options.Title) w.setAlwaysOnTop(w.options.AlwaysOnTop) w.setResizable(!w.options.DisableResize) diff --git a/exp/pkg/application/window_delegate.h b/exp/pkg/application/window_delegate.h index 26ca44643..f6e91c15c 100644 --- a/exp/pkg/application/window_delegate.h +++ b/exp/pkg/application/window_delegate.h @@ -7,10 +7,13 @@ #import #import -@interface WindowDelegate : NSObject +extern void processMessage(unsigned int, const char*); + +@interface WindowDelegate : NSObject @property bool hideOnClose; @property (retain) WKWebView* webView; +@property unsigned int windowId; @end diff --git a/exp/pkg/application/window_delegate.m b/exp/pkg/application/window_delegate.m index 2bf7e2324..41774038d 100644 --- a/exp/pkg/application/window_delegate.m +++ b/exp/pkg/application/window_delegate.m @@ -19,5 +19,28 @@ return true; } +// Handle script messages from the external bridge +- (void)userContentController:(nonnull WKUserContentController *)userContentController didReceiveScriptMessage:(nonnull WKScriptMessage *)message { + NSString *m = message.body; + + /* + // TODO: Check for drag + if ( [m isEqualToString:@"drag"] ) { + if( [self IsFullScreen] ) { + return; + } + if( self.mouseEvent != nil ) { + [self.mainWindow performWindowDragWithEvent:self.mouseEvent]; + } + return; + } + */ + + const char *_m = [m UTF8String]; + + processMessage(self.windowId, _m); +} + + @end From 85abb1122f93f4585338ef04423bd952f59434dc Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Fri, 9 Dec 2022 07:47:47 +1100 Subject: [PATCH 11/85] Add main thread dispatching Make `window.Run` operate on main thread --- exp/examples/basic/main.go | 27 ++++--- exp/pkg/application/application.go | 10 +-- exp/pkg/application/mainthread.go | 41 +++++++++++ exp/pkg/application/mainthread_darwin.go | 20 +++++ exp/pkg/application/window.go | 6 +- exp/pkg/application/window_darwin.go | 94 ++++++++++++------------ 6 files changed, 129 insertions(+), 69 deletions(-) create mode 100644 exp/pkg/application/mainthread.go create mode 100644 exp/pkg/application/mainthread_darwin.go diff --git a/exp/examples/basic/main.go b/exp/examples/basic/main.go index ad1284142..bea07f89f 100644 --- a/exp/examples/basic/main.go +++ b/exp/examples/basic/main.go @@ -45,17 +45,22 @@ func main() { }, }) - myWindow2 := app.NewWindow(&options.Window{ - Title: "#2", - Width: 1024, - Height: 768, - AlwaysOnTop: false, - URL: "https://google.com", - DisableResize: true, - Mac: &options.MacWindow{ - Backdrop: options.MacBackdropTranslucent, - }, - }) + var myWindow2 *application.Window + go func() { + time.Sleep(2 * time.Second) + myWindow2 = app.NewWindow(&options.Window{ + Title: "#2", + Width: 1024, + Height: 768, + AlwaysOnTop: false, + URL: "https://google.com", + DisableResize: true, + Mac: &options.MacWindow{ + Backdrop: options.MacBackdropTranslucent, + }, + }) + + }() go func() { time.Sleep(5 * time.Second) diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index 55668f494..9dce249ee 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -40,10 +40,7 @@ func (a *App) NewWindow(options *options.Window) *Window { } a.windows[id] = newWindow if a.running { - err := newWindow.Run() - if err != nil { - panic(err) - } + newWindow.Run() } return newWindow @@ -67,10 +64,7 @@ func (a *App) Run() error { // run windows for _, window := range a.windows { - err := window.Run() - if err != nil { - return err - } + go window.Run() } return a.run() diff --git a/exp/pkg/application/mainthread.go b/exp/pkg/application/mainthread.go new file mode 100644 index 000000000..4e201c71e --- /dev/null +++ b/exp/pkg/application/mainthread.go @@ -0,0 +1,41 @@ +//go:build darwin + +package application + +/* +extern void dispatch(unsigned int id); +*/ +import "C" +import "strconv" + +var mainThreadFuntionStore = make(map[uint]func()) + +func generateFunctionStoreID() uint { + startID := 0 + for { + if _, ok := mainThreadFuntionStore[uint(startID)]; !ok { + return uint(startID) + } + startID++ + if startID == 0 { + panic("Too many functions stored") + } + } +} + +func Dispatch(fn func()) { + id := generateFunctionStoreID() + mainThreadFuntionStore[id] = fn + C.dispatch(C.uint(id)) +} + +//export dispatchCallback +func dispatchCallback(id C.uint) { + + fn := mainThreadFuntionStore[uint(id)] + if fn == nil { + panic("dispatchCallback called with invalid id " + strconv.Itoa(int(id))) + } + fn() + delete(mainThreadFuntionStore, uint(id)) +} diff --git a/exp/pkg/application/mainthread_darwin.go b/exp/pkg/application/mainthread_darwin.go new file mode 100644 index 000000000..4654bfa6c --- /dev/null +++ b/exp/pkg/application/mainthread_darwin.go @@ -0,0 +1,20 @@ +//go:build darwin + +package application + +/* +#cgo CFLAGS: -mmacosx-version-min=10.13 -x objective-c +#cgo LDFLAGS: -framework Cocoa + +#include "Cocoa/Cocoa.h" + +extern void dispatchCallback(unsigned int); + +void dispatch(unsigned int id) { + dispatch_async(dispatch_get_main_queue(), ^{ + dispatchCallback(id); + }); +} + +*/ +import "C" diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index ea785e6e0..33017a9ed 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -11,7 +11,6 @@ type windowImpl interface { setTitle(title string) setSize(width, height int) setAlwaysOnTop(alwaysOnTop bool) - run() error navigateToURL(url string) setResizable(resizable bool) setMinSize(width, height int) @@ -26,6 +25,7 @@ type windowImpl interface { isFullscreen() bool restore() setBackgroundColor(color *options.RGBA) + run() } type Window struct { @@ -68,9 +68,9 @@ func (w *Window) SetSize(width, height int) { w.impl.setSize(width, height) } -func (w *Window) Run() error { +func (w *Window) Run() { w.impl = newWindowImpl(w.id, w.options) - return w.impl.run() + w.impl.run() } func (w *Window) SetAlwaysOnTop(b bool) { diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index f2ff9bd83..06d28010a 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -489,59 +489,59 @@ func (w *macosWindow) enableDevTools() { C.windowEnableDevTools(w.nsWindow) } -func (w *macosWindow) run() error { - w.nsWindow = C.windowNew(C.uint(w.id), C.int(w.options.Width), C.int(w.options.Height)) - w.setTitle(w.options.Title) - w.setAlwaysOnTop(w.options.AlwaysOnTop) - w.setResizable(!w.options.DisableResize) - w.setMinSize(w.options.MinWidth, w.options.MinHeight) - w.setMaxSize(w.options.MaxWidth, w.options.MaxHeight) - if w.options.URL != "" { - w.navigateToURL(w.options.URL) - } - if w.options.EnableDevTools { - w.enableDevTools() - } - w.setBackgroundColor(w.options.BackgroundColour) - if w.options.Mac != nil { - macOptions := w.options.Mac - switch macOptions.Backdrop { - case options.MacBackdropTransparent: - C.windowSetTransparent(w.nsWindow) - C.webviewSetTransparent(w.nsWindow) - case options.MacBackdropTranslucent: - C.windowSetTranslucent(w.nsWindow) - C.webviewSetTransparent(w.nsWindow) +func (w *macosWindow) run() { + Dispatch(func() { + w.nsWindow = C.windowNew(C.uint(w.id), C.int(w.options.Width), C.int(w.options.Height)) + w.setTitle(w.options.Title) + w.setAlwaysOnTop(w.options.AlwaysOnTop) + w.setResizable(!w.options.DisableResize) + w.setMinSize(w.options.MinWidth, w.options.MinHeight) + w.setMaxSize(w.options.MaxWidth, w.options.MaxHeight) + if w.options.URL != "" { + w.navigateToURL(w.options.URL) } - - if macOptions.TitleBar != nil { - titleBarOptions := macOptions.TitleBar - C.windowSetTitleBarAppearsTransparent(w.nsWindow, C.bool(titleBarOptions.AppearsTransparent)) - C.windowSetHideTitleBar(w.nsWindow, C.bool(titleBarOptions.Hide)) - C.windowSetHideTitle(w.nsWindow, C.bool(titleBarOptions.HideTitle)) - C.windowSetFullSizeContent(w.nsWindow, C.bool(titleBarOptions.FullSizeContent)) - C.windowSetUseToolbar(w.nsWindow, C.bool(titleBarOptions.UseToolbar)) - C.windowSetHideToolbarSeparator(w.nsWindow, C.bool(titleBarOptions.HideToolbarSeparator)) + if w.options.EnableDevTools { + w.enableDevTools() } + w.setBackgroundColor(w.options.BackgroundColour) + if w.options.Mac != nil { + macOptions := w.options.Mac + switch macOptions.Backdrop { + case options.MacBackdropTransparent: + C.windowSetTransparent(w.nsWindow) + C.webviewSetTransparent(w.nsWindow) + case options.MacBackdropTranslucent: + C.windowSetTranslucent(w.nsWindow) + C.webviewSetTransparent(w.nsWindow) + } - if macOptions.Appearance != "" { - C.windowSetAppearanceTypeByName(w.nsWindow, C.CString(string(macOptions.Appearance))) - } + if macOptions.TitleBar != nil { + titleBarOptions := macOptions.TitleBar + C.windowSetTitleBarAppearsTransparent(w.nsWindow, C.bool(titleBarOptions.AppearsTransparent)) + C.windowSetHideTitleBar(w.nsWindow, C.bool(titleBarOptions.Hide)) + C.windowSetHideTitle(w.nsWindow, C.bool(titleBarOptions.HideTitle)) + C.windowSetFullSizeContent(w.nsWindow, C.bool(titleBarOptions.FullSizeContent)) + C.windowSetUseToolbar(w.nsWindow, C.bool(titleBarOptions.UseToolbar)) + C.windowSetHideToolbarSeparator(w.nsWindow, C.bool(titleBarOptions.HideToolbarSeparator)) + } - switch w.options.StartState { - case options.WindowStateMaximised: - w.setMaximised() - case options.WindowStateMinimised: - w.setMinimised() - case options.WindowStateFullscreen: - w.setFullscreen() + if macOptions.Appearance != "" { + C.windowSetAppearanceTypeByName(w.nsWindow, C.CString(string(macOptions.Appearance))) + } + + switch w.options.StartState { + case options.WindowStateMaximised: + w.setMaximised() + case options.WindowStateMinimised: + w.setMinimised() + case options.WindowStateFullscreen: + w.setFullscreen() + + } } - - } - C.windowShow(w.nsWindow) - - return nil + C.windowShow(w.nsWindow) + }) } func (w *macosWindow) setBackgroundColor(colour *options.RGBA) { From d5e21d50036c44e4a61ff71e6be99d8ce40acfa4 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Fri, 9 Dec 2022 08:22:17 +1100 Subject: [PATCH 12/85] Fix race condition in closing window during navigating Add sane defaults --- exp/go.mod | 5 +- exp/go.sum | 2 - exp/pkg/application/application.go | 8 ++ exp/pkg/application/window_darwin.go | 6 +- exp/pkg/options/application.go | 136 --------------------------- exp/pkg/options/mac.go | 105 +++++++++++++++++++++ exp/pkg/options/window.go | 30 ++++++ 7 files changed, 147 insertions(+), 145 deletions(-) create mode 100644 exp/pkg/options/mac.go create mode 100644 exp/pkg/options/window.go diff --git a/exp/go.mod b/exp/go.mod index 6b99bc397..1969eb348 100644 --- a/exp/go.mod +++ b/exp/go.mod @@ -2,7 +2,4 @@ module github.com/wailsapp/wails/exp go 1.19 -require ( - github.com/gofrs/uuid v4.3.1+incompatible - github.com/leaanthony/clir v1.3.0 -) +require github.com/leaanthony/clir v1.3.0 diff --git a/exp/go.sum b/exp/go.sum index 119fea365..ec90627a4 100644 --- a/exp/go.sum +++ b/exp/go.sum @@ -1,4 +1,2 @@ -github.com/gofrs/uuid v4.3.1+incompatible h1:0/KbAdpx3UXAx1kEOWHJeOkpbgRFGHVgv+CFIY7dBJI= -github.com/gofrs/uuid v4.3.1+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/leaanthony/clir v1.3.0 h1:L9nPDWrmc/qU9UWZZvRaFajWYuO0np9V5p+5gxyYno0= github.com/leaanthony/clir v1.3.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index 9dce249ee..8f01314d5 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -33,6 +33,14 @@ func (a *App) On(s string, callback func()) { } func (a *App) NewWindow(options *options.Window) *Window { + // Ensure we have sane defaults + if options.Width == 0 { + options.Width = 1024 + } + if options.Height == 0 { + options.Height = 768 + } + newWindow := NewWindow(options) id := newWindow.id if a.windows == nil { diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index 06d28010a..d06cb4667 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -497,9 +497,6 @@ func (w *macosWindow) run() { w.setResizable(!w.options.DisableResize) w.setMinSize(w.options.MinWidth, w.options.MinHeight) w.setMaxSize(w.options.MaxWidth, w.options.MaxHeight) - if w.options.URL != "" { - w.navigateToURL(w.options.URL) - } if w.options.EnableDevTools { w.enableDevTools() } @@ -540,6 +537,9 @@ func (w *macosWindow) run() { } } + if w.options.URL != "" { + w.navigateToURL(w.options.URL) + } C.windowShow(w.nsWindow) }) } diff --git a/exp/pkg/options/application.go b/exp/pkg/options/application.go index a8b17c21f..afc004245 100644 --- a/exp/pkg/options/application.go +++ b/exp/pkg/options/application.go @@ -3,139 +3,3 @@ package options type Application struct { Mac *Mac } - -// Mac contains macOS specific options - -type ActivationPolicy int - -const ( - ActivationPolicyRegular ActivationPolicy = iota - ActivationPolicyAccessory - ActivationPolicyProhibited -) - -type Mac struct { - // ActivationPolicy is the activation policy for the application. Defaults to - // applicationActivationPolicyRegular. - ActivationPolicy ActivationPolicy -} - -type Window struct { - Title string - Width, Height int - AlwaysOnTop bool - URL string - DisableResize bool - Resizable bool - MinWidth int - MinHeight int - MaxWidth int - MaxHeight int - EnableDevTools bool - StartState WindowState - Mac *MacWindow - BackgroundColour *RGBA -} - -type RGBA struct { - Red, Green, Blue, Alpha uint8 -} - -type MacBackdrop int - -const ( - MacBackdropNormal MacBackdrop = iota - MacBackdropTransparent - MacBackdropTranslucent -) - -type WindowState int - -const ( - WindowStateNormal WindowState = iota - WindowStateMinimised - WindowStateMaximised - WindowStateFullscreen -) - -// MacWindow contains macOS specific options -type MacWindow struct { - Backdrop MacBackdrop - TitleBar *TitleBar - Appearance MacAppearanceType -} - -// TitleBar contains options for the Mac titlebar -type TitleBar struct { - AppearsTransparent bool - Hide bool - HideTitle bool - FullSizeContent bool - UseToolbar bool - HideToolbarSeparator bool -} - -// TitleBarDefault results in the default Mac Titlebar -func TitleBarDefault() *TitleBar { - return &TitleBar{ - AppearsTransparent: false, - Hide: false, - HideTitle: false, - FullSizeContent: false, - UseToolbar: false, - HideToolbarSeparator: false, - } -} - -// Credit: Comments from Electron site - -// TitleBarHidden results in a hidden title bar and a full size content window, -// yet the title bar still has the standard window controls (“traffic lights”) -// in the top left. -func TitleBarHidden() *TitleBar { - return &TitleBar{ - AppearsTransparent: true, - Hide: false, - HideTitle: true, - FullSizeContent: true, - UseToolbar: false, - HideToolbarSeparator: false, - } -} - -// TitleBarHiddenInset results in a hidden title bar with an alternative look where -// the traffic light buttons are slightly more inset from the window edge. -func TitleBarHiddenInset() *TitleBar { - - return &TitleBar{ - AppearsTransparent: true, - Hide: false, - HideTitle: true, - FullSizeContent: true, - UseToolbar: true, - HideToolbarSeparator: true, - } - -} - -// MacAppearanceType is a type of Appearance for Cocoa windows -type MacAppearanceType string - -const ( - // DefaultAppearance uses the default system value - DefaultAppearance MacAppearanceType = "" - // NSAppearanceNameAqua - The standard light system appearance. - NSAppearanceNameAqua MacAppearanceType = "NSAppearanceNameAqua" - // NSAppearanceNameDarkAqua - The standard dark system appearance. - NSAppearanceNameDarkAqua MacAppearanceType = "NSAppearanceNameDarkAqua" - // NSAppearanceNameVibrantLight - The light vibrant appearance - NSAppearanceNameVibrantLight MacAppearanceType = "NSAppearanceNameVibrantLight" - // NSAppearanceNameAccessibilityHighContrastAqua - A high-contrast version of the standard light system appearance. - NSAppearanceNameAccessibilityHighContrastAqua MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastAqua" - // NSAppearanceNameAccessibilityHighContrastDarkAqua - A high-contrast version of the standard dark system appearance. - NSAppearanceNameAccessibilityHighContrastDarkAqua MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastDarkAqua" - // NSAppearanceNameAccessibilityHighContrastVibrantLight - A high-contrast version of the light vibrant appearance. - NSAppearanceNameAccessibilityHighContrastVibrantLight MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastVibrantLight" - // NSAppearanceNameAccessibilityHighContrastVibrantDark - A high-contrast version of the dark vibrant appearance. - NSAppearanceNameAccessibilityHighContrastVibrantDark MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastVibrantDark" -) diff --git a/exp/pkg/options/mac.go b/exp/pkg/options/mac.go new file mode 100644 index 000000000..40730bc7e --- /dev/null +++ b/exp/pkg/options/mac.go @@ -0,0 +1,105 @@ +package options + +type ActivationPolicy int + +const ( + ActivationPolicyRegular ActivationPolicy = iota + ActivationPolicyAccessory + ActivationPolicyProhibited +) + +type Mac struct { + // ActivationPolicy is the activation policy for the application. Defaults to + // applicationActivationPolicyRegular. + ActivationPolicy ActivationPolicy +} + +type MacBackdrop int + +const ( + MacBackdropNormal MacBackdrop = iota + MacBackdropTransparent + MacBackdropTranslucent +) + +// MacWindow contains macOS specific options +type MacWindow struct { + Backdrop MacBackdrop + TitleBar *TitleBar + Appearance MacAppearanceType +} + +// TitleBar contains options for the Mac titlebar +type TitleBar struct { + AppearsTransparent bool + Hide bool + HideTitle bool + FullSizeContent bool + UseToolbar bool + HideToolbarSeparator bool +} + +// TitleBarDefault results in the default Mac Titlebar +func TitleBarDefault() *TitleBar { + return &TitleBar{ + AppearsTransparent: false, + Hide: false, + HideTitle: false, + FullSizeContent: false, + UseToolbar: false, + HideToolbarSeparator: false, + } +} + +// Credit: Comments from Electron site + +// TitleBarHidden results in a hidden title bar and a full size content window, +// yet the title bar still has the standard window controls (“traffic lights”) +// in the top left. +func TitleBarHidden() *TitleBar { + return &TitleBar{ + AppearsTransparent: true, + Hide: false, + HideTitle: true, + FullSizeContent: true, + UseToolbar: false, + HideToolbarSeparator: false, + } +} + +// TitleBarHiddenInset results in a hidden title bar with an alternative look where +// the traffic light buttons are slightly more inset from the window edge. +func TitleBarHiddenInset() *TitleBar { + + return &TitleBar{ + AppearsTransparent: true, + Hide: false, + HideTitle: true, + FullSizeContent: true, + UseToolbar: true, + HideToolbarSeparator: true, + } + +} + +// MacAppearanceType is a type of Appearance for Cocoa windows +type MacAppearanceType string + +const ( + // DefaultAppearance uses the default system value + DefaultAppearance MacAppearanceType = "" + // NSAppearanceNameAqua - The standard light system appearance. + NSAppearanceNameAqua MacAppearanceType = "NSAppearanceNameAqua" + // NSAppearanceNameDarkAqua - The standard dark system appearance. + NSAppearanceNameDarkAqua MacAppearanceType = "NSAppearanceNameDarkAqua" + // NSAppearanceNameVibrantLight - The light vibrant appearance + NSAppearanceNameVibrantLight MacAppearanceType = "NSAppearanceNameVibrantLight" + // NSAppearanceNameAccessibilityHighContrastAqua - A high-contrast version of the standard light system appearance. + NSAppearanceNameAccessibilityHighContrastAqua MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastAqua" + // NSAppearanceNameAccessibilityHighContrastDarkAqua - A high-contrast version of the standard dark system appearance. + NSAppearanceNameAccessibilityHighContrastDarkAqua MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastDarkAqua" + // NSAppearanceNameAccessibilityHighContrastVibrantLight - A high-contrast version of the light vibrant appearance. + NSAppearanceNameAccessibilityHighContrastVibrantLight MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastVibrantLight" + // NSAppearanceNameAccessibilityHighContrastVibrantDark - A high-contrast version of the dark vibrant appearance. + NSAppearanceNameAccessibilityHighContrastVibrantDark MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastVibrantDark" +) diff --git a/exp/pkg/options/window.go b/exp/pkg/options/window.go new file mode 100644 index 000000000..8c94114c3 --- /dev/null +++ b/exp/pkg/options/window.go @@ -0,0 +1,30 @@ +package options + +type WindowState int + +const ( + WindowStateNormal WindowState = iota + WindowStateMinimised + WindowStateMaximised + WindowStateFullscreen +) + +type Window struct { + Title string + Width, Height int + AlwaysOnTop bool + URL string + DisableResize bool + MinWidth int + MinHeight int + MaxWidth int + MaxHeight int + EnableDevTools bool + StartState WindowState + Mac *MacWindow + BackgroundColour *RGBA +} + +type RGBA struct { + Red, Green, Blue, Alpha uint8 +} From a134bfac426dc60a6fd011c2f569c49b8a6f29d9 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sat, 10 Dec 2022 22:34:15 +1100 Subject: [PATCH 13/85] Add Center Add more events --- exp/examples/basic/main.go | 1 + exp/pkg/application/app_delegate.m | 28 ++++++++++++++++++++++++++++ exp/pkg/application/window.go | 8 ++++++++ exp/pkg/application/window_darwin.go | 24 ++++++++++++++++++++++++ exp/pkg/events/events.go | 24 ++++++++++++++++++++---- exp/pkg/events/events.h | 8 ++++++++ exp/pkg/events/events.txt | 10 +++++++++- 7 files changed, 98 insertions(+), 5 deletions(-) diff --git a/exp/examples/basic/main.go b/exp/examples/basic/main.go index bea07f89f..b904f4c3e 100644 --- a/exp/examples/basic/main.go +++ b/exp/examples/basic/main.go @@ -71,6 +71,7 @@ func main() { myWindow2.NavigateToURL("https://wails.io") myWindow.SetMinSize(600, 600) myWindow.SetMaxSize(650, 650) + myWindow.Center() }() diff --git a/exp/pkg/application/app_delegate.m b/exp/pkg/application/app_delegate.m index 921feb0d4..9f4b47daa 100644 --- a/exp/pkg/application/app_delegate.m +++ b/exp/pkg/application/app_delegate.m @@ -30,6 +30,34 @@ systemEventHandler(EventApplicationWillTerminate); } +- (void)applicationDidBecomeActive:(NSNotification *)aNotification +{ + systemEventHandler(EventApplicationDidBecomeActive); +} + +- (void)applicationWillHide:(NSNotification *)aNotification +{ + systemEventHandler(EventApplicationWillHide); +} + +- (void)applicationDidHide:(NSNotification *)aNotification +{ + systemEventHandler(EventApplicationDidHide); +} + +- (void)applicationWillUnhide:(NSNotification *)aNotification +{ + systemEventHandler(EventApplicationWillUnhide); +} + +- (void)applicationDidUnhide:(NSNotification *)aNotification +{ + systemEventHandler(EventApplicationDidUnhide); +} + + + + @end \ No newline at end of file diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index 33017a9ed..b0df941c9 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -26,6 +26,7 @@ type windowImpl interface { restore() setBackgroundColor(color *options.RGBA) run() + center() } type Window struct { @@ -209,3 +210,10 @@ func (w *Window) handleMessage(message string) { w.SetTitle("Hello World") } } + +func (w *Window) Center() { + if w.impl == nil { + return + } + w.impl.center() +} diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index d06cb4667..dc70da65d 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -399,6 +399,20 @@ void windowSetAppearanceTypeByName(void* nsWindow, const char *appearanceName) { }); } +// Center window on current monitor +void windowCenter(void* nsWindow) { + // Center window on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + // get main window + NSWindow* window = (NSWindow*)nsWindow; + [window center]; + }); +} + + + + + */ import "C" import ( @@ -413,6 +427,10 @@ type macosWindow struct { options *options.Window } +func (w *macosWindow) center() { + C.windowCenter(w.nsWindow) +} + func (w *macosWindow) isMinimised() bool { return C.windowIsMinimised(w.nsWindow) == C.bool(true) } @@ -537,6 +555,8 @@ func (w *macosWindow) run() { } } + C.windowCenter(w.nsWindow) + if w.options.URL != "" { w.navigateToURL(w.options.URL) } @@ -550,3 +570,7 @@ func (w *macosWindow) setBackgroundColor(colour *options.RGBA) { } C.webviewSetBackgroundColor(w.nsWindow, C.int(colour.Red), C.int(colour.Green), C.int(colour.Blue), C.int(colour.Alpha)) } + +func (w *macosWindow) Center() { + C.windowCenter(w.nsWindow) +} diff --git a/exp/pkg/events/events.go b/exp/pkg/events/events.go index d172559e5..e2b189bc8 100644 --- a/exp/pkg/events/events.go +++ b/exp/pkg/events/events.go @@ -3,13 +3,29 @@ package events var Mac = newMacEvents() type macEvents struct { - ApplicationDidFinishLaunching string - ApplicationWillTerminate string + ApplicationDidFinishLaunching string + ApplicationWillTerminate string + ApplicationDidBecomeActive string + ApplicationWillUpdate string + ApplicationDidUpdate string + ApplicationWillFinishLaunching string + ApplicationWillHide string + ApplicationWillUnhide string + ApplicationDidHide string + ApplicationDidUnhide string } func newMacEvents() macEvents { return macEvents{ - ApplicationDidFinishLaunching: "mac:ApplicationDidFinishLaunching", - ApplicationWillTerminate: "mac:ApplicationWillTerminate", + ApplicationDidFinishLaunching: "mac:ApplicationDidFinishLaunching", + ApplicationWillTerminate: "mac:ApplicationWillTerminate", + ApplicationDidBecomeActive: "mac:ApplicationDidBecomeActive", + ApplicationWillUpdate: "mac:ApplicationWillUpdate", + ApplicationDidUpdate: "mac:ApplicationDidUpdate", + ApplicationWillFinishLaunching: "mac:ApplicationWillFinishLaunching", + ApplicationWillHide: "mac:ApplicationWillHide", + ApplicationWillUnhide: "mac:ApplicationWillUnhide", + ApplicationDidHide: "mac:ApplicationDidHide", + ApplicationDidUnhide: "mac:ApplicationDidUnhide", } } diff --git a/exp/pkg/events/events.h b/exp/pkg/events/events.h index f6cbc5f55..58f0ff57b 100644 --- a/exp/pkg/events/events.h +++ b/exp/pkg/events/events.h @@ -7,6 +7,14 @@ extern void systemEventHandler(char*); #define EventApplicationDidFinishLaunching "mac:ApplicationDidFinishLaunching" #define EventApplicationWillTerminate "mac:ApplicationWillTerminate" +#define EventApplicationDidBecomeActive "mac:ApplicationDidBecomeActive" +#define EventApplicationWillUpdate "mac:ApplicationWillUpdate" +#define EventApplicationDidUpdate "mac:ApplicationDidUpdate" +#define EventApplicationWillFinishLaunching "mac:ApplicationWillFinishLaunching" +#define EventApplicationWillHide "mac:ApplicationWillHide" +#define EventApplicationWillUnhide "mac:ApplicationWillUnhide" +#define EventApplicationDidHide "mac:ApplicationDidHide" +#define EventApplicationDidUnhide "mac:ApplicationDidUnhide" #endif \ No newline at end of file diff --git a/exp/pkg/events/events.txt b/exp/pkg/events/events.txt index 0f7fd4f70..68a422b9d 100644 --- a/exp/pkg/events/events.txt +++ b/exp/pkg/events/events.txt @@ -1,2 +1,10 @@ mac:ApplicationDidFinishLaunching -mac:ApplicationWillTerminate \ No newline at end of file +mac:ApplicationWillTerminate +mac:ApplicationDidBecomeActive +mac:ApplicationWillUpdate +mac:ApplicationDidUpdate +mac:ApplicationWillFinishLaunching +mac:ApplicationWillHide +mac:ApplicationWillUnhide +mac:ApplicationDidHide +mac:ApplicationDidUnhide From 27370559d3a5662da1c608f4c6dba40b9f162b84 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 11 Dec 2022 11:09:52 +1100 Subject: [PATCH 14/85] Refactor Is* methods Add more events --- exp/pkg/application/app_delegate.m | 46 +++++++++++++++++++++ exp/pkg/application/window_darwin.go | 57 ++++++++++++++------------ exp/pkg/events/events.go | 60 ++++++++++++++++++---------- exp/pkg/events/events.h | 16 ++++++-- exp/pkg/events/events.txt | 16 ++++++-- 5 files changed, 143 insertions(+), 52 deletions(-) diff --git a/exp/pkg/application/app_delegate.m b/exp/pkg/application/app_delegate.m index 9f4b47daa..7e10942db 100644 --- a/exp/pkg/application/app_delegate.m +++ b/exp/pkg/application/app_delegate.m @@ -55,9 +55,55 @@ systemEventHandler(EventApplicationDidUnhide); } +- (void)applicationWillResignActive:(NSNotification *)aNotification +{ + systemEventHandler(EventApplicationWillResignActive); +} +- (void)applicationWillUpdate:(NSNotification *)aNotification +{ + systemEventHandler(EventApplicationWillUpdate); +} +- (void)applicationDidUpdate:(NSNotification *)aNotification +{ + systemEventHandler(EventApplicationDidUpdate); +} +- (void)applicationDidChangeScreenParameters:(NSNotification *)aNotification +{ + systemEventHandler(EventApplicationDidChangeScreenParameters); +} + +- (void)applicationDidChangeOcclusionState:(NSNotification *)aNotification +{ + systemEventHandler(EventApplicationDidChangeOcclusionState); +} + +- (void)applicationDidChangeBackingProperties:(NSNotification *)aNotification +{ + systemEventHandler(EventApplicationDidChangeBackingProperties); +} + +- (void)applicationDidChangeIcon:(NSNotification *)aNotification +{ + systemEventHandler(EventApplicationDidChangeIcon); +} + +- (void)applicationDidChangeEffectiveAppearance:(NSNotification *)aNotification +{ + systemEventHandler(EventApplicationDidChangeEffectiveAppearance); +} + +- (void)applicationDidChangeStatusBarOrientation:(NSNotification *)aNotification +{ + systemEventHandler(EventApplicationDidChangeStatusBarOrientation); +} + +- (void)applicationDidChangeStatusBarFrame:(NSNotification *)aNotification +{ + systemEventHandler(EventApplicationDidChangeStatusBarFrame); +} @end \ No newline at end of file diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index dc70da65d..bc7bbbf10 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -3,7 +3,7 @@ package application /* -#cgo CFLAGS: -mmacosx-version-min=10.10 -x objective-c +#cgo CFLAGS: -mmacosx-version-min=10.13 -x objective-c #cgo LDFLAGS: -framework Cocoa -framework WebKit #include "application.h" @@ -16,7 +16,7 @@ package application // Create a new Window void* windowNew(unsigned int id, int width, int height) { NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, width-1, height-1) - styleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask + styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskMiniaturizable backing:NSBackingStoreBuffered defer:NO]; @@ -123,7 +123,7 @@ void navigationLoadURL(void* nsWindow, char* url) { void windowSetResizable(void* nsWindow, bool resizable) { // Set window resizable on main thread dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)nsWindow setStyleMask:resizable ? NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask : NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask]; + [(NSWindow*)nsWindow setStyleMask:resizable ? NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskMiniaturizable : NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable]; }); } @@ -258,7 +258,7 @@ void windowRestore(void* nsWindow) { // Set window normal on main thread dispatch_async(dispatch_get_main_queue(), ^{ // If window is fullscreen - if([(NSWindow*)nsWindow styleMask] & NSFullScreenWindowMask) { + if([(NSWindow*)nsWindow styleMask] & NSWindowStyleMaskFullScreen) { [(NSWindow*)nsWindow toggleFullScreen:nil]; } // If window is maximised @@ -273,30 +273,16 @@ void windowRestore(void* nsWindow) { } bool windowIsMaximised(void* nsWindow) { - // Get window maximized on main thread - __block bool maximized = false; - dispatch_sync(dispatch_get_main_queue(), ^{ - maximized = [(NSWindow*)nsWindow isZoomed]; - }); - return maximized; + return [(NSWindow*)nsWindow isZoomed]; } bool windowIsFullscreen(void* nsWindow) { // Get window fullscreen on main thread - __block bool fullscreen = false; - dispatch_sync(dispatch_get_main_queue(), ^{ - fullscreen = [(NSWindow*)nsWindow styleMask] & NSFullScreenWindowMask; - }); - return fullscreen; + return [(NSWindow*)nsWindow styleMask] & NSWindowStyleMaskFullScreen; } bool windowIsMinimised(void* nsWindow) { - // Get window minimised on main thread - __block bool minimised = false; - dispatch_sync(dispatch_get_main_queue(), ^{ - minimised = [(NSWindow*)nsWindow isMiniaturized]; - }); - return minimised; + return [(NSWindow*)nsWindow isMiniaturized]; } // Set the titlebar style @@ -416,6 +402,7 @@ void windowCenter(void* nsWindow) { */ import "C" import ( + "sync" "unsafe" "github.com/wailsapp/wails/exp/pkg/options" @@ -432,20 +419,38 @@ func (w *macosWindow) center() { } func (w *macosWindow) isMinimised() bool { - return C.windowIsMinimised(w.nsWindow) == C.bool(true) + return w.syncMainThreadReturningBool(func() bool { + return C.windowIsMinimised(w.nsWindow) == C.bool(true) + }) } func (w *macosWindow) isMaximised() bool { - return C.windowIsMaximised(w.nsWindow) == C.bool(true) + return w.syncMainThreadReturningBool(func() bool { + return C.windowIsMaximised(w.nsWindow) == C.bool(true) + }) } func (w *macosWindow) isFullscreen() bool { - return C.windowIsFullscreen(w.nsWindow) == C.bool(true) + return w.syncMainThreadReturningBool(func() bool { + return C.windowIsFullscreen(w.nsWindow) == C.bool(true) + }) +} + +func (w *macosWindow) syncMainThreadReturningBool(fn func() bool) bool { + var wg sync.WaitGroup + wg.Add(1) + var result bool + Dispatch(func() { + result = fn() + wg.Done() + }) + wg.Done() + return result } func (w *macosWindow) restore() { - //TODO implement me - panic("implement me") + // restore window to normal size + C.windowRestore(w.nsWindow) } func (w *macosWindow) setMaximised() { diff --git a/exp/pkg/events/events.go b/exp/pkg/events/events.go index e2b189bc8..d4cb6a1d0 100644 --- a/exp/pkg/events/events.go +++ b/exp/pkg/events/events.go @@ -3,29 +3,49 @@ package events var Mac = newMacEvents() type macEvents struct { - ApplicationDidFinishLaunching string - ApplicationWillTerminate string - ApplicationDidBecomeActive string - ApplicationWillUpdate string - ApplicationDidUpdate string - ApplicationWillFinishLaunching string - ApplicationWillHide string - ApplicationWillUnhide string - ApplicationDidHide string - ApplicationDidUnhide string + ApplicationWillFinishLaunching string + ApplicationDidFinishLaunching string + ApplicationWillBecomeActive string + ApplicationDidBecomeActive string + ApplicationWillUpdate string + ApplicationDidUpdate string + ApplicationWillHide string + ApplicationDidHide string + ApplicationWillUnhide string + ApplicationDidUnhide string + ApplicationWillResignActive string + ApplicationDidResignActive string + ApplicationWillTerminate string + ApplicationDidChangeOcclusionState string + ApplicationDidChangeScreenParameters string + ApplicationDidChangeBackingProperties string + ApplicationDidChangeIcon string + ApplicationDidChangeStatusBarOrientation string + ApplicationDidChangeStatusBarFrame string + ApplicationDidChangeEffectiveAppearance string } func newMacEvents() macEvents { return macEvents{ - ApplicationDidFinishLaunching: "mac:ApplicationDidFinishLaunching", - ApplicationWillTerminate: "mac:ApplicationWillTerminate", - ApplicationDidBecomeActive: "mac:ApplicationDidBecomeActive", - ApplicationWillUpdate: "mac:ApplicationWillUpdate", - ApplicationDidUpdate: "mac:ApplicationDidUpdate", - ApplicationWillFinishLaunching: "mac:ApplicationWillFinishLaunching", - ApplicationWillHide: "mac:ApplicationWillHide", - ApplicationWillUnhide: "mac:ApplicationWillUnhide", - ApplicationDidHide: "mac:ApplicationDidHide", - ApplicationDidUnhide: "mac:ApplicationDidUnhide", + ApplicationWillFinishLaunching: "mac:ApplicationWillFinishLaunching", + ApplicationDidFinishLaunching: "mac:ApplicationDidFinishLaunching", + ApplicationWillBecomeActive: "mac:ApplicationWillBecomeActive", + ApplicationDidBecomeActive: "mac:ApplicationDidBecomeActive", + ApplicationWillUpdate: "mac:ApplicationWillUpdate", + ApplicationDidUpdate: "mac:ApplicationDidUpdate", + ApplicationWillHide: "mac:ApplicationWillHide", + ApplicationDidHide: "mac:ApplicationDidHide", + ApplicationWillUnhide: "mac:ApplicationWillUnhide", + ApplicationDidUnhide: "mac:ApplicationDidUnhide", + ApplicationWillResignActive: "mac:ApplicationWillResignActive", + ApplicationDidResignActive: "mac:ApplicationDidResignActive", + ApplicationWillTerminate: "mac:ApplicationWillTerminate", + ApplicationDidChangeOcclusionState: "mac:ApplicationDidChangeOcclusionState", + ApplicationDidChangeScreenParameters: "mac:ApplicationDidChangeScreenParameters", + ApplicationDidChangeBackingProperties: "mac:ApplicationDidChangeBackingProperties", + ApplicationDidChangeIcon: "mac:ApplicationDidChangeIcon", + ApplicationDidChangeStatusBarOrientation: "mac:ApplicationDidChangeStatusBarOrientation", + ApplicationDidChangeStatusBarFrame: "mac:ApplicationDidChangeStatusBarFrame", + ApplicationDidChangeEffectiveAppearance: "mac:ApplicationDidChangeEffectiveAppearance", } } diff --git a/exp/pkg/events/events.h b/exp/pkg/events/events.h index 58f0ff57b..192bc4964 100644 --- a/exp/pkg/events/events.h +++ b/exp/pkg/events/events.h @@ -5,16 +5,26 @@ extern void systemEventHandler(char*); +#define EventApplicationWillFinishLaunching "mac:ApplicationWillFinishLaunching" #define EventApplicationDidFinishLaunching "mac:ApplicationDidFinishLaunching" -#define EventApplicationWillTerminate "mac:ApplicationWillTerminate" +#define EventApplicationWillBecomeActive "mac:ApplicationWillBecomeActive" #define EventApplicationDidBecomeActive "mac:ApplicationDidBecomeActive" #define EventApplicationWillUpdate "mac:ApplicationWillUpdate" #define EventApplicationDidUpdate "mac:ApplicationDidUpdate" -#define EventApplicationWillFinishLaunching "mac:ApplicationWillFinishLaunching" #define EventApplicationWillHide "mac:ApplicationWillHide" -#define EventApplicationWillUnhide "mac:ApplicationWillUnhide" #define EventApplicationDidHide "mac:ApplicationDidHide" +#define EventApplicationWillUnhide "mac:ApplicationWillUnhide" #define EventApplicationDidUnhide "mac:ApplicationDidUnhide" +#define EventApplicationWillResignActive "mac:ApplicationWillResignActive" +#define EventApplicationDidResignActive "mac:ApplicationDidResignActive" +#define EventApplicationWillTerminate "mac:ApplicationWillTerminate" +#define EventApplicationDidChangeOcclusionState "mac:ApplicationDidChangeOcclusionState" +#define EventApplicationDidChangeScreenParameters "mac:ApplicationDidChangeScreenParameters" +#define EventApplicationDidChangeBackingProperties "mac:ApplicationDidChangeBackingProperties" +#define EventApplicationDidChangeIcon "mac:ApplicationDidChangeIcon" +#define EventApplicationDidChangeStatusBarOrientation "mac:ApplicationDidChangeStatusBarOrientation" +#define EventApplicationDidChangeStatusBarFrame "mac:ApplicationDidChangeStatusBarFrame" +#define EventApplicationDidChangeEffectiveAppearance "mac:ApplicationDidChangeEffectiveAppearance" #endif \ No newline at end of file diff --git a/exp/pkg/events/events.txt b/exp/pkg/events/events.txt index 68a422b9d..be917db2c 100644 --- a/exp/pkg/events/events.txt +++ b/exp/pkg/events/events.txt @@ -1,10 +1,20 @@ +mac:ApplicationWillFinishLaunching mac:ApplicationDidFinishLaunching -mac:ApplicationWillTerminate +mac:ApplicationWillBecomeActive mac:ApplicationDidBecomeActive mac:ApplicationWillUpdate mac:ApplicationDidUpdate -mac:ApplicationWillFinishLaunching mac:ApplicationWillHide -mac:ApplicationWillUnhide mac:ApplicationDidHide +mac:ApplicationWillUnhide mac:ApplicationDidUnhide +mac:ApplicationWillResignActive +mac:ApplicationDidResignActive +mac:ApplicationWillTerminate +mac:ApplicationDidChangeOcclusionState +mac:ApplicationDidChangeScreenParameters +mac:ApplicationDidChangeBackingProperties +mac:ApplicationDidChangeIcon +mac:ApplicationDidChangeStatusBarOrientation +mac:ApplicationDidChangeStatusBarFrame +mac:ApplicationDidChangeEffectiveAppearance From 4a2cf597c28467b33391d6582cb0815802fb103e Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 11 Dec 2022 11:26:21 +1100 Subject: [PATCH 15/85] Fix resizable --- exp/examples/basic/main.go | 12 ++++++++++++ exp/pkg/application/window_darwin.go | 7 +++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/exp/examples/basic/main.go b/exp/examples/basic/main.go index b904f4c3e..30c87f0b2 100644 --- a/exp/examples/basic/main.go +++ b/exp/examples/basic/main.go @@ -62,6 +62,18 @@ func main() { }() + go func() { + for { + time.Sleep(5 * time.Second) + println("window 1 is fullscreen?", myWindow.IsFullscreen()) + println("window 2 is fullscreen?", myWindow2.IsFullscreen()) + println("window 1 is maximised?", myWindow.IsMaximised()) + println("window 2 is maximised?", myWindow2.IsMaximised()) + println("window 1 is minimised?", myWindow.IsMinimised()) + println("window 2 is minimised?", myWindow2.IsMinimised()) + } + }() + go func() { time.Sleep(5 * time.Second) myWindow.SetTitle("Wooooo") diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index bc7bbbf10..9c9b74761 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -16,7 +16,7 @@ package application // Create a new Window void* windowNew(unsigned int id, int width, int height) { NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, width-1, height-1) - styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskMiniaturizable + styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable backing:NSBackingStoreBuffered defer:NO]; @@ -123,7 +123,7 @@ void navigationLoadURL(void* nsWindow, char* url) { void windowSetResizable(void* nsWindow, bool resizable) { // Set window resizable on main thread dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)nsWindow setStyleMask:resizable ? NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskMiniaturizable : NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable]; + [(NSWindow*)nsWindow setStyleMask:resizable ? NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable : NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable]; }); } @@ -277,7 +277,6 @@ bool windowIsMaximised(void* nsWindow) { } bool windowIsFullscreen(void* nsWindow) { - // Get window fullscreen on main thread return [(NSWindow*)nsWindow styleMask] & NSWindowStyleMaskFullScreen; } @@ -444,7 +443,7 @@ func (w *macosWindow) syncMainThreadReturningBool(fn func() bool) bool { result = fn() wg.Done() }) - wg.Done() + wg.Wait() return result } From bf8e5412210185cdd9e1ced59e5c9065af4b5107 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 11 Dec 2022 13:01:38 +1100 Subject: [PATCH 16/85] Support Window events Convert events to uint Rename system events to application events --- exp/examples/basic/main.go | 95 ------- exp/examples/kitchensink/main.go | 161 ++++++++++++ exp/pkg/application/app_delegate.m | 102 ++++---- exp/pkg/application/application.go | 28 +- exp/pkg/application/application_darwin.go | 23 +- exp/pkg/application/events.go | 9 +- exp/pkg/application/window.go | 21 +- exp/pkg/application/window_delegate.m | 305 ++++++++++++++++++++++ exp/pkg/events/events.go | 226 +++++++++++++--- exp/pkg/events/events.h | 116 ++++++-- exp/pkg/events/events.txt | 105 ++++++-- exp/tasks/events/generate.go | 104 +++++++- 12 files changed, 1051 insertions(+), 244 deletions(-) delete mode 100644 exp/examples/basic/main.go create mode 100644 exp/examples/kitchensink/main.go diff --git a/exp/examples/basic/main.go b/exp/examples/basic/main.go deleted file mode 100644 index 30c87f0b2..000000000 --- a/exp/examples/basic/main.go +++ /dev/null @@ -1,95 +0,0 @@ -package main - -import ( - "log" - "time" - - "github.com/wailsapp/wails/exp/pkg/application" - "github.com/wailsapp/wails/exp/pkg/events" - "github.com/wailsapp/wails/exp/pkg/options" -) - -func main() { - app := application.New(&options.Application{ - Mac: &options.Mac{ - //ActivationPolicy: options.ActivationPolicyAccessory, - }, - }) - app.On(events.Mac.ApplicationDidFinishLaunching, func() { - println("WOOOOO!") - }) - app.On(events.Mac.ApplicationWillTerminate, func() { - println("TERMINATION!!") - }) - myWindow := app.NewWindow(&options.Window{ - Title: "Basic", - Width: 600, - Height: 400, - AlwaysOnTop: true, - DisableResize: false, - //MinWidth: 100, - //MinHeight: 100, - //MaxWidth: 1000, - //MaxHeight: 1000, - EnableDevTools: true, - BackgroundColour: &options.RGBA{ - Red: 255, - Green: 255, - Blue: 255, - Alpha: 30, - }, - StartState: options.WindowStateMaximised, - Mac: &options.MacWindow{ - Backdrop: options.MacBackdropTranslucent, - Appearance: options.NSAppearanceNameDarkAqua, - }, - }) - - var myWindow2 *application.Window - go func() { - time.Sleep(2 * time.Second) - myWindow2 = app.NewWindow(&options.Window{ - Title: "#2", - Width: 1024, - Height: 768, - AlwaysOnTop: false, - URL: "https://google.com", - DisableResize: true, - Mac: &options.MacWindow{ - Backdrop: options.MacBackdropTranslucent, - }, - }) - - }() - - go func() { - for { - time.Sleep(5 * time.Second) - println("window 1 is fullscreen?", myWindow.IsFullscreen()) - println("window 2 is fullscreen?", myWindow2.IsFullscreen()) - println("window 1 is maximised?", myWindow.IsMaximised()) - println("window 2 is maximised?", myWindow2.IsMaximised()) - println("window 1 is minimised?", myWindow.IsMinimised()) - println("window 2 is minimised?", myWindow2.IsMinimised()) - } - }() - - go func() { - time.Sleep(5 * time.Second) - myWindow.SetTitle("Wooooo") - myWindow.SetAlwaysOnTop(true) - myWindow2.EnableDevTools() - myWindow2.SetTitle("OMFG") - myWindow2.NavigateToURL("https://wails.io") - myWindow.SetMinSize(600, 600) - myWindow.SetMaxSize(650, 650) - myWindow.Center() - - }() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } -} diff --git a/exp/examples/kitchensink/main.go b/exp/examples/kitchensink/main.go new file mode 100644 index 000000000..9e1f16ef3 --- /dev/null +++ b/exp/examples/kitchensink/main.go @@ -0,0 +1,161 @@ +package main + +import ( + "log" + "time" + + "github.com/wailsapp/wails/exp/pkg/application" + "github.com/wailsapp/wails/exp/pkg/events" + "github.com/wailsapp/wails/exp/pkg/options" +) + +func main() { + app := application.New(&options.Application{ + Mac: &options.Mac{ + //ActivationPolicy: options.ActivationPolicyAccessory, + }, + }) + app.On(events.Mac.ApplicationDidFinishLaunching, func() { + println("ApplicationDidFinishLaunching") + }) + app.On(events.Mac.ApplicationWillTerminate, func() { + println("ApplicationWillTerminate") + }) + app.On(events.Mac.ApplicationDidBecomeActive, func() { + println("ApplicationDidBecomeActive") + }) + app.On(events.Mac.ApplicationDidChangeBackingProperties, func() { + println("ApplicationDidChangeBackingProperties") + }) + + app.On(events.Mac.ApplicationDidChangeEffectiveAppearance, func() { + println("ApplicationDidChangeEffectiveAppearance") + }) + app.On(events.Mac.ApplicationDidHide, func() { + println("ApplicationDidHide") + }) + + myWindow := app.NewWindow(&options.Window{ + Title: "Kitchen Sink", + Width: 600, + Height: 400, + AlwaysOnTop: true, + DisableResize: false, + //MinWidth: 100, + //MinHeight: 100, + //MaxWidth: 1000, + //MaxHeight: 1000, + EnableDevTools: true, + BackgroundColour: &options.RGBA{ + Red: 255, + Green: 255, + Blue: 255, + Alpha: 30, + }, + StartState: options.WindowStateMaximised, + Mac: &options.MacWindow{ + Backdrop: options.MacBackdropTranslucent, + Appearance: options.NSAppearanceNameDarkAqua, + }, + }) + + myWindow.On(events.Mac.WindowWillClose, func() { + println(myWindow.ID(), "WindowWillClose") + }) + myWindow.On(events.Mac.WindowDidResize, func() { + println(myWindow.ID(), "WindowDidResize") + }) + myWindow.On(events.Mac.WindowDidMove, func() { + println(myWindow.ID(), "WindowDidMove") + }) + myWindow.On(events.Mac.WindowDidMiniaturize, func() { + println(myWindow.ID(), "WindowDidMiniaturize") + }) + myWindow.On(events.Mac.WindowDidDeminiaturize, func() { + println(myWindow.ID(), "WindowDidDeminiaturize") + }) + myWindow.On(events.Mac.WindowDidBecomeKey, func() { + println(myWindow.ID(), "WindowDidBecomeKey") + }) + myWindow.On(events.Mac.WindowDidResignKey, func() { + println(myWindow.ID(), "WindowDidResignKey") + }) + myWindow.On(events.Mac.WindowDidBecomeMain, func() { + println(myWindow.ID(), "WindowDidBecomeMain") + }) + myWindow.On(events.Mac.WindowDidResignMain, func() { + println(myWindow.ID(), "WindowDidResignMain") + }) + myWindow.On(events.Mac.WindowWillEnterFullScreen, func() { + println(myWindow.ID(), "WindowWillEnterFullScreen") + }) + myWindow.On(events.Mac.WindowDidEnterFullScreen, func() { + println(myWindow.ID(), "WindowDidEnterFullScreen") + }) + myWindow.On(events.Mac.WindowWillExitFullScreen, func() { + println(myWindow.ID(), "WindowWillExitFullScreen") + }) + myWindow.On(events.Mac.WindowDidExitFullScreen, func() { + println(myWindow.ID(), "WindowDidExitFullScreen") + }) + myWindow.On(events.Mac.WindowWillEnterVersionBrowser, func() { + println(myWindow.ID(), "WindowWillEnterVersionBrowser") + }) + myWindow.On(events.Mac.WindowDidEnterVersionBrowser, func() { + println(myWindow.ID(), "WindowDidEnterVersionBrowser") + }) + myWindow.On(events.Mac.WindowWillExitVersionBrowser, func() { + println(myWindow.ID(), "WindowWillExitVersionBrowser") + }) + myWindow.On(events.Mac.WindowDidExitVersionBrowser, func() { + println(myWindow.ID(), "WindowDidExitVersionBrowser") + }) + + var myWindow2 *application.Window + go func() { + time.Sleep(2 * time.Second) + myWindow2 = app.NewWindow(&options.Window{ + Title: "#2", + Width: 1024, + Height: 768, + AlwaysOnTop: false, + URL: "https://google.com", + DisableResize: true, + Mac: &options.MacWindow{ + Backdrop: options.MacBackdropTranslucent, + }, + }) + + }() + + go func() { + for { + time.Sleep(5 * time.Second) + println("window 1 is fullscreen?", myWindow.IsFullscreen()) + println("window 2 is fullscreen?", myWindow2.IsFullscreen()) + println("window 1 is maximised?", myWindow.IsMaximised()) + println("window 2 is maximised?", myWindow2.IsMaximised()) + println("window 1 is minimised?", myWindow.IsMinimised()) + println("window 2 is minimised?", myWindow2.IsMinimised()) + } + }() + + go func() { + time.Sleep(5 * time.Second) + myWindow.SetTitle("Wooooo") + myWindow.SetAlwaysOnTop(true) + myWindow2.EnableDevTools() + myWindow2.SetTitle("OMFG") + myWindow2.NavigateToURL("https://wails.io") + myWindow.SetMinSize(600, 600) + myWindow.SetMaxSize(650, 650) + myWindow.Center() + + }() + + err := app.Run() + + if err != nil { + log.Fatal(err) + } +} diff --git a/exp/pkg/application/app_delegate.m b/exp/pkg/application/app_delegate.m index 7e10942db..55c4a9390 100644 --- a/exp/pkg/application/app_delegate.m +++ b/exp/pkg/application/app_delegate.m @@ -16,94 +16,96 @@ [NSApp activateIgnoringOtherApps:YES]; //callOnApplicationDidFinishLaunchingHandler(); - systemEventHandler(EventApplicationDidFinishLaunching); + applicationEventHandler(EventApplicationDidFinishLaunching); } + - (void)setApplicationActivationPolicy:(NSApplicationActivationPolicy)policy { self.activationPolicy = policy; } -- (void)applicationWillTerminate:(NSNotification *)aNotification -{ - systemEventHandler(EventApplicationWillTerminate); +// GENERATED EVENTS START +- (void)applicationDidBecomeActive:(NSNotification *)notification { + applicationEventHandler(EventApplicationDidBecomeActive); } -- (void)applicationDidBecomeActive:(NSNotification *)aNotification -{ - systemEventHandler(EventApplicationDidBecomeActive); +- (void)applicationDidChangeBackingProperties:(NSNotification *)notification { + applicationEventHandler(EventApplicationDidChangeBackingProperties); } -- (void)applicationWillHide:(NSNotification *)aNotification -{ - systemEventHandler(EventApplicationWillHide); +- (void)applicationDidChangeEffectiveAppearance:(NSNotification *)notification { + applicationEventHandler(EventApplicationDidChangeEffectiveAppearance); } -- (void)applicationDidHide:(NSNotification *)aNotification -{ - systemEventHandler(EventApplicationDidHide); +- (void)applicationDidChangeIcon:(NSNotification *)notification { + applicationEventHandler(EventApplicationDidChangeIcon); } -- (void)applicationWillUnhide:(NSNotification *)aNotification -{ - systemEventHandler(EventApplicationWillUnhide); +- (void)applicationDidChangeOcclusionState:(NSNotification *)notification { + applicationEventHandler(EventApplicationDidChangeOcclusionState); } -- (void)applicationDidUnhide:(NSNotification *)aNotification -{ - systemEventHandler(EventApplicationDidUnhide); +- (void)applicationDidChangeScreenParameters:(NSNotification *)notification { + applicationEventHandler(EventApplicationDidChangeScreenParameters); } -- (void)applicationWillResignActive:(NSNotification *)aNotification -{ - systemEventHandler(EventApplicationWillResignActive); +- (void)applicationDidChangeStatusBarFrame:(NSNotification *)notification { + applicationEventHandler(EventApplicationDidChangeStatusBarFrame); } -- (void)applicationWillUpdate:(NSNotification *)aNotification -{ - systemEventHandler(EventApplicationWillUpdate); +- (void)applicationDidChangeStatusBarOrientation:(NSNotification *)notification { + applicationEventHandler(EventApplicationDidChangeStatusBarOrientation); } -- (void)applicationDidUpdate:(NSNotification *)aNotification -{ - systemEventHandler(EventApplicationDidUpdate); +- (void)applicationDidHide:(NSNotification *)notification { + applicationEventHandler(EventApplicationDidHide); } -- (void)applicationDidChangeScreenParameters:(NSNotification *)aNotification -{ - systemEventHandler(EventApplicationDidChangeScreenParameters); +- (void)applicationDidResignActive:(NSNotification *)notification { + applicationEventHandler(EventApplicationDidResignActive); } -- (void)applicationDidChangeOcclusionState:(NSNotification *)aNotification -{ - systemEventHandler(EventApplicationDidChangeOcclusionState); +- (void)applicationDidUnhide:(NSNotification *)notification { + applicationEventHandler(EventApplicationDidUnhide); } -- (void)applicationDidChangeBackingProperties:(NSNotification *)aNotification -{ - systemEventHandler(EventApplicationDidChangeBackingProperties); +- (void)applicationDidUpdate:(NSNotification *)notification { + applicationEventHandler(EventApplicationDidUpdate); } -- (void)applicationDidChangeIcon:(NSNotification *)aNotification -{ - systemEventHandler(EventApplicationDidChangeIcon); +- (void)applicationWillBecomeActive:(NSNotification *)notification { + applicationEventHandler(EventApplicationWillBecomeActive); } -- (void)applicationDidChangeEffectiveAppearance:(NSNotification *)aNotification -{ - systemEventHandler(EventApplicationDidChangeEffectiveAppearance); +- (void)applicationWillFinishLaunching:(NSNotification *)notification { + applicationEventHandler(EventApplicationWillFinishLaunching); } -- (void)applicationDidChangeStatusBarOrientation:(NSNotification *)aNotification -{ - systemEventHandler(EventApplicationDidChangeStatusBarOrientation); +- (void)applicationWillHide:(NSNotification *)notification { + applicationEventHandler(EventApplicationWillHide); } -- (void)applicationDidChangeStatusBarFrame:(NSNotification *)aNotification -{ - systemEventHandler(EventApplicationDidChangeStatusBarFrame); +- (void)applicationWillResignActive:(NSNotification *)notification { + applicationEventHandler(EventApplicationWillResignActive); } +- (void)applicationWillTerminate:(NSNotification *)notification { + applicationEventHandler(EventApplicationWillTerminate); +} + +- (void)applicationWillUnhide:(NSNotification *)notification { + applicationEventHandler(EventApplicationWillUnhide); +} + +- (void)applicationWillUpdate:(NSNotification *)notification { + applicationEventHandler(EventApplicationWillUpdate); +} + +// GENERATED EVENTS END + +@end + + -@end \ No newline at end of file diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index 8f01314d5..62c443db2 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -19,8 +19,8 @@ type Application interface { } type App struct { - options *options.Application - systemEventListeners map[string][]func() + options *options.Application + applicationEventListeners map[uint][]func() windows map[uint]*Window @@ -28,8 +28,8 @@ type App struct { running bool } -func (a *App) On(s string, callback func()) { - a.systemEventListeners[s] = append(a.systemEventListeners[s], callback) +func (a *App) On(eventID uint, callback func()) { + a.applicationEventListeners[eventID] = append(a.applicationEventListeners[eventID], callback) } func (a *App) NewWindow(options *options.Window) *Window { @@ -59,8 +59,14 @@ func (a *App) Run() error { a.running = true go func() { for { - event := <-systemEvents - a.handleSystemEvent(event) + event := <-applicationEvents + a.handleApplicationEvent(event) + } + }() + go func() { + for { + event := <-windowEvents + a.handleWindowEvent(event) } }() go func() { @@ -88,3 +94,13 @@ func (a *App) handleMessage(event *windowMessage) { // Get callback from window window.handleMessage(event.message) } + +func (a *App) handleWindowEvent(event *WindowEvent) { + // Get window from window map + window, ok := a.windows[event.WindowID] + if !ok { + log.Printf("Window #%d not found", event.WindowID) + return + } + window.handleWindowEvent(event.EventID) +} diff --git a/exp/pkg/application/application_darwin.go b/exp/pkg/application/application_darwin.go index 19dc7e264..aa2ec7a79 100644 --- a/exp/pkg/application/application_darwin.go +++ b/exp/pkg/application/application_darwin.go @@ -20,8 +20,8 @@ func New(options *options.Application) *App { C.SetActivationPolicy(C.int(options.Mac.ActivationPolicy)) } return &App{ - options: options, - systemEventListeners: make(map[string][]func()), + options: options, + applicationEventListeners: make(map[uint][]func()), } } @@ -30,8 +30,8 @@ func (a *App) run() error { return nil } -func (a *App) handleSystemEvent(event string) { - listeners, ok := a.systemEventListeners[event] +func (a *App) handleApplicationEvent(event uint) { + listeners, ok := a.applicationEventListeners[event] if !ok { return } @@ -40,10 +40,17 @@ func (a *App) handleSystemEvent(event string) { } } -//export systemEventHandler -func systemEventHandler(name *C.char) { - goString := C.GoString(name) - systemEvents <- goString +//export applicationEventHandler +func applicationEventHandler(eventID C.uint) { + applicationEvents <- uint(eventID) +} + +//export windowEventHandler +func windowEventHandler(windowID C.uint, eventID C.uint) { + windowEvents <- &WindowEvent{ + WindowID: uint(windowID), + EventID: uint(eventID), + } } //export processMessage diff --git a/exp/pkg/application/events.go b/exp/pkg/application/events.go index cd3d7cd4e..6732fb500 100644 --- a/exp/pkg/application/events.go +++ b/exp/pkg/application/events.go @@ -1,3 +1,10 @@ package application -var systemEvents = make(chan string) +var applicationEvents = make(chan uint) + +type WindowEvent struct { + WindowID uint + EventID uint +} + +var windowEvents = make(chan *WindowEvent) diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index b0df941c9..c91ad4a7d 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -33,6 +33,8 @@ type Window struct { options *options.Window impl windowImpl id uint + + eventListeners map[uint][]func() } var windowID uint @@ -47,8 +49,9 @@ func getWindowID() uint { func NewWindow(options *options.Window) *Window { return &Window{ - id: getWindowID(), - options: options, + id: getWindowID(), + options: options, + eventListeners: make(map[uint][]func()), } } @@ -217,3 +220,17 @@ func (w *Window) Center() { } w.impl.center() } + +func (w *Window) On(eventID uint, callback func()) { + w.eventListeners[eventID] = append(w.eventListeners[eventID], callback) +} + +func (w *Window) handleWindowEvent(id uint) { + for _, callback := range w.eventListeners[id] { + callback() + } +} + +func (w *Window) ID() uint { + return w.id +} diff --git a/exp/pkg/application/window_delegate.m b/exp/pkg/application/window_delegate.m index 41774038d..1b50ea7f3 100644 --- a/exp/pkg/application/window_delegate.m +++ b/exp/pkg/application/window_delegate.m @@ -9,6 +9,7 @@ #import #import #import "window_delegate.h" +#import "../events/events.h" @implementation WindowDelegate - (BOOL)windowShouldClose:(NSWindow *)sender { @@ -41,6 +42,310 @@ processMessage(self.windowId, _m); } +// GENERATED EVENTS START +- (void)windowDidBecomeKey:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidBecomeKey); +} +- (void)windowDidBecomeMain:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidBecomeMain); +} + +- (void)windowDidBeginSheet:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidBeginSheet); +} + +- (void)windowDidChangeAlpha:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidChangeAlpha); +} + +- (void)windowDidChangeBackingLocation:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidChangeBackingLocation); +} + +- (void)windowDidChangeBackingProperties:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidChangeBackingProperties); +} + +- (void)windowDidChangeCollectionBehavior:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidChangeCollectionBehavior); +} + +- (void)windowDidChangeEffectiveAppearance:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidChangeEffectiveAppearance); +} + +- (void)windowDidChangeOcclusionState:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidChangeOcclusionState); +} + +- (void)windowDidChangeOrderingMode:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidChangeOrderingMode); +} + +- (void)windowDidChangeScreen:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidChangeScreen); +} + +- (void)windowDidChangeScreenParameters:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidChangeScreenParameters); +} + +- (void)windowDidChangeScreenProfile:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidChangeScreenProfile); +} + +- (void)windowDidChangeScreenSpace:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidChangeScreenSpace); +} + +- (void)windowDidChangeScreenSpaceProperties:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidChangeScreenSpaceProperties); +} + +- (void)windowDidChangeSharingType:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidChangeSharingType); +} + +- (void)windowDidChangeSpace:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidChangeSpace); +} + +- (void)windowDidChangeSpaceOrderingMode:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidChangeSpaceOrderingMode); +} + +- (void)windowDidChangeTitle:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidChangeTitle); +} + +- (void)windowDidChangeToolbar:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidChangeToolbar); +} + +- (void)windowDidChangeVisibility:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidChangeVisibility); +} + +- (void)windowDidClose:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidClose); +} + +- (void)windowDidDeminiaturize:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidDeminiaturize); +} + +- (void)windowDidEndSheet:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidEndSheet); +} + +- (void)windowDidEnterFullScreen:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidEnterFullScreen); +} + +- (void)windowDidEnterVersionBrowser:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidEnterVersionBrowser); +} + +- (void)windowDidExitFullScreen:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidExitFullScreen); +} + +- (void)windowDidExitVersionBrowser:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidExitVersionBrowser); +} + +- (void)windowDidExpose:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidExpose); +} + +- (void)windowDidFocus:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidFocus); +} + +- (void)windowDidMiniaturize:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidMiniaturize); +} + +- (void)windowDidMove:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidMove); +} + +- (void)windowDidOrderOffScreen:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidOrderOffScreen); +} + +- (void)windowDidOrderOnScreen:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidOrderOnScreen); +} + +- (void)windowDidResignKey:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidResignKey); +} + +- (void)windowDidResignMain:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidResignMain); +} + +- (void)windowDidResize:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidResize); +} + +- (void)windowDidUnfocus:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidUnfocus); +} + +- (void)windowDidUpdate:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidUpdate); +} + +- (void)windowDidUpdateAlpha:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidUpdateAlpha); +} + +- (void)windowDidUpdateCollectionBehavior:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidUpdateCollectionBehavior); +} + +- (void)windowDidUpdateCollectionProperties:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidUpdateCollectionProperties); +} + +- (void)windowDidUpdateShadow:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidUpdateShadow); +} + +- (void)windowDidUpdateTitle:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidUpdateTitle); +} + +- (void)windowDidUpdateToolbar:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidUpdateToolbar); +} + +- (void)windowDidUpdateVisibility:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowDidUpdateVisibility); +} + +- (void)windowWillBecomeKey:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillBecomeKey); +} + +- (void)windowWillBecomeMain:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillBecomeMain); +} + +- (void)windowWillBeginSheet:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillBeginSheet); +} + +- (void)windowWillChangeOrderingMode:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillChangeOrderingMode); +} + +- (void)windowWillClose:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillClose); +} + +- (void)windowWillDeminiaturize:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillDeminiaturize); +} + +- (void)windowWillEnterFullScreen:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillEnterFullScreen); +} + +- (void)windowWillEnterVersionBrowser:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillEnterVersionBrowser); +} + +- (void)windowWillExitFullScreen:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillExitFullScreen); +} + +- (void)windowWillExitVersionBrowser:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillExitVersionBrowser); +} + +- (void)windowWillFocus:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillFocus); +} + +- (void)windowWillMiniaturize:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillMiniaturize); +} + +- (void)windowWillMove:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillMove); +} + +- (void)windowWillOrderOffScreen:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillOrderOffScreen); +} + +- (void)windowWillOrderOnScreen:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillOrderOnScreen); +} + +- (void)windowWillResignMain:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillResignMain); +} + +- (void)windowWillResize:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillResize); +} + +- (void)windowWillUnfocus:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillUnfocus); +} + +- (void)windowWillUpdate:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillUpdate); +} + +- (void)windowWillUpdateAlpha:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillUpdateAlpha); +} + +- (void)windowWillUpdateCollectionBehavior:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillUpdateCollectionBehavior); +} + +- (void)windowWillUpdateCollectionProperties:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillUpdateCollectionProperties); +} + +- (void)windowWillUpdateShadow:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillUpdateShadow); +} + +- (void)windowWillUpdateTitle:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillUpdateTitle); +} + +- (void)windowWillUpdateToolbar:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillUpdateToolbar); +} + +- (void)windowWillUpdateVisibility:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillUpdateVisibility); +} + +- (void)windowWillUseStandardFrame:(NSNotification *)notification { + windowEventHandler(self.windowId, EventWindowWillUseStandardFrame); +} + +// GENERATED EVENTS END @end + + + + + + + + + + + diff --git a/exp/pkg/events/events.go b/exp/pkg/events/events.go index d4cb6a1d0..5ecb93aa1 100644 --- a/exp/pkg/events/events.go +++ b/exp/pkg/events/events.go @@ -3,49 +3,195 @@ package events var Mac = newMacEvents() type macEvents struct { - ApplicationWillFinishLaunching string - ApplicationDidFinishLaunching string - ApplicationWillBecomeActive string - ApplicationDidBecomeActive string - ApplicationWillUpdate string - ApplicationDidUpdate string - ApplicationWillHide string - ApplicationDidHide string - ApplicationWillUnhide string - ApplicationDidUnhide string - ApplicationWillResignActive string - ApplicationDidResignActive string - ApplicationWillTerminate string - ApplicationDidChangeOcclusionState string - ApplicationDidChangeScreenParameters string - ApplicationDidChangeBackingProperties string - ApplicationDidChangeIcon string - ApplicationDidChangeStatusBarOrientation string - ApplicationDidChangeStatusBarFrame string - ApplicationDidChangeEffectiveAppearance string + ApplicationDidBecomeActive uint + ApplicationDidChangeBackingProperties uint + ApplicationDidChangeEffectiveAppearance uint + ApplicationDidChangeIcon uint + ApplicationDidChangeOcclusionState uint + ApplicationDidChangeScreenParameters uint + ApplicationDidChangeStatusBarFrame uint + ApplicationDidChangeStatusBarOrientation uint + ApplicationDidFinishLaunching uint + ApplicationDidHide uint + ApplicationDidResignActive uint + ApplicationDidUnhide uint + ApplicationDidUpdate uint + ApplicationWillBecomeActive uint + ApplicationWillFinishLaunching uint + ApplicationWillHide uint + ApplicationWillResignActive uint + ApplicationWillTerminate uint + ApplicationWillUnhide uint + ApplicationWillUpdate uint + WindowDidBecomeKey uint + WindowDidBecomeMain uint + WindowDidBeginSheet uint + WindowDidChangeAlpha uint + WindowDidChangeBackingLocation uint + WindowDidChangeBackingProperties uint + WindowDidChangeCollectionBehavior uint + WindowDidChangeEffectiveAppearance uint + WindowDidChangeOcclusionState uint + WindowDidChangeOrderingMode uint + WindowDidChangeScreen uint + WindowDidChangeScreenParameters uint + WindowDidChangeScreenProfile uint + WindowDidChangeScreenSpace uint + WindowDidChangeScreenSpaceProperties uint + WindowDidChangeSharingType uint + WindowDidChangeSpace uint + WindowDidChangeSpaceOrderingMode uint + WindowDidChangeTitle uint + WindowDidChangeToolbar uint + WindowDidChangeVisibility uint + WindowDidClose uint + WindowDidDeminiaturize uint + WindowDidEndSheet uint + WindowDidEnterFullScreen uint + WindowDidEnterVersionBrowser uint + WindowDidExitFullScreen uint + WindowDidExitVersionBrowser uint + WindowDidExpose uint + WindowDidFocus uint + WindowDidMiniaturize uint + WindowDidMove uint + WindowDidOrderOffScreen uint + WindowDidOrderOnScreen uint + WindowDidResignKey uint + WindowDidResignMain uint + WindowDidResize uint + WindowDidUnfocus uint + WindowDidUpdate uint + WindowDidUpdateAlpha uint + WindowDidUpdateCollectionBehavior uint + WindowDidUpdateCollectionProperties uint + WindowDidUpdateShadow uint + WindowDidUpdateTitle uint + WindowDidUpdateToolbar uint + WindowDidUpdateVisibility uint + WindowWillBecomeKey uint + WindowWillBecomeMain uint + WindowWillBeginSheet uint + WindowWillChangeOrderingMode uint + WindowWillClose uint + WindowWillDeminiaturize uint + WindowWillEnterFullScreen uint + WindowWillEnterVersionBrowser uint + WindowWillExitFullScreen uint + WindowWillExitVersionBrowser uint + WindowWillFocus uint + WindowWillMiniaturize uint + WindowWillMove uint + WindowWillOrderOffScreen uint + WindowWillOrderOnScreen uint + WindowWillResignMain uint + WindowWillResize uint + WindowWillUnfocus uint + WindowWillUpdate uint + WindowWillUpdateAlpha uint + WindowWillUpdateCollectionBehavior uint + WindowWillUpdateCollectionProperties uint + WindowWillUpdateShadow uint + WindowWillUpdateTitle uint + WindowWillUpdateToolbar uint + WindowWillUpdateVisibility uint + WindowWillUseStandardFrame uint } func newMacEvents() macEvents { return macEvents{ - ApplicationWillFinishLaunching: "mac:ApplicationWillFinishLaunching", - ApplicationDidFinishLaunching: "mac:ApplicationDidFinishLaunching", - ApplicationWillBecomeActive: "mac:ApplicationWillBecomeActive", - ApplicationDidBecomeActive: "mac:ApplicationDidBecomeActive", - ApplicationWillUpdate: "mac:ApplicationWillUpdate", - ApplicationDidUpdate: "mac:ApplicationDidUpdate", - ApplicationWillHide: "mac:ApplicationWillHide", - ApplicationDidHide: "mac:ApplicationDidHide", - ApplicationWillUnhide: "mac:ApplicationWillUnhide", - ApplicationDidUnhide: "mac:ApplicationDidUnhide", - ApplicationWillResignActive: "mac:ApplicationWillResignActive", - ApplicationDidResignActive: "mac:ApplicationDidResignActive", - ApplicationWillTerminate: "mac:ApplicationWillTerminate", - ApplicationDidChangeOcclusionState: "mac:ApplicationDidChangeOcclusionState", - ApplicationDidChangeScreenParameters: "mac:ApplicationDidChangeScreenParameters", - ApplicationDidChangeBackingProperties: "mac:ApplicationDidChangeBackingProperties", - ApplicationDidChangeIcon: "mac:ApplicationDidChangeIcon", - ApplicationDidChangeStatusBarOrientation: "mac:ApplicationDidChangeStatusBarOrientation", - ApplicationDidChangeStatusBarFrame: "mac:ApplicationDidChangeStatusBarFrame", - ApplicationDidChangeEffectiveAppearance: "mac:ApplicationDidChangeEffectiveAppearance", + ApplicationDidBecomeActive: 0, + ApplicationDidChangeBackingProperties: 1, + ApplicationDidChangeEffectiveAppearance: 2, + ApplicationDidChangeIcon: 3, + ApplicationDidChangeOcclusionState: 4, + ApplicationDidChangeScreenParameters: 5, + ApplicationDidChangeStatusBarFrame: 6, + ApplicationDidChangeStatusBarOrientation: 7, + ApplicationDidFinishLaunching: 8, + ApplicationDidHide: 9, + ApplicationDidResignActive: 10, + ApplicationDidUnhide: 11, + ApplicationDidUpdate: 12, + ApplicationWillBecomeActive: 13, + ApplicationWillFinishLaunching: 14, + ApplicationWillHide: 15, + ApplicationWillResignActive: 16, + ApplicationWillTerminate: 17, + ApplicationWillUnhide: 18, + ApplicationWillUpdate: 19, + WindowDidBecomeKey: 20, + WindowDidBecomeMain: 21, + WindowDidBeginSheet: 22, + WindowDidChangeAlpha: 23, + WindowDidChangeBackingLocation: 24, + WindowDidChangeBackingProperties: 25, + WindowDidChangeCollectionBehavior: 26, + WindowDidChangeEffectiveAppearance: 27, + WindowDidChangeOcclusionState: 28, + WindowDidChangeOrderingMode: 29, + WindowDidChangeScreen: 30, + WindowDidChangeScreenParameters: 31, + WindowDidChangeScreenProfile: 32, + WindowDidChangeScreenSpace: 33, + WindowDidChangeScreenSpaceProperties: 34, + WindowDidChangeSharingType: 35, + WindowDidChangeSpace: 36, + WindowDidChangeSpaceOrderingMode: 37, + WindowDidChangeTitle: 38, + WindowDidChangeToolbar: 39, + WindowDidChangeVisibility: 40, + WindowDidClose: 41, + WindowDidDeminiaturize: 42, + WindowDidEndSheet: 43, + WindowDidEnterFullScreen: 44, + WindowDidEnterVersionBrowser: 45, + WindowDidExitFullScreen: 46, + WindowDidExitVersionBrowser: 47, + WindowDidExpose: 48, + WindowDidFocus: 49, + WindowDidMiniaturize: 50, + WindowDidMove: 51, + WindowDidOrderOffScreen: 52, + WindowDidOrderOnScreen: 53, + WindowDidResignKey: 54, + WindowDidResignMain: 55, + WindowDidResize: 56, + WindowDidUnfocus: 57, + WindowDidUpdate: 58, + WindowDidUpdateAlpha: 59, + WindowDidUpdateCollectionBehavior: 60, + WindowDidUpdateCollectionProperties: 61, + WindowDidUpdateShadow: 62, + WindowDidUpdateTitle: 63, + WindowDidUpdateToolbar: 64, + WindowDidUpdateVisibility: 65, + WindowWillBecomeKey: 66, + WindowWillBecomeMain: 67, + WindowWillBeginSheet: 68, + WindowWillChangeOrderingMode: 69, + WindowWillClose: 70, + WindowWillDeminiaturize: 71, + WindowWillEnterFullScreen: 72, + WindowWillEnterVersionBrowser: 73, + WindowWillExitFullScreen: 74, + WindowWillExitVersionBrowser: 75, + WindowWillFocus: 76, + WindowWillMiniaturize: 77, + WindowWillMove: 78, + WindowWillOrderOffScreen: 79, + WindowWillOrderOnScreen: 80, + WindowWillResignMain: 81, + WindowWillResize: 82, + WindowWillUnfocus: 83, + WindowWillUpdate: 84, + WindowWillUpdateAlpha: 85, + WindowWillUpdateCollectionBehavior: 86, + WindowWillUpdateCollectionProperties: 87, + WindowWillUpdateShadow: 88, + WindowWillUpdateTitle: 89, + WindowWillUpdateToolbar: 90, + WindowWillUpdateVisibility: 91, + WindowWillUseStandardFrame: 92, } } diff --git a/exp/pkg/events/events.h b/exp/pkg/events/events.h index 192bc4964..de249b749 100644 --- a/exp/pkg/events/events.h +++ b/exp/pkg/events/events.h @@ -3,28 +3,102 @@ #ifndef _events_h #define _events_h -extern void systemEventHandler(char*); +extern void applicationEventHandler(unsigned int); +extern void windowEventHandler(unsigned int, unsigned int); -#define EventApplicationWillFinishLaunching "mac:ApplicationWillFinishLaunching" -#define EventApplicationDidFinishLaunching "mac:ApplicationDidFinishLaunching" -#define EventApplicationWillBecomeActive "mac:ApplicationWillBecomeActive" -#define EventApplicationDidBecomeActive "mac:ApplicationDidBecomeActive" -#define EventApplicationWillUpdate "mac:ApplicationWillUpdate" -#define EventApplicationDidUpdate "mac:ApplicationDidUpdate" -#define EventApplicationWillHide "mac:ApplicationWillHide" -#define EventApplicationDidHide "mac:ApplicationDidHide" -#define EventApplicationWillUnhide "mac:ApplicationWillUnhide" -#define EventApplicationDidUnhide "mac:ApplicationDidUnhide" -#define EventApplicationWillResignActive "mac:ApplicationWillResignActive" -#define EventApplicationDidResignActive "mac:ApplicationDidResignActive" -#define EventApplicationWillTerminate "mac:ApplicationWillTerminate" -#define EventApplicationDidChangeOcclusionState "mac:ApplicationDidChangeOcclusionState" -#define EventApplicationDidChangeScreenParameters "mac:ApplicationDidChangeScreenParameters" -#define EventApplicationDidChangeBackingProperties "mac:ApplicationDidChangeBackingProperties" -#define EventApplicationDidChangeIcon "mac:ApplicationDidChangeIcon" -#define EventApplicationDidChangeStatusBarOrientation "mac:ApplicationDidChangeStatusBarOrientation" -#define EventApplicationDidChangeStatusBarFrame "mac:ApplicationDidChangeStatusBarFrame" -#define EventApplicationDidChangeEffectiveAppearance "mac:ApplicationDidChangeEffectiveAppearance" +#define EventApplicationDidBecomeActive 0 +#define EventApplicationDidChangeBackingProperties 1 +#define EventApplicationDidChangeEffectiveAppearance 2 +#define EventApplicationDidChangeIcon 3 +#define EventApplicationDidChangeOcclusionState 4 +#define EventApplicationDidChangeScreenParameters 5 +#define EventApplicationDidChangeStatusBarFrame 6 +#define EventApplicationDidChangeStatusBarOrientation 7 +#define EventApplicationDidFinishLaunching 8 +#define EventApplicationDidHide 9 +#define EventApplicationDidResignActive 10 +#define EventApplicationDidUnhide 11 +#define EventApplicationDidUpdate 12 +#define EventApplicationWillBecomeActive 13 +#define EventApplicationWillFinishLaunching 14 +#define EventApplicationWillHide 15 +#define EventApplicationWillResignActive 16 +#define EventApplicationWillTerminate 17 +#define EventApplicationWillUnhide 18 +#define EventApplicationWillUpdate 19 +#define EventWindowDidBecomeKey 20 +#define EventWindowDidBecomeMain 21 +#define EventWindowDidBeginSheet 22 +#define EventWindowDidChangeAlpha 23 +#define EventWindowDidChangeBackingLocation 24 +#define EventWindowDidChangeBackingProperties 25 +#define EventWindowDidChangeCollectionBehavior 26 +#define EventWindowDidChangeEffectiveAppearance 27 +#define EventWindowDidChangeOcclusionState 28 +#define EventWindowDidChangeOrderingMode 29 +#define EventWindowDidChangeScreen 30 +#define EventWindowDidChangeScreenParameters 31 +#define EventWindowDidChangeScreenProfile 32 +#define EventWindowDidChangeScreenSpace 33 +#define EventWindowDidChangeScreenSpaceProperties 34 +#define EventWindowDidChangeSharingType 35 +#define EventWindowDidChangeSpace 36 +#define EventWindowDidChangeSpaceOrderingMode 37 +#define EventWindowDidChangeTitle 38 +#define EventWindowDidChangeToolbar 39 +#define EventWindowDidChangeVisibility 40 +#define EventWindowDidClose 41 +#define EventWindowDidDeminiaturize 42 +#define EventWindowDidEndSheet 43 +#define EventWindowDidEnterFullScreen 44 +#define EventWindowDidEnterVersionBrowser 45 +#define EventWindowDidExitFullScreen 46 +#define EventWindowDidExitVersionBrowser 47 +#define EventWindowDidExpose 48 +#define EventWindowDidFocus 49 +#define EventWindowDidMiniaturize 50 +#define EventWindowDidMove 51 +#define EventWindowDidOrderOffScreen 52 +#define EventWindowDidOrderOnScreen 53 +#define EventWindowDidResignKey 54 +#define EventWindowDidResignMain 55 +#define EventWindowDidResize 56 +#define EventWindowDidUnfocus 57 +#define EventWindowDidUpdate 58 +#define EventWindowDidUpdateAlpha 59 +#define EventWindowDidUpdateCollectionBehavior 60 +#define EventWindowDidUpdateCollectionProperties 61 +#define EventWindowDidUpdateShadow 62 +#define EventWindowDidUpdateTitle 63 +#define EventWindowDidUpdateToolbar 64 +#define EventWindowDidUpdateVisibility 65 +#define EventWindowWillBecomeKey 66 +#define EventWindowWillBecomeMain 67 +#define EventWindowWillBeginSheet 68 +#define EventWindowWillChangeOrderingMode 69 +#define EventWindowWillClose 70 +#define EventWindowWillDeminiaturize 71 +#define EventWindowWillEnterFullScreen 72 +#define EventWindowWillEnterVersionBrowser 73 +#define EventWindowWillExitFullScreen 74 +#define EventWindowWillExitVersionBrowser 75 +#define EventWindowWillFocus 76 +#define EventWindowWillMiniaturize 77 +#define EventWindowWillMove 78 +#define EventWindowWillOrderOffScreen 79 +#define EventWindowWillOrderOnScreen 80 +#define EventWindowWillResignMain 81 +#define EventWindowWillResize 82 +#define EventWindowWillUnfocus 83 +#define EventWindowWillUpdate 84 +#define EventWindowWillUpdateAlpha 85 +#define EventWindowWillUpdateCollectionBehavior 86 +#define EventWindowWillUpdateCollectionProperties 87 +#define EventWindowWillUpdateShadow 88 +#define EventWindowWillUpdateTitle 89 +#define EventWindowWillUpdateToolbar 90 +#define EventWindowWillUpdateVisibility 91 +#define EventWindowWillUseStandardFrame 92 #endif \ No newline at end of file diff --git a/exp/pkg/events/events.txt b/exp/pkg/events/events.txt index be917db2c..4929170a5 100644 --- a/exp/pkg/events/events.txt +++ b/exp/pkg/events/events.txt @@ -1,20 +1,93 @@ -mac:ApplicationWillFinishLaunching -mac:ApplicationDidFinishLaunching -mac:ApplicationWillBecomeActive mac:ApplicationDidBecomeActive -mac:ApplicationWillUpdate -mac:ApplicationDidUpdate -mac:ApplicationWillHide -mac:ApplicationDidHide -mac:ApplicationWillUnhide -mac:ApplicationDidUnhide -mac:ApplicationWillResignActive -mac:ApplicationDidResignActive -mac:ApplicationWillTerminate +mac:ApplicationDidChangeBackingProperties +mac:ApplicationDidChangeEffectiveAppearance +mac:ApplicationDidChangeIcon mac:ApplicationDidChangeOcclusionState mac:ApplicationDidChangeScreenParameters -mac:ApplicationDidChangeBackingProperties -mac:ApplicationDidChangeIcon -mac:ApplicationDidChangeStatusBarOrientation mac:ApplicationDidChangeStatusBarFrame -mac:ApplicationDidChangeEffectiveAppearance +mac:ApplicationDidChangeStatusBarOrientation +mac:ApplicationDidFinishLaunching! +mac:ApplicationDidHide +mac:ApplicationDidResignActive +mac:ApplicationDidUnhide +mac:ApplicationDidUpdate +mac:ApplicationWillBecomeActive +mac:ApplicationWillFinishLaunching +mac:ApplicationWillHide +mac:ApplicationWillResignActive +mac:ApplicationWillTerminate +mac:ApplicationWillUnhide +mac:ApplicationWillUpdate +mac:WindowDidBecomeKey +mac:WindowDidBecomeMain +mac:WindowDidBeginSheet +mac:WindowDidChangeAlpha +mac:WindowDidChangeBackingLocation +mac:WindowDidChangeBackingProperties +mac:WindowDidChangeCollectionBehavior +mac:WindowDidChangeEffectiveAppearance +mac:WindowDidChangeOcclusionState +mac:WindowDidChangeOrderingMode +mac:WindowDidChangeScreen +mac:WindowDidChangeScreenParameters +mac:WindowDidChangeScreenProfile +mac:WindowDidChangeScreenSpace +mac:WindowDidChangeScreenSpaceProperties +mac:WindowDidChangeSharingType +mac:WindowDidChangeSpace +mac:WindowDidChangeSpaceOrderingMode +mac:WindowDidChangeTitle +mac:WindowDidChangeToolbar +mac:WindowDidChangeVisibility +mac:WindowDidClose +mac:WindowDidDeminiaturize +mac:WindowDidEndSheet +mac:WindowDidEnterFullScreen +mac:WindowDidEnterVersionBrowser +mac:WindowDidExitFullScreen +mac:WindowDidExitVersionBrowser +mac:WindowDidExpose +mac:WindowDidFocus +mac:WindowDidMiniaturize +mac:WindowDidMove +mac:WindowDidOrderOffScreen +mac:WindowDidOrderOnScreen +mac:WindowDidResignKey +mac:WindowDidResignMain +mac:WindowDidResize +mac:WindowDidUnfocus +mac:WindowDidUpdate +mac:WindowDidUpdateAlpha +mac:WindowDidUpdateCollectionBehavior +mac:WindowDidUpdateCollectionProperties +mac:WindowDidUpdateShadow +mac:WindowDidUpdateTitle +mac:WindowDidUpdateToolbar +mac:WindowDidUpdateVisibility +mac:WindowWillBecomeKey +mac:WindowWillBecomeMain +mac:WindowWillBeginSheet +mac:WindowWillChangeOrderingMode +mac:WindowWillClose +mac:WindowWillDeminiaturize +mac:WindowWillEnterFullScreen +mac:WindowWillEnterVersionBrowser +mac:WindowWillExitFullScreen +mac:WindowWillExitVersionBrowser +mac:WindowWillFocus +mac:WindowWillMiniaturize +mac:WindowWillMove +mac:WindowWillOrderOffScreen +mac:WindowWillOrderOnScreen +mac:WindowWillResignMain +mac:WindowWillResize +mac:WindowWillUnfocus +mac:WindowWillUpdate +mac:WindowWillUpdateAlpha +mac:WindowWillUpdateCollectionBehavior +mac:WindowWillUpdateCollectionProperties +mac:WindowWillUpdateShadow +mac:WindowWillUpdateTitle +mac:WindowWillUpdateToolbar +mac:WindowWillUpdateVisibility +mac:WindowWillUseStandardFrame \ No newline at end of file diff --git a/exp/tasks/events/generate.go b/exp/tasks/events/generate.go index 040f8acee..f97d1cda5 100644 --- a/exp/tasks/events/generate.go +++ b/exp/tasks/events/generate.go @@ -3,6 +3,7 @@ package main import ( "bytes" "os" + "strconv" "strings" ) @@ -24,7 +25,8 @@ var eventsH = `//go:build darwin #ifndef _events_h #define _events_h -extern void systemEventHandler(char*); +extern void applicationEventHandler(unsigned int); +extern void windowEventHandler(unsigned int, unsigned int); $$CHEADEREVENTS @@ -40,9 +42,11 @@ func main() { macEventsDecl := bytes.NewBufferString("") macEventsValues := bytes.NewBufferString("") cHeaderEvents := bytes.NewBufferString("") + windowDelegateEvents := bytes.NewBufferString("") + applicationDelegateEvents := bytes.NewBufferString("") // Loop over each line in the file - for _, line := range bytes.Split(eventNames, []byte{'\n'}) { + for id, line := range bytes.Split(eventNames, []byte{'\n'}) { // Skip empty lines if len(line) == 0 { @@ -53,16 +57,41 @@ func main() { split := bytes.Split(line, []byte{':'}) platform := strings.TrimSpace(string(split[0])) event := strings.TrimSpace(string(split[1])) + var ignoreEvent bool + if strings.HasSuffix(event, "!") { + event = event[:len(event)-1] + ignoreEvent = true + } // Title case the event name eventTitle := string(bytes.ToUpper([]byte{event[0]})) + event[1:] + // delegate function name has a lowercase first character + delegateEventFunction := string(bytes.ToLower([]byte{event[0]})) + event[1:] // Add to buffer switch platform { case "mac": - macEventsDecl.WriteString("\t" + eventTitle + " string\n") - macEventsValues.WriteString("\t\t" + event + ": \"" + platform + ":" + event + "\",\n") - cHeaderEvents.WriteString("#define Event" + eventTitle + " \"" + platform + ":" + event + "\"\n") + macEventsDecl.WriteString("\t" + eventTitle + " uint\n") + macEventsValues.WriteString("\t\t" + event + ": " + strconv.Itoa(id) + ",\n") + cHeaderEvents.WriteString("#define Event" + eventTitle + " " + strconv.Itoa(id) + "\n") + if ignoreEvent { + continue + } + // Check if this is a window event + if strings.HasPrefix(event, "Window") { + windowDelegateEvents.WriteString(`- (void)` + delegateEventFunction + `:(NSNotification *)notification { + windowEventHandler(self.windowId, Event` + eventTitle + `); +} + +`) + } + if strings.HasPrefix(event, "Application") { + applicationDelegateEvents.WriteString(`- (void)` + delegateEventFunction + `:(NSNotification *)notification { + applicationEventHandler(Event` + eventTitle + `); +} + +`) + } } } @@ -82,4 +111,69 @@ func main() { panic(err) } + // Load the window_delegate.m file + windowDelegate, err := os.ReadFile("../../pkg/application/window_delegate.m") + if err != nil { + panic(err) + } + // iterate over the lines until we reach a line that says "// GENERATED EVENTS START" + // then we insert the events + // then we iterate until we reach a line that says "// GENERATED EVENTS END" + // then we write the file + var buffer bytes.Buffer + var inGeneratedEvents bool + for _, line := range bytes.Split(windowDelegate, []byte{'\n'}) { + if bytes.Contains(line, []byte("// GENERATED EVENTS START")) { + inGeneratedEvents = true + buffer.WriteString("// GENERATED EVENTS START\n") + buffer.WriteString(windowDelegateEvents.String()) + continue + } + if bytes.Contains(line, []byte("// GENERATED EVENTS END")) { + inGeneratedEvents = false + buffer.WriteString("// GENERATED EVENTS END\n") + continue + } + if !inGeneratedEvents { + buffer.Write(line) + buffer.WriteString("\n") + } + } + err = os.WriteFile("../../pkg/application/window_delegate.m", buffer.Bytes(), 0755) + if err != nil { + panic(err) + } + + // Load the app_delegate.m file + appDelegate, err := os.ReadFile("../../pkg/application/app_delegate.m") + if err != nil { + panic(err) + } + // iterate over the lines until we reach a line that says "// GENERATED EVENTS START" + // then we insert the events + // then we iterate until we reach a line that says "// GENERATED EVENTS END" + // then we write the file + buffer.Reset() + for _, line := range bytes.Split(appDelegate, []byte{'\n'}) { + if bytes.Contains(line, []byte("// GENERATED EVENTS START")) { + inGeneratedEvents = true + buffer.WriteString("// GENERATED EVENTS START\n") + buffer.WriteString(applicationDelegateEvents.String()) + continue + } + if bytes.Contains(line, []byte("// GENERATED EVENTS END")) { + inGeneratedEvents = false + buffer.WriteString("// GENERATED EVENTS END\n") + continue + } + if !inGeneratedEvents { + buffer.Write(line) + buffer.WriteString("\n") + } + } + err = os.WriteFile("../../pkg/application/app_delegate.m", buffer.Bytes(), 0755) + if err != nil { + panic(err) + } + } From ddb2f63f7b027bf1527bd98e34b76c3d5aed9dee Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 11 Dec 2022 14:39:53 +1100 Subject: [PATCH 17/85] Support Window aliases --- exp/.gitignore | 2 +- exp/pkg/application/application.go | 9 ++++++++- exp/pkg/application/window.go | 1 + exp/pkg/options/window.go | 2 ++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/exp/.gitignore b/exp/.gitignore index 3fa7f363f..5fbf23563 100644 --- a/exp/.gitignore +++ b/exp/.gitignore @@ -1,2 +1,2 @@ -examples/basic/basic +examples/kitchensink/kitchensink cmd/wails/wails \ No newline at end of file diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index 62c443db2..a2dd95210 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -22,7 +22,8 @@ type App struct { options *options.Application applicationEventListeners map[uint][]func() - windows map[uint]*Window + windows map[uint]*Window + windowAliases map[string]uint // Running running bool @@ -47,6 +48,12 @@ func (a *App) NewWindow(options *options.Window) *Window { a.windows = make(map[uint]*Window) } a.windows[id] = newWindow + if options.Alias != "" { + if a.windowAliases == nil { + a.windowAliases = make(map[string]uint) + } + a.windowAliases[options.Alias] = id + } if a.running { newWindow.Run() } diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index c91ad4a7d..b62d539ae 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -48,6 +48,7 @@ func getWindowID() uint { } func NewWindow(options *options.Window) *Window { + return &Window{ id: getWindowID(), options: options, diff --git a/exp/pkg/options/window.go b/exp/pkg/options/window.go index 8c94114c3..ae7cd923b 100644 --- a/exp/pkg/options/window.go +++ b/exp/pkg/options/window.go @@ -10,6 +10,8 @@ const ( ) type Window struct { + // Alias is a human-readable name for the window. This can be used to reference the window in the frontend. + Alias string Title string Width, Height int AlwaysOnTop bool From f6a16950f2a8ecb93c63a4cc5ebbb674d8bc8267 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 11 Dec 2022 19:57:20 +1100 Subject: [PATCH 18/85] Add Window methods Width(), Height(), Size() + Position() Fix main thread locking issue Add Window aliases --- exp/examples/kitchensink/main.go | 54 ++++++++--------- exp/pkg/application/application.go | 21 ++++++- exp/pkg/application/mainthread.go | 21 +++++-- exp/pkg/application/window.go | 58 +++++++++++++++++-- exp/pkg/application/window_darwin.go | 86 +++++++++++++++++++++++++++- 5 files changed, 195 insertions(+), 45 deletions(-) diff --git a/exp/examples/kitchensink/main.go b/exp/examples/kitchensink/main.go index 9e1f16ef3..220b2970d 100644 --- a/exp/examples/kitchensink/main.go +++ b/exp/examples/kitchensink/main.go @@ -2,6 +2,7 @@ package main import ( "log" + "sync" "time" "github.com/wailsapp/wails/exp/pkg/application" @@ -63,10 +64,12 @@ func main() { println(myWindow.ID(), "WindowWillClose") }) myWindow.On(events.Mac.WindowDidResize, func() { - println(myWindow.ID(), "WindowDidResize") + w, h := myWindow.Size() + println(myWindow.ID(), "WindowDidResize", w, h) }) myWindow.On(events.Mac.WindowDidMove, func() { - println(myWindow.ID(), "WindowDidMove") + x, y := myWindow.Position() + println(myWindow.ID(), "WindowDidMove", x, y) }) myWindow.On(events.Mac.WindowDidMiniaturize, func() { println(myWindow.ID(), "WindowDidMiniaturize") @@ -112,36 +115,28 @@ func main() { }) var myWindow2 *application.Window - go func() { - time.Sleep(2 * time.Second) - myWindow2 = app.NewWindow(&options.Window{ - Title: "#2", - Width: 1024, - Height: 768, - AlwaysOnTop: false, - URL: "https://google.com", - DisableResize: true, - Mac: &options.MacWindow{ - Backdrop: options.MacBackdropTranslucent, - }, - }) - - }() - - go func() { - for { - time.Sleep(5 * time.Second) - println("window 1 is fullscreen?", myWindow.IsFullscreen()) - println("window 2 is fullscreen?", myWindow2.IsFullscreen()) - println("window 1 is maximised?", myWindow.IsMaximised()) - println("window 2 is maximised?", myWindow2.IsMaximised()) - println("window 1 is minimised?", myWindow.IsMinimised()) - println("window 2 is minimised?", myWindow2.IsMinimised()) - } - }() + var myWindow2Lock sync.RWMutex + myWindow2 = app.NewWindow(&options.Window{ + Title: "#2", + Width: 1024, + Height: 768, + AlwaysOnTop: false, + URL: "https://google.com", + Mac: &options.MacWindow{ + Backdrop: options.MacBackdropTranslucent, + }, + }) + //myWindow2.On(events.Mac.WindowDidMove, func() { + // myWindow2Lock.RLock() + // x, y := myWindow2.Position() + // println(myWindow2.ID(), "WindowDidMove: ", x, y) + // myWindow2Lock.RUnlock() + //}) + // go func() { time.Sleep(5 * time.Second) + myWindow2Lock.RLock() myWindow.SetTitle("Wooooo") myWindow.SetAlwaysOnTop(true) myWindow2.EnableDevTools() @@ -150,6 +145,7 @@ func main() { myWindow.SetMinSize(600, 600) myWindow.SetMaxSize(650, 650) myWindow.Center() + myWindow2Lock.RUnlock() }() diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index a2dd95210..2a64fb3ed 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -2,10 +2,16 @@ package application import ( "log" + "runtime" + "sync" "github.com/wailsapp/wails/exp/pkg/options" ) +func init() { + runtime.LockOSThread() +} + // Messages sent from javascript get routed here type windowMessage struct { windowId uint @@ -22,8 +28,10 @@ type App struct { options *options.Application applicationEventListeners map[uint][]func() - windows map[uint]*Window - windowAliases map[string]uint + windows map[uint]*Window + windowsLock sync.Mutex + windowAliases map[string]uint + windowAliasesLock sync.Mutex // Running running bool @@ -47,12 +55,17 @@ func (a *App) NewWindow(options *options.Window) *Window { if a.windows == nil { a.windows = make(map[uint]*Window) } + a.windowsLock.Lock() a.windows[id] = newWindow + a.windowsLock.Unlock() + if options.Alias != "" { if a.windowAliases == nil { a.windowAliases = make(map[string]uint) } + a.windowAliasesLock.Lock() a.windowAliases[options.Alias] = id + a.windowAliasesLock.Unlock() } if a.running { newWindow.Run() @@ -93,7 +106,9 @@ func (a *App) Run() error { func (a *App) handleMessage(event *windowMessage) { // Get window from window map + a.windowsLock.Lock() window, ok := a.windows[event.windowId] + a.windowsLock.Unlock() if !ok { log.Printf("Window #%d not found", event.windowId) return @@ -104,7 +119,9 @@ func (a *App) handleMessage(event *windowMessage) { func (a *App) handleWindowEvent(event *WindowEvent) { // Get window from window map + a.windowsLock.Lock() window, ok := a.windows[event.WindowID] + a.windowsLock.Unlock() if !ok { log.Printf("Window #%d not found", event.WindowID) return diff --git a/exp/pkg/application/mainthread.go b/exp/pkg/application/mainthread.go index 4e201c71e..c91fec8b0 100644 --- a/exp/pkg/application/mainthread.go +++ b/exp/pkg/application/mainthread.go @@ -6,9 +6,13 @@ package application extern void dispatch(unsigned int id); */ import "C" -import "strconv" +import ( + "os" + "sync" +) var mainThreadFuntionStore = make(map[uint]func()) +var mainThreadFuntionStoreLock sync.RWMutex func generateFunctionStoreID() uint { startID := 0 @@ -24,18 +28,23 @@ func generateFunctionStoreID() uint { } func Dispatch(fn func()) { + mainThreadFuntionStoreLock.Lock() id := generateFunctionStoreID() mainThreadFuntionStore[id] = fn + mainThreadFuntionStoreLock.Unlock() C.dispatch(C.uint(id)) } //export dispatchCallback -func dispatchCallback(id C.uint) { - - fn := mainThreadFuntionStore[uint(id)] +func dispatchCallback(callbackID C.uint) { + mainThreadFuntionStoreLock.RLock() + id := uint(callbackID) + fn := mainThreadFuntionStore[id] if fn == nil { - panic("dispatchCallback called with invalid id " + strconv.Itoa(int(id))) + println("***** dispatchCallback called with invalid id: ", id) + os.Exit(1) } + delete(mainThreadFuntionStore, id) + mainThreadFuntionStoreLock.RUnlock() fn() - delete(mainThreadFuntionStore, uint(id)) } diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index b62d539ae..84d83cbcc 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -27,14 +27,20 @@ type windowImpl interface { setBackgroundColor(color *options.RGBA) run() center() + size() (int, int) + width() int + height() int + position() (int, int) } type Window struct { - options *options.Window - impl windowImpl - id uint + options *options.Window + impl windowImpl + implLock sync.RWMutex + id uint - eventListeners map[uint][]func() + eventListeners map[uint][]func() + eventListenersLock sync.RWMutex } var windowID uint @@ -48,7 +54,6 @@ func getWindowID() uint { } func NewWindow(options *options.Window) *Window { - return &Window{ id: getWindowID(), options: options, @@ -57,6 +62,8 @@ func NewWindow(options *options.Window) *Window { } func (w *Window) SetTitle(title string) { + w.implLock.RLock() + defer w.implLock.RUnlock() if w.impl == nil { w.options.Title = title return @@ -74,7 +81,9 @@ func (w *Window) SetSize(width, height int) { } func (w *Window) Run() { + w.implLock.Lock() w.impl = newWindowImpl(w.id, w.options) + w.implLock.Unlock() w.impl.run() } @@ -191,8 +200,18 @@ func (w *Window) IsMaximised() bool { return w.impl.isMaximised() } +// Size returns the current size of the window +func (w *Window) Size() (int, int) { + if w.impl == nil { + return 0, 0 + } + return w.impl.size() +} + // IsFullscreen returns true if the window is fullscreen func (w *Window) IsFullscreen() bool { + w.implLock.RLock() + defer w.implLock.RUnlock() if w.impl == nil { return false } @@ -223,15 +242,42 @@ func (w *Window) Center() { } func (w *Window) On(eventID uint, callback func()) { + w.eventListenersLock.Lock() w.eventListeners[eventID] = append(w.eventListeners[eventID], callback) + w.eventListenersLock.Unlock() } func (w *Window) handleWindowEvent(id uint) { + w.eventListenersLock.RLock() for _, callback := range w.eventListeners[id] { - callback() + go callback() } + w.eventListenersLock.RUnlock() } func (w *Window) ID() uint { return w.id } + +func (w *Window) Width() int { + if w.impl == nil { + return 0 + } + return w.impl.width() +} + +func (w *Window) Height() int { + if w.impl == nil { + return 0 + } + return w.impl.height() +} + +func (w *Window) Position() (int, int) { + w.implLock.RLock() + defer w.implLock.RUnlock() + if w.impl == nil { + return 0, 0 + } + return w.impl.position() +} diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index 9c9b74761..a2eb3f5bb 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -394,8 +394,47 @@ void windowCenter(void* nsWindow) { }); } +// Get the current size of the window +void windowGetSize(void* nsWindow, int* width, int* height) { + // get main window + NSWindow* window = (NSWindow*)nsWindow; + // get window frame + NSRect frame = [window frame]; + // set width and height + *width = frame.size.width; + *height = frame.size.height; +} +// Get window width +int windowGetWidth(void* nsWindow) { + // get main window + NSWindow* window = (NSWindow*)nsWindow; + // get window frame + NSRect frame = [window frame]; + // return width + return frame.size.width; +} +// Get window height +int windowGetHeight(void* nsWindow) { + // get main window + NSWindow* window = (NSWindow*)nsWindow; + // get window frame + NSRect frame = [window frame]; + // return height + return frame.size.height; +} + +// Get window position +void windowGetPosition(void* nsWindow, int* x, int* y) { + // get main window + NSWindow* window = (NSWindow*)nsWindow; + // get window frame + NSRect frame = [window frame]; + // set x and y + *x = frame.origin.x; + *y = frame.origin.y; +} */ @@ -511,6 +550,41 @@ func (w *macosWindow) enableDevTools() { C.windowEnableDevTools(w.nsWindow) } +func (w *macosWindow) size() (int, int) { + var width, height C.int + var wg sync.WaitGroup + wg.Add(1) + Dispatch(func() { + C.windowGetSize(w.nsWindow, &width, &height) + wg.Done() + }) + wg.Wait() + return int(width), int(height) +} + +func (w *macosWindow) width() int { + var width C.int + var wg sync.WaitGroup + wg.Add(1) + Dispatch(func() { + width = C.windowGetWidth(w.nsWindow) + wg.Done() + }) + wg.Wait() + return int(width) +} +func (w *macosWindow) height() int { + var height C.int + var wg sync.WaitGroup + wg.Add(1) + Dispatch(func() { + height = C.windowGetHeight(w.nsWindow) + wg.Done() + }) + wg.Wait() + return int(height) +} + func (w *macosWindow) run() { Dispatch(func() { w.nsWindow = C.windowNew(C.uint(w.id), C.int(w.options.Width), C.int(w.options.Height)) @@ -575,6 +649,14 @@ func (w *macosWindow) setBackgroundColor(colour *options.RGBA) { C.webviewSetBackgroundColor(w.nsWindow, C.int(colour.Red), C.int(colour.Green), C.int(colour.Blue), C.int(colour.Alpha)) } -func (w *macosWindow) Center() { - C.windowCenter(w.nsWindow) +func (w *macosWindow) position() (int, int) { + var x, y C.int + var wg sync.WaitGroup + wg.Add(1) + go Dispatch(func() { + C.windowGetPosition(w.nsWindow, &x, &y) + wg.Done() + }) + wg.Wait() + return int(x), int(y) } From f38c6c6d1cfe45192fa76ee85f971619a0e3f599 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 11 Dec 2022 20:05:00 +1100 Subject: [PATCH 19/85] Add Fatal() --- exp/pkg/application/errors.go | 16 ++++++++++++++++ exp/pkg/application/mainthread.go | 6 ++---- 2 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 exp/pkg/application/errors.go diff --git a/exp/pkg/application/errors.go b/exp/pkg/application/errors.go new file mode 100644 index 000000000..747142328 --- /dev/null +++ b/exp/pkg/application/errors.go @@ -0,0 +1,16 @@ +package application + +import ( + "fmt" + "os" +) + +func Fatal(message string, args ...interface{}) { + println("*********************** FATAL ***********************") + println("There has been a catastrophic failure in your application.") + println("Please report this error at https://github.com/wailsapp/wails/issues") + println("******************** Error Details ******************") + println(fmt.Sprintf(message, args...)) + println("*********************** FATAL ***********************") + os.Exit(1) +} diff --git a/exp/pkg/application/mainthread.go b/exp/pkg/application/mainthread.go index c91fec8b0..16068c39b 100644 --- a/exp/pkg/application/mainthread.go +++ b/exp/pkg/application/mainthread.go @@ -7,7 +7,6 @@ extern void dispatch(unsigned int id); */ import "C" import ( - "os" "sync" ) @@ -22,7 +21,7 @@ func generateFunctionStoreID() uint { } startID++ if startID == 0 { - panic("Too many functions stored") + Fatal("Too many functions have been dispatched to the main thread") } } } @@ -41,8 +40,7 @@ func dispatchCallback(callbackID C.uint) { id := uint(callbackID) fn := mainThreadFuntionStore[id] if fn == nil { - println("***** dispatchCallback called with invalid id: ", id) - os.Exit(1) + Fatal("dispatchCallback called with invalid id: ", id) } delete(mainThreadFuntionStore, id) mainThreadFuntionStoreLock.RUnlock() From a35a8760946451c8b8d3c07606b21ac15e0b6ed9 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Tue, 13 Dec 2022 21:54:12 +1100 Subject: [PATCH 20/85] Add support for system tray + menus --- exp/examples/kitchensink/icon.png | Bin 0 -> 1622 bytes exp/examples/kitchensink/main.go | 190 ++++++++++-------- exp/pkg/application/application.go | 52 +++++ exp/pkg/application/application_darwin.go | 6 + exp/pkg/application/context.go | 42 ++++ exp/pkg/application/events.go | 2 + exp/pkg/application/menu.go | 39 ++++ exp/pkg/application/menu_darwin.go | 71 +++++++ exp/pkg/application/menuitem.go | 132 ++++++++++++ exp/pkg/application/menuitem.h | 18 ++ exp/pkg/application/menuitem.m | 13 ++ exp/pkg/application/menuitem_darwin.go | 101 ++++++++++ exp/pkg/application/systemtray.go | 86 ++++++++ exp/pkg/application/systemtray_darwin.go | 132 ++++++++++++ exp/pkg/application/window_darwin.go | 15 ++ exp/pkg/events/events.txt | 25 ++- exp/pkg/menu/menu.go | 22 ++ exp/pkg/options/window.go | 18 ++ lib/ipc/message.go | 2 +- lib/renderer/webview.go | 4 +- .../frontend/desktop/darwin/frontend.go | 4 +- .../frontend/desktop/linux/frontend.go | 4 +- .../frontend/desktop/windows/frontend.go | 4 +- v2/internal/frontend/runtime/events.go | 2 +- v2/internal/menumanager/menumanager.go | 3 +- v2/pkg/menu/tray.go | 4 +- 26 files changed, 894 insertions(+), 97 deletions(-) create mode 100644 exp/examples/kitchensink/icon.png create mode 100644 exp/pkg/application/context.go create mode 100644 exp/pkg/application/menu.go create mode 100644 exp/pkg/application/menu_darwin.go create mode 100644 exp/pkg/application/menuitem.go create mode 100644 exp/pkg/application/menuitem.h create mode 100644 exp/pkg/application/menuitem.m create mode 100644 exp/pkg/application/menuitem_darwin.go create mode 100644 exp/pkg/application/systemtray.go create mode 100644 exp/pkg/application/systemtray_darwin.go create mode 100644 exp/pkg/menu/menu.go diff --git a/exp/examples/kitchensink/icon.png b/exp/examples/kitchensink/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..fc492c9167cce9c272f98bf99207d0efff1d1c1a GIT binary patch literal 1622 zcmV-c2C4apP)?9E5by_tm=H)BK!2&G8Wn%g z1REfMKm>jvR4h%YDEwl01TgZle?-$?nBFt(Ztk8lvpYj`ldheUe8TR%=j?p%mzjHK z?ykvXgb_v$>U*@FR5X( zImyGEK7E?h0m2M;^5luMy}j*{j*bpeS6Nv}@_1nR#x?iv-zRyPuC6Xp2M9CZ`+N6@ z2uyQxGpXzE?#axiS!mW{$10bvHTwY3o;n2L%Dr<#I-0+NHt&vQ25`t|E12Xp)O zZKBVPFavJgxrl#^2vxT3J~kIXpj2PO_&R<Ak5LDN9Ejvgap#3 zMpo9}2EZNT=H@2p=fSIt62c5Pd-g05go%oZl5<;ITS=c9Sy@?fjXQ(a*ViSR%|>)# zgc*>Uno2}rEEbEL`)cYH=~Ls}xpQ*O-Me>5AI}T6JYr2s2s0olDT#>UfeFgj*H69- za37#HCuC-3%6D}$Gc%-*r?9Y)Xi`F$0mqLYC!%=P*4E_7k9`*D1JqW9GiT07M~)mJ z?L6?=X0w@SQbL#khYuen!gv-I7UaC);bGGE?%g}7w6v7818~1^<;oS(&hzNeBcewQ zVFpA-MiOB>v$M1EB(<@zLHgi9>hk5wq#ek}$dH~seM;JS>=UIHgc-1J-##LYXKHFn zD!Futv;(J3rK_F+a0x6fE|PXTaAv`6HP)ksFazKkgozFdv@<$7Dm{DljI=K;ElGZU zeo|Rk8R-LV-n>cLcwlwFT3jK_0QfJsdbS4xV6wvP4(y?hhlYko8xK4mU@fi? zW&kWztE;O-pdB@H>^nYc6P;Qe@b>Ln$;ZcsXmN!w1AzDM-xHCp`0(L_6ciLB*IvDP zmGrvT0ICg zz!NYG*o^^fg8Bwtehvig=68aVlapVv>+er^>*=t$WQL8&Y|;~~U~fc3#IWg~pPPCp zvi9WU$x zvFrgX?%%(EA}uYgijBbnmoy%m=73^`A6!EWDJj4;9oBmQUc7aDot UG_K_hc>n+a07*qoM6N<$g0pSuE&u=k literal 0 HcmV?d00001 diff --git a/exp/examples/kitchensink/main.go b/exp/examples/kitchensink/main.go index 220b2970d..4c4c12c0e 100644 --- a/exp/examples/kitchensink/main.go +++ b/exp/examples/kitchensink/main.go @@ -1,51 +1,75 @@ package main import ( + _ "embed" "log" "sync" "time" "github.com/wailsapp/wails/exp/pkg/application" - "github.com/wailsapp/wails/exp/pkg/events" "github.com/wailsapp/wails/exp/pkg/options" ) +//go:embed icon.png +var icon []byte + func main() { app := application.New(&options.Application{ Mac: &options.Mac{ //ActivationPolicy: options.ActivationPolicyAccessory, }, }) - app.On(events.Mac.ApplicationDidFinishLaunching, func() { - println("ApplicationDidFinishLaunching") - }) - app.On(events.Mac.ApplicationWillTerminate, func() { - println("ApplicationWillTerminate") - }) - app.On(events.Mac.ApplicationDidBecomeActive, func() { - println("ApplicationDidBecomeActive") - }) - app.On(events.Mac.ApplicationDidChangeBackingProperties, func() { - println("ApplicationDidChangeBackingProperties") - }) + /* + app.On(events.Mac.ApplicationDidFinishLaunching, func() { + println("ApplicationDidFinishLaunching") + }) + app.On(events.Mac.ApplicationWillTerminate, func() { + println("ApplicationWillTerminate") + }) + app.On(events.Mac.ApplicationDidBecomeActive, func() { + println("ApplicationDidBecomeActive") + }) + app.On(events.Mac.ApplicationDidChangeBackingProperties, func() { + println("ApplicationDidChangeBackingProperties") + }) - app.On(events.Mac.ApplicationDidChangeEffectiveAppearance, func() { - println("ApplicationDidChangeEffectiveAppearance") - }) - app.On(events.Mac.ApplicationDidHide, func() { - println("ApplicationDidHide") - }) + app.On(events.Mac.ApplicationDidChangeEffectiveAppearance, func() { + println("ApplicationDidChangeEffectiveAppearance") + }) + app.On(events.Mac.ApplicationDidHide, func() { + println("ApplicationDidHide") + }) + + */ + + menuCallback := func(ctx *application.Context) { + menuItem := ctx.ClickedMenuItem() + menuItem.SetLabel("Clicked!") + } + + myMenu := app.NewMenu() + file1 := myMenu.Add("File") + file1.SetTooltip("File Menu") + file1.OnClick(menuCallback) + myMenu.Add("File 2").SetTooltip("ROFLCOPTER!!!!").OnClick(menuCallback) + myMenu.AddSeperator() + myMenu.AddCheckbox("My checkbox", true).OnClick(menuCallback) + myMenu.Add("File 3").OnClick(menuCallback).SetTooltip("sdfsdfsdfsdf") + myMenu.Add("File 4").OnClick(menuCallback) + myMenu.Add("File 5").OnClick(menuCallback) + + mySystray := app.NewSystemTray() + mySystray.SetLabel("Wails is awesome") + mySystray.SetIcon(icon) + mySystray.SetMenu(myMenu) + mySystray.SetIconPosition(application.NSImageLeading) myWindow := app.NewWindow(&options.Window{ - Title: "Kitchen Sink", - Width: 600, - Height: 400, - AlwaysOnTop: true, - DisableResize: false, - //MinWidth: 100, - //MinHeight: 100, - //MaxWidth: 1000, - //MaxHeight: 1000, + Title: "Kitchen Sink", + Width: 600, + Height: 400, + AlwaysOnTop: true, + DisableResize: false, EnableDevTools: true, BackgroundColour: &options.RGBA{ Red: 255, @@ -59,61 +83,61 @@ func main() { Appearance: options.NSAppearanceNameDarkAqua, }, }) - - myWindow.On(events.Mac.WindowWillClose, func() { - println(myWindow.ID(), "WindowWillClose") - }) - myWindow.On(events.Mac.WindowDidResize, func() { - w, h := myWindow.Size() - println(myWindow.ID(), "WindowDidResize", w, h) - }) - myWindow.On(events.Mac.WindowDidMove, func() { - x, y := myWindow.Position() - println(myWindow.ID(), "WindowDidMove", x, y) - }) - myWindow.On(events.Mac.WindowDidMiniaturize, func() { - println(myWindow.ID(), "WindowDidMiniaturize") - }) - myWindow.On(events.Mac.WindowDidDeminiaturize, func() { - println(myWindow.ID(), "WindowDidDeminiaturize") - }) - myWindow.On(events.Mac.WindowDidBecomeKey, func() { - println(myWindow.ID(), "WindowDidBecomeKey") - }) - myWindow.On(events.Mac.WindowDidResignKey, func() { - println(myWindow.ID(), "WindowDidResignKey") - }) - myWindow.On(events.Mac.WindowDidBecomeMain, func() { - println(myWindow.ID(), "WindowDidBecomeMain") - }) - myWindow.On(events.Mac.WindowDidResignMain, func() { - println(myWindow.ID(), "WindowDidResignMain") - }) - myWindow.On(events.Mac.WindowWillEnterFullScreen, func() { - println(myWindow.ID(), "WindowWillEnterFullScreen") - }) - myWindow.On(events.Mac.WindowDidEnterFullScreen, func() { - println(myWindow.ID(), "WindowDidEnterFullScreen") - }) - myWindow.On(events.Mac.WindowWillExitFullScreen, func() { - println(myWindow.ID(), "WindowWillExitFullScreen") - }) - myWindow.On(events.Mac.WindowDidExitFullScreen, func() { - println(myWindow.ID(), "WindowDidExitFullScreen") - }) - myWindow.On(events.Mac.WindowWillEnterVersionBrowser, func() { - println(myWindow.ID(), "WindowWillEnterVersionBrowser") - }) - myWindow.On(events.Mac.WindowDidEnterVersionBrowser, func() { - println(myWindow.ID(), "WindowDidEnterVersionBrowser") - }) - myWindow.On(events.Mac.WindowWillExitVersionBrowser, func() { - println(myWindow.ID(), "WindowWillExitVersionBrowser") - }) - myWindow.On(events.Mac.WindowDidExitVersionBrowser, func() { - println(myWindow.ID(), "WindowDidExitVersionBrowser") - }) - + /* + myWindow.On(events.Mac.WindowWillClose, func() { + println(myWindow.ID(), "WindowWillClose") + }) + myWindow.On(events.Mac.WindowDidResize, func() { + //w, h := myWindow.Size() + //println(myWindow.ID(), "WindowDidResize", w, h) + }) + myWindow.On(events.Mac.WindowDidMove, func() { + //x, y := myWindow.Position() + //println(myWindow.ID(), "WindowDidMove", x, y) + }) + myWindow.On(events.Mac.WindowDidMiniaturize, func() { + println(myWindow.ID(), "WindowDidMiniaturize") + }) + myWindow.On(events.Mac.WindowDidDeminiaturize, func() { + println(myWindow.ID(), "WindowDidDeminiaturize") + }) + myWindow.On(events.Mac.WindowDidBecomeKey, func() { + println(myWindow.ID(), "WindowDidBecomeKey") + }) + myWindow.On(events.Mac.WindowDidResignKey, func() { + println(myWindow.ID(), "WindowDidResignKey") + }) + myWindow.On(events.Mac.WindowDidBecomeMain, func() { + println(myWindow.ID(), "WindowDidBecomeMain") + }) + myWindow.On(events.Mac.WindowDidResignMain, func() { + println(myWindow.ID(), "WindowDidResignMain") + }) + myWindow.On(events.Mac.WindowWillEnterFullScreen, func() { + println(myWindow.ID(), "WindowWillEnterFullScreen") + }) + myWindow.On(events.Mac.WindowDidEnterFullScreen, func() { + println(myWindow.ID(), "WindowDidEnterFullScreen") + }) + myWindow.On(events.Mac.WindowWillExitFullScreen, func() { + println(myWindow.ID(), "WindowWillExitFullScreen") + }) + myWindow.On(events.Mac.WindowDidExitFullScreen, func() { + println(myWindow.ID(), "WindowDidExitFullScreen") + }) + myWindow.On(events.Mac.WindowWillEnterVersionBrowser, func() { + println(myWindow.ID(), "WindowWillEnterVersionBrowser") + }) + myWindow.On(events.Mac.WindowDidEnterVersionBrowser, func() { + println(myWindow.ID(), "WindowDidEnterVersionBrowser") + }) + myWindow.On(events.Mac.WindowWillExitVersionBrowser, func() { + println(myWindow.ID(), "WindowWillExitVersionBrowser") + }) + myWindow.On(events.Mac.WindowDidExitVersionBrowser, func() { + println(myWindow.ID(), "WindowDidExitVersionBrowser") + }) + */ var myWindow2 *application.Window var myWindow2Lock sync.RWMutex myWindow2 = app.NewWindow(&options.Window{ diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index 2a64fb3ed..d12bd435f 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -28,15 +28,32 @@ type App struct { options *options.Application applicationEventListeners map[uint][]func() + // Windows windows map[uint]*Window windowsLock sync.Mutex windowAliases map[string]uint windowAliasesLock sync.Mutex + // System Trays + systemTrays map[uint]*SystemTray + systemTraysLock sync.Mutex + systemTrayID uint + systemTrayIDLock sync.RWMutex + + // MenuItems + menuItems map[uint]*MenuItem + menuItemsLock sync.Mutex + // Running running bool } +func (a *App) getSystemTrayID() uint { + a.systemTrayIDLock.Lock() + defer a.systemTrayIDLock.Unlock() + a.systemTrayID++ + return a.systemTrayID +} func (a *App) On(eventID uint, callback func()) { a.applicationEventListeners[eventID] = append(a.applicationEventListeners[eventID], callback) } @@ -74,6 +91,20 @@ func (a *App) NewWindow(options *options.Window) *Window { return newWindow } +func (a *App) NewSystemTray() *SystemTray { + + id := a.getSystemTrayID() + newSystemTray := NewSystemTray(id) + a.systemTraysLock.Lock() + a.systemTrays[id] = newSystemTray + a.systemTraysLock.Unlock() + + if a.running { + newSystemTray.Run() + } + return newSystemTray +} + func (a *App) Run() error { a.running = true @@ -96,11 +127,23 @@ func (a *App) Run() error { } }() + go func() { + for { + menuItemID := <-menuItemClicked + a.handleMenuItemClicked(menuItemID) + } + }() + // run windows for _, window := range a.windows { go window.Run() } + // run system trays + for _, systray := range a.systemTrays { + go systray.Run() + } + return a.run() } @@ -128,3 +171,12 @@ func (a *App) handleWindowEvent(event *WindowEvent) { } window.handleWindowEvent(event.EventID) } + +func (a *App) handleMenuItemClicked(menuItemID uint) { + menuItem := getMenuItemByID(menuItemID) + if menuItem == nil { + log.Printf("MenuItem #%d not found", menuItemID) + return + } + menuItem.handleClick() +} diff --git a/exp/pkg/application/application_darwin.go b/exp/pkg/application/application_darwin.go index aa2ec7a79..784c089c1 100644 --- a/exp/pkg/application/application_darwin.go +++ b/exp/pkg/application/application_darwin.go @@ -22,6 +22,7 @@ func New(options *options.Application) *App { return &App{ options: options, applicationEventListeners: make(map[uint][]func()), + systemTrays: make(map[uint]*SystemTray), } } @@ -60,3 +61,8 @@ func processMessage(windowID C.uint, message *C.char) { message: C.GoString(message), } } + +//export processMenuItemClick +func processMenuItemClick(menuID C.uint) { + menuItemClicked <- uint(menuID) +} diff --git a/exp/pkg/application/context.go b/exp/pkg/application/context.go new file mode 100644 index 000000000..fff4675ef --- /dev/null +++ b/exp/pkg/application/context.go @@ -0,0 +1,42 @@ +package application + +type Context struct { + // contains filtered or unexported fields + data map[string]any +} + +func newContext() *Context { + return &Context{ + data: make(map[string]any), + } +} + +const ( + clickedMenuItem string = "clickedMenuItem" + menuItemIsChecked string = "menuItemIsChecked" +) + +func (c *Context) ClickedMenuItem() *MenuItem { + result, exists := c.data[clickedMenuItem] + if !exists { + return nil + } + return result.(*MenuItem) +} + +func (c *Context) IsChecked() bool { + result, exists := c.data[menuItemIsChecked] + if !exists { + return false + } + return result.(bool) +} + +func (c *Context) withClickedMenuItem(menuItem *MenuItem) *Context { + c.data[clickedMenuItem] = menuItem + return c +} + +func (c *Context) withChecked(checked bool) { + c.data[menuItemIsChecked] = checked +} diff --git a/exp/pkg/application/events.go b/exp/pkg/application/events.go index 6732fb500..e073fdeb8 100644 --- a/exp/pkg/application/events.go +++ b/exp/pkg/application/events.go @@ -8,3 +8,5 @@ type WindowEvent struct { } var windowEvents = make(chan *WindowEvent) + +var menuItemClicked = make(chan uint) diff --git a/exp/pkg/application/menu.go b/exp/pkg/application/menu.go new file mode 100644 index 000000000..02b2db395 --- /dev/null +++ b/exp/pkg/application/menu.go @@ -0,0 +1,39 @@ +package application + +type menuImpl interface { + update() +} + +type Menu struct { + items []*MenuItem + + impl menuImpl +} + +func (m *Menu) Add(label string) *MenuItem { + result := newMenuItem(label) + m.items = append(m.items, result) + return result +} + +func (m *Menu) AddSeperator() { + result := newMenuItemSeperator() + m.items = append(m.items, result) +} + +func (m *Menu) AddCheckbox(label string, enabled bool) *MenuItem { + result := newMenuItemCheckbox(label, enabled) + m.items = append(m.items, result) + return result +} + +func (m *Menu) Update() { + if m.impl == nil { + m.impl = newMenuImpl(m) + } + m.impl.update() +} + +func (a *App) NewMenu() *Menu { + return &Menu{} +} diff --git a/exp/pkg/application/menu_darwin.go b/exp/pkg/application/menu_darwin.go new file mode 100644 index 000000000..530b99ae3 --- /dev/null +++ b/exp/pkg/application/menu_darwin.go @@ -0,0 +1,71 @@ +//go:build darwin + +package application + +/* +#cgo CFLAGS: -mmacosx-version-min=10.10 -x objective-c +#cgo LDFLAGS: -framework Cocoa + +#include "menuitem.h" + +extern void setMenuItemChecked(void*, unsigned int, bool); + +// Clear and release all menu items in the menu +void clearMenu(void* nsMenu) { + NSMenu *menu = (NSMenu *)nsMenu; + [menu removeAllItems]; +} + + +// Create a new NSMenu +void* createNSMenu() { + NSMenu *menu = [[NSMenu alloc] init]; + return (void*)menu; +} + +void addMenuItem(void* nsMenu, void* nsMenuItem) { + NSMenu *menu = (NSMenu *)nsMenu; + [menu addItem:nsMenuItem]; +} + +// add seperator to menu +void addMenuSeparator(void* nsMenu) { + NSMenu *menu = (NSMenu *)nsMenu; + [menu addItem:[NSMenuItem separatorItem]]; +} + +*/ +import "C" +import "unsafe" + +type macosMenu struct { + menu *Menu + + nsMenu unsafe.Pointer +} + +func newMenuImpl(menu *Menu) *macosMenu { + result := &macosMenu{ + menu: menu, + } + return result +} + +func (m *macosMenu) update() { + if m.nsMenu == nil { + m.nsMenu = C.createNSMenu() + } else { + C.clearMenu(m.nsMenu) + } + for _, item := range m.menu.items { + switch item.itemType { + case text, checkbox: + menuItem := newMenuItemImpl(item) + item.impl = menuItem + C.addMenuItem(m.nsMenu, menuItem.nsMenuItem) + case separator: + C.addMenuSeparator(m.nsMenu) + } + + } +} diff --git a/exp/pkg/application/menuitem.go b/exp/pkg/application/menuitem.go new file mode 100644 index 000000000..264270235 --- /dev/null +++ b/exp/pkg/application/menuitem.go @@ -0,0 +1,132 @@ +package application + +import ( + "sync" + "sync/atomic" +) + +type menuItemType int + +const ( + text menuItemType = iota + separator + checkbox + radio + submenu +) + +var menuItemID uintptr +var menuItemMap = make(map[uint]*MenuItem) +var menuItemMapLock sync.Mutex + +func addToMenuItemMap(menuItem *MenuItem) { + menuItemMapLock.Lock() + menuItemMap[menuItem.id] = menuItem + menuItemMapLock.Unlock() +} + +func getMenuItemByID(id uint) *MenuItem { + menuItemMapLock.Lock() + defer menuItemMapLock.Unlock() + return menuItemMap[id] +} + +type menuItemImpl interface { + setTooltip(s string) + setLabel(s string) + setDisabled(disabled bool) + setChecked(checked bool) +} + +type MenuItem struct { + id uint + label string + tooltip string + disabled bool + checked bool + callback func(*Context) + itemType menuItemType + + impl menuItemImpl +} + +func newMenuItem(label string) *MenuItem { + result := &MenuItem{ + id: uint(atomic.AddUintptr(&menuItemID, 1)), + label: label, + itemType: text, + } + addToMenuItemMap(result) + return result +} + +func newMenuItemSeperator() *MenuItem { + result := &MenuItem{ + itemType: separator, + } + return result +} + +func newMenuItemCheckbox(label string, checked bool) *MenuItem { + result := &MenuItem{ + id: uint(atomic.AddUintptr(&menuItemID, 1)), + label: label, + checked: checked, + itemType: checkbox, + } + addToMenuItemMap(result) + return result +} + +func (m *MenuItem) handleClick() { + var ctx = newContext().withClickedMenuItem(m) + if m.itemType == checkbox { + m.checked = !m.checked + ctx.withChecked(m.checked) + m.impl.setChecked(m.checked) + } + if m.callback != nil { + go m.callback(ctx) + } +} + +func (m *MenuItem) SetTooltip(s string) *MenuItem { + m.tooltip = s + if m.impl != nil { + m.impl.setTooltip(s) + } + return m +} + +func (m *MenuItem) SetLabel(s string) *MenuItem { + m.label = s + if m.impl != nil { + m.impl.setLabel(s) + } + return m +} + +func (m *MenuItem) SetEnabled(enabled bool) *MenuItem { + m.disabled = !enabled + if m.impl != nil { + m.impl.setDisabled(m.disabled) + } + return m +} + +func (m *MenuItem) OnClick(f func(*Context)) *MenuItem { + m.callback = f + return m +} + +func (m *MenuItem) Label() string { + return m.label +} + +func (m *MenuItem) Tooltip() string { + return m.tooltip +} + +func (m *MenuItem) Enabled() bool { + return !m.disabled +} diff --git a/exp/pkg/application/menuitem.h b/exp/pkg/application/menuitem.h new file mode 100644 index 000000000..91fce726e --- /dev/null +++ b/exp/pkg/application/menuitem.h @@ -0,0 +1,18 @@ + +#ifndef MenuItemDelegate_h +#define MenuItemDelegate_h + +#import + +extern void processMenuItemClick(unsigned int); + +@interface MenuItem : NSMenuItem + +@property unsigned int menuItemID; + +- (void) handleClick; + +@end + + +#endif /* MenuItemDelegate_h */ diff --git a/exp/pkg/application/menuitem.m b/exp/pkg/application/menuitem.m new file mode 100644 index 000000000..f875d0de5 --- /dev/null +++ b/exp/pkg/application/menuitem.m @@ -0,0 +1,13 @@ +//go:build darwin + +#import + +#import "menuitem.h" + +@implementation MenuItem + +- (void) handleClick { + processMenuItemClick(self.menuItemID); +} + +@end diff --git a/exp/pkg/application/menuitem_darwin.go b/exp/pkg/application/menuitem_darwin.go new file mode 100644 index 000000000..b5878fa72 --- /dev/null +++ b/exp/pkg/application/menuitem_darwin.go @@ -0,0 +1,101 @@ +package application + +/* +#cgo CFLAGS: -mmacosx-version-min=10.13 -x objective-c +#cgo LDFLAGS: -framework Cocoa -framework WebKit + +#include "Cocoa/Cocoa.h" +#include "menuitem.h" + +// Create menu item +void* newMenuItem(unsigned int menuItemID, char *label, bool disabled, char* tooltip) { + MenuItem *menuItem = [MenuItem new]; + + // Label + menuItem.title = [NSString stringWithUTF8String:label]; + + // Process callback + menuItem.menuItemID = menuItemID; + menuItem.action = @selector(handleClick); + menuItem.target = menuItem; + menuItem.enabled = !disabled; + + // Tooltip + if( tooltip != NULL ) { + menuItem.toolTip = [NSString stringWithUTF8String:tooltip]; + free(tooltip); + } + + // Set the tag + [menuItem setTag:menuItemID]; + + return (void*)menuItem; +} + +// set menu item label +void setMenuItemLabel(void* nsMenuItem, char *label) { + MenuItem *menuItem = (MenuItem *)nsMenuItem; + menuItem.title = [NSString stringWithUTF8String:label]; +} + +// set menu item disabled +void setMenuItemDisabled(void* nsMenuItem, bool disabled) { + MenuItem *menuItem = (MenuItem *)nsMenuItem; + menuItem.enabled = !disabled; +} + +// set menu item tooltip +void setMenuItemTooltip(void* nsMenuItem, char *tooltip) { + MenuItem *menuItem = (MenuItem *)nsMenuItem; + menuItem.toolTip = [NSString stringWithUTF8String:tooltip]; +} + +// Check menu item +void setMenuItemChecked(void* nsMenuItem, bool checked) { + MenuItem *menuItem = (MenuItem *)nsMenuItem; + menuItem.state = checked ? NSControlStateValueOn : NSControlStateValueOff; +} + +*/ +import "C" +import ( + "unsafe" +) + +type macosMenuItem struct { + menuItem *MenuItem + + nsMenuItem unsafe.Pointer +} + +func (m macosMenuItem) setTooltip(tooltip string) { + C.setMenuItemTooltip(m.nsMenuItem, C.CString(tooltip)) +} + +func (m macosMenuItem) setLabel(s string) { + C.setMenuItemLabel(m.nsMenuItem, C.CString(s)) +} + +func (m macosMenuItem) setDisabled(disabled bool) { + C.setMenuItemDisabled(m.nsMenuItem, C.bool(disabled)) +} + +func (m macosMenuItem) setChecked(checked bool) { + C.setMenuItemChecked(m.nsMenuItem, C.bool(checked)) +} + +func newMenuItemImpl(item *MenuItem) *macosMenuItem { + result := &macosMenuItem{ + menuItem: item, + } + switch item.itemType { + case text, checkbox: + result.nsMenuItem = unsafe.Pointer(C.newMenuItem(C.uint(item.id), C.CString(item.label), C.bool(item.disabled), C.CString(item.tooltip))) + if item.itemType == checkbox { + C.setMenuItemChecked(result.nsMenuItem, C.bool(item.checked)) + } + default: + panic("WTF") + } + return result +} diff --git a/exp/pkg/application/systemtray.go b/exp/pkg/application/systemtray.go new file mode 100644 index 000000000..f593f5b3c --- /dev/null +++ b/exp/pkg/application/systemtray.go @@ -0,0 +1,86 @@ +package application + +type IconPosition int + +const ( + NSImageNone = iota + NSImageOnly + NSImageLeft + NSImageRight + NSImageBelow + NSImageAbove + NSImageOverlaps + NSImageLeading + NSImageTrailing +) + +type systemTrayImpl interface { + setLabel(label string) + run() + setIcon(icon []byte) + setMenu(menu *Menu) + setIconPosition(position int) +} + +type SystemTray struct { + id uint + label string + icon []byte + iconPosition int + + // Platform specific implementation + impl systemTrayImpl + menu *Menu +} + +func NewSystemTray(id uint) *SystemTray { + return &SystemTray{ + id: id, + label: "", + iconPosition: NSImageLeading, + } +} + +func (s *SystemTray) SetLabel(label string) { + if s.impl == nil { + s.label = label + return + } + s.impl.setLabel(label) +} + +func (s *SystemTray) Label() string { + return s.label +} + +func (s *SystemTray) Run() { + s.impl = newSystemTrayImpl(s) + s.impl.run() +} + +func (s *SystemTray) SetIcon(icon []byte) *SystemTray { + if s.impl == nil { + s.icon = icon + } else { + s.impl.setIcon(icon) + } + return s +} + +func (s *SystemTray) SetMenu(menu *Menu) *SystemTray { + if s.impl == nil { + s.menu = menu + } else { + s.impl.setMenu(menu) + } + return s +} + +func (s *SystemTray) SetIconPosition(iconPosition int) *SystemTray { + if s.impl == nil { + s.iconPosition = iconPosition + } else { + s.impl.setIconPosition(iconPosition) + } + return s +} diff --git a/exp/pkg/application/systemtray_darwin.go b/exp/pkg/application/systemtray_darwin.go new file mode 100644 index 000000000..6f99e0044 --- /dev/null +++ b/exp/pkg/application/systemtray_darwin.go @@ -0,0 +1,132 @@ +//go:build darwin + +package application + +/* +#cgo CFLAGS: -mmacosx-version-min=10.13 -x objective-c +#cgo LDFLAGS: -framework Cocoa -framework WebKit + +#include "Cocoa/Cocoa.h" +#include "menuitem.h" + +// Create a new system tray +void* systemTrayNew() { + NSStatusItem *statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength] retain]; + return (void*)statusItem; +} + +void systemTraySetLabel(void* nsStatusItem, char *label) { + if( label == NULL ) { + return; + } + // Set the label on the main thread + dispatch_async(dispatch_get_main_queue(), ^{ + NSStatusItem *statusItem = (NSStatusItem *)nsStatusItem; + statusItem.button.title = [NSString stringWithUTF8String:label]; + free(label); + }); +} + +// Create an nsimage from a byte array +NSImage* imageFromBytes(const unsigned char *bytes, int length) { + NSData *data = [NSData dataWithBytes:bytes length:length]; + NSImage *image = [[NSImage alloc] initWithData:data]; + return image; +} + +// Set the icon on the system tray +void systemTraySetIcon(void* nsStatusItem, void* nsImage, int position) { + // Set the icon on the main thread + dispatch_async(dispatch_get_main_queue(), ^{ + NSStatusItem *statusItem = (NSStatusItem *)nsStatusItem; + NSImage *image = (NSImage *)nsImage; + + NSStatusBar *statusBar = [NSStatusBar systemStatusBar]; + CGFloat thickness = [statusBar thickness]; + [image setSize:NSMakeSize(thickness, thickness)]; + statusItem.button.image = image; + statusItem.button.imagePosition = position; + }); +} + +// Add menu to system tray +void systemTraySetMenu(void* nsStatusItem, void* nsMenu) { + // Set the menu on the main thread + dispatch_async(dispatch_get_main_queue(), ^{ + NSStatusItem *statusItem = (NSStatusItem *)nsStatusItem; + NSMenu *menu = (NSMenu *)nsMenu; + statusItem.menu = menu; + }); +} + +*/ +import "C" +import ( + "unsafe" +) + +type macosSystemTray struct { + id uint + label string + icon []byte + menu *Menu + + nsStatusItem unsafe.Pointer + nsImage unsafe.Pointer + nsMenu unsafe.Pointer + iconPosition int +} + +func (s *macosSystemTray) setIconPosition(position int) { + s.iconPosition = position +} + +func (s *macosSystemTray) setMenu(menu *Menu) { + s.menu = menu +} + +func (s *macosSystemTray) run() { + Dispatch(func() { + if s.nsStatusItem != nil { + Fatal("System tray '%d' already running", s.id) + } + s.nsStatusItem = unsafe.Pointer(C.systemTrayNew()) + if s.label != "" { + C.systemTraySetLabel(s.nsStatusItem, C.CString(s.label)) + } + if s.icon != nil { + s.nsImage = unsafe.Pointer(C.imageFromBytes((*C.uchar)(&s.icon[0]), C.int(len(s.icon)))) + C.systemTraySetIcon(s.nsStatusItem, s.nsImage, C.int(s.iconPosition)) + } + if s.menu != nil { + s.menu.Update() + // Convert impl to macosMenu object + s.nsMenu = (s.menu.impl).(*macosMenu).nsMenu + C.systemTraySetMenu(s.nsStatusItem, s.nsMenu) + } + + }) +} + +func (s *macosSystemTray) setIcon(icon []byte) { + s.icon = icon + Dispatch(func() { + s.nsImage = unsafe.Pointer(C.imageFromBytes((*C.uchar)(&icon[0]), C.int(len(icon)))) + C.systemTraySetIcon(s.nsStatusItem, s.nsImage, C.int(s.iconPosition)) + }) +} + +func newSystemTrayImpl(s *SystemTray) systemTrayImpl { + return &macosSystemTray{ + id: s.id, + label: s.label, + icon: s.icon, + menu: s.menu, + iconPosition: s.iconPosition, + } +} + +func (s *macosSystemTray) setLabel(label string) { + s.label = label + C.systemTraySetLabel(s.nsStatusItem, C.CString(label)) +} diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index a2eb3f5bb..616622fda 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -51,6 +51,21 @@ void* windowNew(unsigned int id, int width, int height) { return window; } +//// Make window toggle frameless +//void windowSetFrameless(void* window, bool frameless) { +// NSWindow* nsWindow = (NSWindow*)window; +// if (frameless) { +// [nsWindow setStyleMask:NSWindowStyleMaskBorderless]; +// } else { +// [nsWindow setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable]; +// } +//} + +void windowSetFrameless(void* window) { + NSWindow* nsWindow = (NSWindow*)window; + [nsWindow setStyleMask:NSWindowStyleMaskBorderless]; +} + // Make NSWindow transparent void windowSetTransparent(void* nsWindow) { // On main thread diff --git a/exp/pkg/events/events.txt b/exp/pkg/events/events.txt index 4929170a5..4eacfe99b 100644 --- a/exp/pkg/events/events.txt +++ b/exp/pkg/events/events.txt @@ -90,4 +90,27 @@ mac:WindowWillUpdateShadow mac:WindowWillUpdateTitle mac:WindowWillUpdateToolbar mac:WindowWillUpdateVisibility -mac:WindowWillUseStandardFrame \ No newline at end of file +mac:WindowWillUseStandardFrame +mac:MenuWillOpen +mac:MenuDidOpen +mac:MenuDidClose +mac:MenuWillSendAction +mac:MenuDidSendAction +mac:MenuWillHighlightItem +mac:MenuDidHighlightItem +mac:MenuWillDisplayItem +mac:MenuDidDisplayItem +mac:MenuWillAddItem +mac:MenuDidAddItem +mac:MenuWillRemoveItem +mac:MenuDidRemoveItem +mac:MenuWillBeginTracking +mac:MenuDidBeginTracking +mac:MenuWillEndTracking +mac:MenuDidEndTracking +mac:MenuWillUpdate +mac:MenuDidUpdate +mac:MenuWillPopUp +mac:MenuDidPopUp +mac:MenuWillSendActionToItem +mac:MenuDidSendActionToItem diff --git a/exp/pkg/menu/menu.go b/exp/pkg/menu/menu.go new file mode 100644 index 000000000..1e2c71cf5 --- /dev/null +++ b/exp/pkg/menu/menu.go @@ -0,0 +1,22 @@ +package menu + +type Menu struct { + Items []*Item +} + +func (m *Menu) Label(label string) *Item { + return &Item{ + Label: label, + } +} + +type CallbackContext struct { + MenuItem *Item +} + +type Item struct { + Label string + Disabled bool + Click func(*CallbackContext) + ID uint +} diff --git a/exp/pkg/options/window.go b/exp/pkg/options/window.go index ae7cd923b..e1c44563f 100644 --- a/exp/pkg/options/window.go +++ b/exp/pkg/options/window.go @@ -1,5 +1,10 @@ package options +import ( + "io/fs" + "net/http" +) + type WindowState int const ( @@ -17,6 +22,7 @@ type Window struct { AlwaysOnTop bool URL string DisableResize bool + Frameless bool MinWidth int MinHeight int MaxWidth int @@ -25,6 +31,18 @@ type Window struct { StartState WindowState Mac *MacWindow BackgroundColour *RGBA + Assets Assets +} + +type Assets struct { + // URL to load the `index.html` file from. If this is a relative path, it will be resolved relative to the `FS` filesystem + URL string + // FS to use for loading assets from + FS fs.FS + // Handler is a custom handler to use for serving assets. If this is set, the `URL` and `FS` fields are ignored. + Handler http.Handler + // Middleware is a custom middleware to use for serving assets. If this is set, the `URL` and `FS` fields are ignored. + Middleware func(http.Handler) http.Handler } type RGBA struct { diff --git a/lib/ipc/message.go b/lib/ipc/message.go index 8c09ab988..ca53ad017 100644 --- a/lib/ipc/message.go +++ b/lib/ipc/message.go @@ -55,7 +55,7 @@ func newIPCMessage(incomingMessage string, responseFunction func(*ipcResponse) e // hasCallbackID checks if the message can send an error back to the frontend func (m *ipcMessage) hasCallbackID() error { if m.CallbackID == "" { - return fmt.Errorf("attempted to return error to message with no Callback ID") + return fmt.Errorf("attempted to return error to message with no callback ID") } return nil } diff --git a/lib/renderer/webview.go b/lib/renderer/webview.go index 777a8560c..eb244aabe 100644 --- a/lib/renderer/webview.go +++ b/lib/renderer/webview.go @@ -186,7 +186,7 @@ func (w *WebView) evalJSSync(js string) error { go func() { exit := false - // We are done when we receive the Callback ID + // We are done when we receive the callback ID w.log.Debug("SyncJS: sending with ID = " + ID) w.eventManager.On(ID, func(...interface{}) { w.log.Debug("SyncJS: Got callback ID = " + ID) @@ -361,7 +361,7 @@ func (w *WebView) focus() { // callback sends a callback to the frontend func (w *WebView) callback(data string) error { - callbackCMD := fmt.Sprintf("window.wails._.Callback('%s');", data) + callbackCMD := fmt.Sprintf("window.wails._.callback('%s');", data) return w.evalJS(callbackCMD) } diff --git a/v2/internal/frontend/desktop/darwin/frontend.go b/v2/internal/frontend/desktop/darwin/frontend.go index a1eff8e8d..6f543c673 100644 --- a/v2/internal/frontend/desktop/darwin/frontend.go +++ b/v2/internal/frontend/desktop/darwin/frontend.go @@ -325,7 +325,7 @@ func (f *Frontend) processMessage(message string) { switch result[0] { case 'c': - // Callback from a method call + // callback from a method call f.Callback(result[1:]) default: f.logger.Info("Unknown message returned from dispatcher: %+v", result) @@ -335,7 +335,7 @@ func (f *Frontend) processMessage(message string) { } func (f *Frontend) Callback(message string) { - f.ExecJS(`window.wails.Callback(` + strconv.Quote(message) + `);`) + f.ExecJS(`window.wails.callback(` + strconv.Quote(message) + `);`) } func (f *Frontend) ExecJS(js string) { diff --git a/v2/internal/frontend/desktop/linux/frontend.go b/v2/internal/frontend/desktop/linux/frontend.go index 0e1c1de39..576cfa3dc 100644 --- a/v2/internal/frontend/desktop/linux/frontend.go +++ b/v2/internal/frontend/desktop/linux/frontend.go @@ -425,7 +425,7 @@ func (f *Frontend) processMessage(message string) { switch result[0] { case 'c': - // Callback from a method call + // callback from a method call f.Callback(result[1:]) default: f.logger.Info("Unknown message returned from dispatcher: %+v", result) @@ -434,7 +434,7 @@ func (f *Frontend) processMessage(message string) { } func (f *Frontend) Callback(message string) { - f.ExecJS(`window.wails.Callback(` + strconv.Quote(message) + `);`) + f.ExecJS(`window.wails.callback(` + strconv.Quote(message) + `);`) } func (f *Frontend) startDrag() { diff --git a/v2/internal/frontend/desktop/windows/frontend.go b/v2/internal/frontend/desktop/windows/frontend.go index b65358860..93702bf5f 100644 --- a/v2/internal/frontend/desktop/windows/frontend.go +++ b/v2/internal/frontend/desktop/windows/frontend.go @@ -605,7 +605,7 @@ func (f *Frontend) processMessage(message string) { switch result[0] { case 'c': - // Callback from a method call + // callback from a method call f.Callback(result[1:]) default: f.logger.Info("Unknown message returned from dispatcher: %+v", result) @@ -615,7 +615,7 @@ func (f *Frontend) processMessage(message string) { func (f *Frontend) Callback(message string) { f.mainWindow.Invoke(func() { - f.chromium.Eval(`window.wails.Callback(` + strconv.Quote(message) + `);`) + f.chromium.Eval(`window.wails.callback(` + strconv.Quote(message) + `);`) }) } diff --git a/v2/internal/frontend/runtime/events.go b/v2/internal/frontend/runtime/events.go index 2725817ce..eb32e3fe3 100644 --- a/v2/internal/frontend/runtime/events.go +++ b/v2/internal/frontend/runtime/events.go @@ -129,7 +129,7 @@ func (e *Events) notifyBackend(eventName string, data ...interface{}) { // We have a dirty flag to indicate that there are items to delete itemsToDelete := false - // Callback in goroutine + // callback in goroutine for _, listener := range listeners { if listener.counter > 0 { listener.counter-- diff --git a/v2/internal/menumanager/menumanager.go b/v2/internal/menumanager/menumanager.go index ea7939415..5b0587eae 100644 --- a/v2/internal/menumanager/menumanager.go +++ b/v2/internal/menumanager/menumanager.go @@ -2,6 +2,7 @@ package menumanager import ( "fmt" + "github.com/wailsapp/wails/v2/pkg/menu" ) @@ -90,7 +91,7 @@ func (m *Manager) ProcessClick(menuID string, data string, menuType string, pare return fmt.Errorf("No callback for menu '%s'", menuItem.Label) } - // Create new Callback struct + // Create new callback struct callbackData := &menu.CallbackData{ MenuItem: menuItem, //ContextData: data, diff --git a/v2/pkg/menu/tray.go b/v2/pkg/menu/tray.go index 7554795ad..d47b2d0f0 100644 --- a/v2/pkg/menu/tray.go +++ b/v2/pkg/menu/tray.go @@ -26,8 +26,8 @@ type TrayMenu struct { // Tooltip Tooltip string - // Callback function when menu clicked - //Click Callback `json:"-"` + // callback function when menu clicked + //Click callback `json:"-"` // Disabled makes the item unselectable Disabled bool From bb36ce61bc7cb0be2f2c8b9bfade801761440330 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 14 Dec 2022 07:52:10 +1100 Subject: [PATCH 21/85] Refactor dispatching --- exp/pkg/application/mainthread.go | 36 ++++++------------------ exp/pkg/application/mainthread_darwin.go | 19 ++++++++++++- exp/pkg/application/systemtray_darwin.go | 4 +-- exp/pkg/application/window_darwin.go | 12 ++++---- 4 files changed, 35 insertions(+), 36 deletions(-) diff --git a/exp/pkg/application/mainthread.go b/exp/pkg/application/mainthread.go index 16068c39b..8c62a8672 100644 --- a/exp/pkg/application/mainthread.go +++ b/exp/pkg/application/mainthread.go @@ -1,22 +1,16 @@ -//go:build darwin - package application -/* -extern void dispatch(unsigned int id); -*/ -import "C" import ( "sync" ) -var mainThreadFuntionStore = make(map[uint]func()) -var mainThreadFuntionStoreLock sync.RWMutex +var mainThreadFunctionStore = make(map[uint]func()) +var mainThreadFunctionStoreLock sync.RWMutex func generateFunctionStoreID() uint { startID := 0 for { - if _, ok := mainThreadFuntionStore[uint(startID)]; !ok { + if _, ok := mainThreadFunctionStore[uint(startID)]; !ok { return uint(startID) } startID++ @@ -26,23 +20,11 @@ func generateFunctionStoreID() uint { } } -func Dispatch(fn func()) { - mainThreadFuntionStoreLock.Lock() +func DispatchOnMainThread(fn func()) { + mainThreadFunctionStoreLock.Lock() id := generateFunctionStoreID() - mainThreadFuntionStore[id] = fn - mainThreadFuntionStoreLock.Unlock() - C.dispatch(C.uint(id)) -} - -//export dispatchCallback -func dispatchCallback(callbackID C.uint) { - mainThreadFuntionStoreLock.RLock() - id := uint(callbackID) - fn := mainThreadFuntionStore[id] - if fn == nil { - Fatal("dispatchCallback called with invalid id: ", id) - } - delete(mainThreadFuntionStore, id) - mainThreadFuntionStoreLock.RUnlock() - fn() + mainThreadFunctionStore[id] = fn + mainThreadFunctionStoreLock.Unlock() + // Call platform specific dispatch function + platformDispatch(id) } diff --git a/exp/pkg/application/mainthread_darwin.go b/exp/pkg/application/mainthread_darwin.go index 4654bfa6c..5a026d1ca 100644 --- a/exp/pkg/application/mainthread_darwin.go +++ b/exp/pkg/application/mainthread_darwin.go @@ -10,7 +10,7 @@ package application extern void dispatchCallback(unsigned int); -void dispatch(unsigned int id) { +static void dispatch(unsigned int id) { dispatch_async(dispatch_get_main_queue(), ^{ dispatchCallback(id); }); @@ -18,3 +18,20 @@ void dispatch(unsigned int id) { */ import "C" + +func platformDispatch(id uint) { + C.dispatch(C.uint(id)) +} + +//export dispatchCallback +func dispatchCallback(callbackID C.uint) { + mainThreadFunctionStoreLock.RLock() + id := uint(callbackID) + fn := mainThreadFunctionStore[id] + if fn == nil { + Fatal("dispatchCallback called with invalid id: ", id) + } + delete(mainThreadFunctionStore, id) + mainThreadFunctionStoreLock.RUnlock() + fn() +} diff --git a/exp/pkg/application/systemtray_darwin.go b/exp/pkg/application/systemtray_darwin.go index 6f99e0044..c04ae2b2b 100644 --- a/exp/pkg/application/systemtray_darwin.go +++ b/exp/pkg/application/systemtray_darwin.go @@ -86,7 +86,7 @@ func (s *macosSystemTray) setMenu(menu *Menu) { } func (s *macosSystemTray) run() { - Dispatch(func() { + DispatchOnMainThread(func() { if s.nsStatusItem != nil { Fatal("System tray '%d' already running", s.id) } @@ -110,7 +110,7 @@ func (s *macosSystemTray) run() { func (s *macosSystemTray) setIcon(icon []byte) { s.icon = icon - Dispatch(func() { + DispatchOnMainThread(func() { s.nsImage = unsafe.Pointer(C.imageFromBytes((*C.uchar)(&icon[0]), C.int(len(icon)))) C.systemTraySetIcon(s.nsStatusItem, s.nsImage, C.int(s.iconPosition)) }) diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index 616622fda..4f7b21cf7 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -493,7 +493,7 @@ func (w *macosWindow) syncMainThreadReturningBool(fn func() bool) bool { var wg sync.WaitGroup wg.Add(1) var result bool - Dispatch(func() { + DispatchOnMainThread(func() { result = fn() wg.Done() }) @@ -569,7 +569,7 @@ func (w *macosWindow) size() (int, int) { var width, height C.int var wg sync.WaitGroup wg.Add(1) - Dispatch(func() { + DispatchOnMainThread(func() { C.windowGetSize(w.nsWindow, &width, &height) wg.Done() }) @@ -581,7 +581,7 @@ func (w *macosWindow) width() int { var width C.int var wg sync.WaitGroup wg.Add(1) - Dispatch(func() { + DispatchOnMainThread(func() { width = C.windowGetWidth(w.nsWindow) wg.Done() }) @@ -592,7 +592,7 @@ func (w *macosWindow) height() int { var height C.int var wg sync.WaitGroup wg.Add(1) - Dispatch(func() { + DispatchOnMainThread(func() { height = C.windowGetHeight(w.nsWindow) wg.Done() }) @@ -601,7 +601,7 @@ func (w *macosWindow) height() int { } func (w *macosWindow) run() { - Dispatch(func() { + DispatchOnMainThread(func() { w.nsWindow = C.windowNew(C.uint(w.id), C.int(w.options.Width), C.int(w.options.Height)) w.setTitle(w.options.Title) w.setAlwaysOnTop(w.options.AlwaysOnTop) @@ -668,7 +668,7 @@ func (w *macosWindow) position() (int, int) { var x, y C.int var wg sync.WaitGroup wg.Add(1) - go Dispatch(func() { + go DispatchOnMainThread(func() { C.windowGetPosition(w.nsWindow, &x, &y) wg.Done() }) From c7ac90def4439225c70ed816547810b3704c63d3 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 14 Dec 2022 08:26:52 +1100 Subject: [PATCH 22/85] Support template icons --- exp/examples/kitchensink/macos_icon.png | Bin 0 -> 1212 bytes exp/examples/kitchensink/main.go | 12 ++++++- exp/pkg/application/menu_darwin.go | 5 +++ exp/pkg/application/systemtray.go | 16 ++++++++-- exp/pkg/application/systemtray_darwin.go | 38 ++++++++++++++++------- 5 files changed, 56 insertions(+), 15 deletions(-) create mode 100644 exp/examples/kitchensink/macos_icon.png diff --git a/exp/examples/kitchensink/macos_icon.png b/exp/examples/kitchensink/macos_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..659d860e141b3bbf9139c9290f0fe57a78fbe3e9 GIT binary patch literal 1212 zcmV;t1Vj6YP)#O?|gIZHH`tSTp#>6n{nBD>~F8L_Fi+YDN}m&>eZ`P zuU0EUm5EN^OOb3Qf0O>72n%PS(CCznS;45 zDZPie7#}IA4*7)`@1pd5T&m2#c%xF&G>msq>0e?t#HC1xdG3RHo99PThg|RbYDu60FOngUozP>yDE}aJo_nEZ z6{$hKk<2eX2{hmk83fr3Jr9x^WCQeUBQ?l#zQ;=f4cJcxK^}#kH%JYF1{@_d$ZFr? zC4mO)CW9cu!&x8CRDLEk$UUy-Lgg1y-}dC$0VMP1J%fd)KG212e*wYIkK1IaV)bg%I_$$LKe zXCf{MG++Z62w9P8uO+!0ccdQs#dwzFJrllVm?Y4ETggDk;Cb}#L6XZ+8!*b?Kb1uj zr#69-ht=20g(10t+V4jny?qibsUU{6vjrGct zB<^_~=gCO|4Om77^L#7Ss_Yq(vkR%mNZhztd7H#NgA-*NNuU9?XMlrw?8LW`#Elyz ze+1aSz$p^1IjPLVd2*6K18fIooD5j=sqzkqpH?nVHj$jMm&80raF!-XpaFJq({ycb z2H438tu;hvvF8DP@7pU99+ z{4Qy$O8-7Z@}oF}GmMf18(^OZ4%x(eu6HxZk796fRU!#C-~<`6iA}C|3&}U}l|tA3 znk2ynd_e}yaaLL4dY>jWP3-Zn-BuE8z%eptj$_cfmDJ=ISC;$!wvu22J|x5Dz$NlF ztGzX!`Q8#qumSIqVRNj6-Vy`0`rZ;rumNqBxsBtbx6PueVb>DFb4RHp*nl>BcE&-{ z`wXdLypO#ll3)W~CId6BBfV`6cm#V(B*6wePXyqrK9jUF;4SPcl>{5Giwuq2gncHB? Date: Wed, 14 Dec 2022 08:48:17 +1100 Subject: [PATCH 23/85] Support submenus --- exp/examples/kitchensink/main.go | 9 ++++++++- exp/pkg/application/menu.go | 8 +++++++- exp/pkg/application/menu_darwin.go | 21 ++++++++++++++++++--- exp/pkg/application/menuitem.go | 12 ++++++++++++ exp/pkg/application/menuitem_darwin.go | 2 +- 5 files changed, 46 insertions(+), 6 deletions(-) diff --git a/exp/examples/kitchensink/main.go b/exp/examples/kitchensink/main.go index cd476b0a8..93f594af2 100644 --- a/exp/examples/kitchensink/main.go +++ b/exp/examples/kitchensink/main.go @@ -56,8 +56,15 @@ func main() { file1.SetTooltip("File Menu") file1.OnClick(menuCallback) myMenu.Add("File 2").SetTooltip("ROFLCOPTER!!!!").OnClick(menuCallback) - myMenu.AddSeperator() + myMenu.AddSeparator() myMenu.AddCheckbox("My checkbox", true).OnClick(menuCallback) + myMenu.AddSeparator() + submenu := myMenu.AddSubmenu("Submenu") + submenu.Add("Submenu item 1").OnClick(menuCallback) + submenu.Add("Submenu item 2").OnClick(menuCallback) + submenu.Add("Submenu item 3").OnClick(menuCallback) + myMenu.AddSeparator() + myMenu.Add("File 3").OnClick(menuCallback).SetTooltip("sdfsdfsdfsdf") myMenu.Add("File 4").OnClick(menuCallback) myMenu.Add("File 5").OnClick(menuCallback) diff --git a/exp/pkg/application/menu.go b/exp/pkg/application/menu.go index 02b2db395..387990de0 100644 --- a/exp/pkg/application/menu.go +++ b/exp/pkg/application/menu.go @@ -16,7 +16,7 @@ func (m *Menu) Add(label string) *MenuItem { return result } -func (m *Menu) AddSeperator() { +func (m *Menu) AddSeparator() { result := newMenuItemSeperator() m.items = append(m.items, result) } @@ -34,6 +34,12 @@ func (m *Menu) Update() { m.impl.update() } +func (m *Menu) AddSubmenu(s string) *Menu { + result := newSubMenuItem(s) + m.items = append(m.items, result) + return result.submenu +} + func (a *App) NewMenu() *Menu { return &Menu{} } diff --git a/exp/pkg/application/menu_darwin.go b/exp/pkg/application/menu_darwin.go index cbff34bee..fb604faaa 100644 --- a/exp/pkg/application/menu_darwin.go +++ b/exp/pkg/application/menu_darwin.go @@ -34,6 +34,13 @@ void addMenuSeparator(void* nsMenu) { [menu addItem:[NSMenuItem separatorItem]]; } +// Set the submenu of a menu item +void setMenuItemSubmenu(void* nsMenuItem, void* nsMenu) { + NSMenuItem *menuItem = (NSMenuItem *)nsMenuItem; + NSMenu *menu = (NSMenu *)nsMenu; + [menuItem setSubmenu:menu]; +} + */ import "C" import "unsafe" @@ -61,14 +68,22 @@ func (m *macosMenu) update() { } func (m *macosMenu) processMenu(parent unsafe.Pointer, menu *Menu) { - for _, item := range m.menu.items { + for _, item := range menu.items { switch item.itemType { + case submenu: + submenu := item.submenu + nsSubmenu := C.createNSMenu() + m.processMenu(nsSubmenu, submenu) + menuItem := newMenuItemImpl(item) + item.impl = menuItem + C.addMenuItem(parent, menuItem.nsMenuItem) + C.setMenuItemSubmenu(menuItem.nsMenuItem, nsSubmenu) case text, checkbox: menuItem := newMenuItemImpl(item) item.impl = menuItem - C.addMenuItem(m.nsMenu, menuItem.nsMenuItem) + C.addMenuItem(parent, menuItem.nsMenuItem) case separator: - C.addMenuSeparator(m.nsMenu) + C.addMenuSeparator(parent) } } diff --git a/exp/pkg/application/menuitem.go b/exp/pkg/application/menuitem.go index 264270235..8bf5a84ac 100644 --- a/exp/pkg/application/menuitem.go +++ b/exp/pkg/application/menuitem.go @@ -44,6 +44,7 @@ type MenuItem struct { tooltip string disabled bool checked bool + submenu *Menu callback func(*Context) itemType menuItemType @@ -78,6 +79,17 @@ func newMenuItemCheckbox(label string, checked bool) *MenuItem { return result } +func newSubMenuItem(label string) *MenuItem { + result := &MenuItem{ + id: uint(atomic.AddUintptr(&menuItemID, 1)), + label: label, + itemType: submenu, + submenu: &Menu{}, + } + addToMenuItemMap(result) + return result +} + func (m *MenuItem) handleClick() { var ctx = newContext().withClickedMenuItem(m) if m.itemType == checkbox { diff --git a/exp/pkg/application/menuitem_darwin.go b/exp/pkg/application/menuitem_darwin.go index b5878fa72..525777f36 100644 --- a/exp/pkg/application/menuitem_darwin.go +++ b/exp/pkg/application/menuitem_darwin.go @@ -89,7 +89,7 @@ func newMenuItemImpl(item *MenuItem) *macosMenuItem { menuItem: item, } switch item.itemType { - case text, checkbox: + case text, checkbox, submenu: result.nsMenuItem = unsafe.Pointer(C.newMenuItem(C.uint(item.id), C.CString(item.label), C.bool(item.disabled), C.CString(item.tooltip))) if item.itemType == checkbox { C.setMenuItemChecked(result.nsMenuItem, C.bool(item.checked)) From 7c18f25508833c0525758c255b40718f9978783d Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 14 Dec 2022 19:03:27 +1100 Subject: [PATCH 24/85] Support radio menuitems Support systemtray destroy() --- exp/examples/kitchensink/main.go | 29 ++++++++++++++++++++++-- exp/pkg/application/menu.go | 28 +++++++++++++++++++++++ exp/pkg/application/menu_darwin.go | 2 +- exp/pkg/application/menuitem.go | 23 ++++++++++++++++++- exp/pkg/application/menuitem_darwin.go | 4 ++-- exp/pkg/application/systemtray.go | 8 +++++++ exp/pkg/application/systemtray_darwin.go | 15 ++++++++++++ 7 files changed, 103 insertions(+), 6 deletions(-) diff --git a/exp/examples/kitchensink/main.go b/exp/examples/kitchensink/main.go index 93f594af2..351ccdc51 100644 --- a/exp/examples/kitchensink/main.go +++ b/exp/examples/kitchensink/main.go @@ -51,14 +51,39 @@ func main() { menuItem.SetLabel("Clicked!") } + radioCallback := func(ctx *application.Context) { + menuItem := ctx.ClickedMenuItem() + menuItem.SetLabel(menuItem.Label() + "!") + } + myMenu := app.NewMenu() file1 := myMenu.Add("File") - file1.SetTooltip("File Menu") + file1.SetTooltip("Create New Tray Menu") file1.OnClick(menuCallback) - myMenu.Add("File 2").SetTooltip("ROFLCOPTER!!!!").OnClick(menuCallback) + myMenu.Add("Create New Tray Menu").SetTooltip("ROFLCOPTER!!!!").OnClick(func(ctx *application.Context) { + mySystray := app.NewSystemTray() + mySystray.SetLabel("Wails") + if runtime.GOOS == "darwin" { + mySystray.SetTemplateIcon(macosIcon) + } else { + mySystray.SetIcon(icon) + } + myMenu := app.NewMenu() + myMenu.Add("Item 1") + myMenu.AddSeparator() + myMenu.Add("Kill this menu").OnClick(func(ctx *application.Context) { + mySystray.Destroy() + }) + mySystray.SetMenu(myMenu) + + }) myMenu.AddSeparator() myMenu.AddCheckbox("My checkbox", true).OnClick(menuCallback) myMenu.AddSeparator() + myMenu.AddRadio("Radio 1", true).OnClick(radioCallback) + myMenu.AddRadio("Radio 2", false).OnClick(radioCallback) + myMenu.AddRadio("Radio 3", false).OnClick(radioCallback) + submenu := myMenu.AddSubmenu("Submenu") submenu.Add("Submenu item 1").OnClick(menuCallback) submenu.Add("Submenu item 2").OnClick(menuCallback) diff --git a/exp/pkg/application/menu.go b/exp/pkg/application/menu.go index 387990de0..49a2f2c96 100644 --- a/exp/pkg/application/menu.go +++ b/exp/pkg/application/menu.go @@ -27,7 +27,14 @@ func (m *Menu) AddCheckbox(label string, enabled bool) *MenuItem { return result } +func (m *Menu) AddRadio(label string, enabled bool) *MenuItem { + result := newMenuItemRadio(label, enabled) + m.items = append(m.items, result) + return result +} + func (m *Menu) Update() { + m.processRadioGroups() if m.impl == nil { m.impl = newMenuImpl(m) } @@ -40,6 +47,27 @@ func (m *Menu) AddSubmenu(s string) *Menu { return result.submenu } +func (m *Menu) processRadioGroups() { + var radioGroup []*MenuItem + for _, item := range m.items { + if item.itemType == radio { + radioGroup = append(radioGroup, item) + } else { + if len(radioGroup) > 0 { + for _, item := range radioGroup { + item.radioGroupMembers = radioGroup + } + radioGroup = nil + } + } + } + if len(radioGroup) > 0 { + for _, item := range radioGroup { + item.radioGroupMembers = radioGroup + } + } +} + func (a *App) NewMenu() *Menu { return &Menu{} } diff --git a/exp/pkg/application/menu_darwin.go b/exp/pkg/application/menu_darwin.go index fb604faaa..8c97dd98f 100644 --- a/exp/pkg/application/menu_darwin.go +++ b/exp/pkg/application/menu_darwin.go @@ -78,7 +78,7 @@ func (m *macosMenu) processMenu(parent unsafe.Pointer, menu *Menu) { item.impl = menuItem C.addMenuItem(parent, menuItem.nsMenuItem) C.setMenuItemSubmenu(menuItem.nsMenuItem, nsSubmenu) - case text, checkbox: + case text, checkbox, radio: menuItem := newMenuItemImpl(item) item.impl = menuItem C.addMenuItem(parent, menuItem.nsMenuItem) diff --git a/exp/pkg/application/menuitem.go b/exp/pkg/application/menuitem.go index 8bf5a84ac..58733b722 100644 --- a/exp/pkg/application/menuitem.go +++ b/exp/pkg/application/menuitem.go @@ -48,7 +48,8 @@ type MenuItem struct { callback func(*Context) itemType menuItemType - impl menuItemImpl + impl menuItemImpl + radioGroupMembers []*MenuItem } func newMenuItem(label string) *MenuItem { @@ -79,6 +80,17 @@ func newMenuItemCheckbox(label string, checked bool) *MenuItem { return result } +func newMenuItemRadio(label string, checked bool) *MenuItem { + result := &MenuItem{ + id: uint(atomic.AddUintptr(&menuItemID, 1)), + label: label, + checked: checked, + itemType: radio, + } + addToMenuItemMap(result) + return result +} + func newSubMenuItem(label string) *MenuItem { result := &MenuItem{ id: uint(atomic.AddUintptr(&menuItemID, 1)), @@ -97,6 +109,15 @@ func (m *MenuItem) handleClick() { ctx.withChecked(m.checked) m.impl.setChecked(m.checked) } + if m.itemType == radio { + for _, member := range m.radioGroupMembers { + member.checked = false + member.impl.setChecked(false) + } + m.checked = true + ctx.withChecked(true) + m.impl.setChecked(true) + } if m.callback != nil { go m.callback(ctx) } diff --git a/exp/pkg/application/menuitem_darwin.go b/exp/pkg/application/menuitem_darwin.go index 525777f36..68736fc71 100644 --- a/exp/pkg/application/menuitem_darwin.go +++ b/exp/pkg/application/menuitem_darwin.go @@ -89,9 +89,9 @@ func newMenuItemImpl(item *MenuItem) *macosMenuItem { menuItem: item, } switch item.itemType { - case text, checkbox, submenu: + case text, checkbox, submenu, radio: result.nsMenuItem = unsafe.Pointer(C.newMenuItem(C.uint(item.id), C.CString(item.label), C.bool(item.disabled), C.CString(item.tooltip))) - if item.itemType == checkbox { + if item.itemType == checkbox || item.itemType == radio { C.setMenuItemChecked(result.nsMenuItem, C.bool(item.checked)) } default: diff --git a/exp/pkg/application/systemtray.go b/exp/pkg/application/systemtray.go index abcd38840..23ba6f286 100644 --- a/exp/pkg/application/systemtray.go +++ b/exp/pkg/application/systemtray.go @@ -21,6 +21,7 @@ type systemTrayImpl interface { setMenu(menu *Menu) setIconPosition(position int) setTemplateIcon(icon []byte) + destroy() } type SystemTray struct { @@ -96,3 +97,10 @@ func (s *SystemTray) SetTemplateIcon(icon []byte) *SystemTray { } return s } + +func (s *SystemTray) Destroy() { + if s.impl == nil { + return + } + s.impl.destroy() +} diff --git a/exp/pkg/application/systemtray_darwin.go b/exp/pkg/application/systemtray_darwin.go index 6766204e1..d26690f9d 100644 --- a/exp/pkg/application/systemtray_darwin.go +++ b/exp/pkg/application/systemtray_darwin.go @@ -62,6 +62,16 @@ void systemTraySetMenu(void* nsStatusItem, void* nsMenu) { }); } +// Destroy system tray +void systemTrayDestroy(void* nsStatusItem) { + // Remove the status item from the status bar and its associated menu + dispatch_async(dispatch_get_main_queue(), ^{ + NSStatusItem *statusItem = (NSStatusItem *)nsStatusItem; + [[NSStatusBar systemStatusBar] removeStatusItem:statusItem]; + [statusItem release]; + }); +} + */ import "C" import ( @@ -144,3 +154,8 @@ func (s *macosSystemTray) setLabel(label string) { s.label = label C.systemTraySetLabel(s.nsStatusItem, C.CString(label)) } + +func (s *macosSystemTray) destroy() { + // Remove the status item from the status bar and its associated menu + C.systemTrayDestroy(s.nsStatusItem) +} From d84cb5b1902dcbeab3b8ec4415bbc42ffe6c0af2 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 14 Dec 2022 19:15:58 +1100 Subject: [PATCH 25/85] Fix enabled menuitem --- exp/examples/kitchensink/main.go | 13 +++++++++---- exp/pkg/application/menuitem_darwin.go | 21 +++++++++++++++++---- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/exp/examples/kitchensink/main.go b/exp/examples/kitchensink/main.go index 351ccdc51..679174f4b 100644 --- a/exp/examples/kitchensink/main.go +++ b/exp/examples/kitchensink/main.go @@ -77,6 +77,7 @@ func main() { mySystray.SetMenu(myMenu) }) + myMenu.Add("Not Enabled").SetEnabled(false) myMenu.AddSeparator() myMenu.AddCheckbox("My checkbox", true).OnClick(menuCallback) myMenu.AddSeparator() @@ -89,13 +90,17 @@ func main() { submenu.Add("Submenu item 2").OnClick(menuCallback) submenu.Add("Submenu item 3").OnClick(menuCallback) myMenu.AddSeparator() + file4 := myMenu.Add("File 4").OnClick(func(*application.Context) { + println("File 4 clicked") + }) - myMenu.Add("File 3").OnClick(menuCallback).SetTooltip("sdfsdfsdfsdf") - myMenu.Add("File 4").OnClick(menuCallback) + myMenu.Add("Click to toggle").OnClick(func(*application.Context) { + enabled := file4.Enabled() + println("Enabled: ", enabled) + file4.SetEnabled(!enabled) + }) myMenu.Add("File 5").OnClick(menuCallback) - //myMenu.AddSubmenu("File 6").OnClick(menuCallback) - mySystray := app.NewSystemTray() mySystray.SetLabel("Wails is awesome") if runtime.GOOS == "darwin" { diff --git a/exp/pkg/application/menuitem_darwin.go b/exp/pkg/application/menuitem_darwin.go index 68736fc71..acd2de5d9 100644 --- a/exp/pkg/application/menuitem_darwin.go +++ b/exp/pkg/application/menuitem_darwin.go @@ -14,10 +14,13 @@ void* newMenuItem(unsigned int menuItemID, char *label, bool disabled, char* too // Label menuItem.title = [NSString stringWithUTF8String:label]; - // Process callback + if( disabled ) { + [menuItem setTarget:nil]; + } else { + [menuItem setTarget:menuItem]; + } menuItem.menuItemID = menuItemID; menuItem.action = @selector(handleClick); - menuItem.target = menuItem; menuItem.enabled = !disabled; // Tooltip @@ -38,10 +41,20 @@ void setMenuItemLabel(void* nsMenuItem, char *label) { menuItem.title = [NSString stringWithUTF8String:label]; } + // set menu item disabled void setMenuItemDisabled(void* nsMenuItem, bool disabled) { - MenuItem *menuItem = (MenuItem *)nsMenuItem; - menuItem.enabled = !disabled; + dispatch_async(dispatch_get_main_queue(), ^{ + MenuItem *menuItem = (MenuItem *)nsMenuItem; + printf("setMenuItemDisabled: %d\n", disabled); + [menuItem setEnabled:!disabled]; + // remove target + if( disabled ) { + [menuItem setTarget:nil]; + } else { + [menuItem setTarget:menuItem]; + } + }); } // set menu item tooltip From 79af667b7a41561e718cd124b79ea1006cd5a680 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Thu, 15 Dec 2022 08:00:49 +1100 Subject: [PATCH 26/85] Support Menu Accelerators --- exp/examples/kitchensink/main.go | 37 ++++---- exp/pkg/application/keys.go | 114 +++++++++++++++++++++++++ exp/pkg/application/keys_darwin.go | 28 ++++++ exp/pkg/application/menuitem.go | 43 ++++++++-- exp/pkg/application/menuitem_darwin.go | 26 ++++++ 5 files changed, 223 insertions(+), 25 deletions(-) create mode 100644 exp/pkg/application/keys.go create mode 100644 exp/pkg/application/keys_darwin.go diff --git a/exp/examples/kitchensink/main.go b/exp/examples/kitchensink/main.go index 679174f4b..6731b86bb 100644 --- a/exp/examples/kitchensink/main.go +++ b/exp/examples/kitchensink/main.go @@ -18,7 +18,7 @@ var icon []byte var macosIcon []byte func main() { - app := application.New(&options.Application{ + app := application.NewWithOptions(&options.Application{ Mac: &options.Mac{ //ActivationPolicy: options.ActivationPolicyAccessory, }, @@ -60,23 +60,26 @@ func main() { file1 := myMenu.Add("File") file1.SetTooltip("Create New Tray Menu") file1.OnClick(menuCallback) - myMenu.Add("Create New Tray Menu").SetTooltip("ROFLCOPTER!!!!").OnClick(func(ctx *application.Context) { - mySystray := app.NewSystemTray() - mySystray.SetLabel("Wails") - if runtime.GOOS == "darwin" { - mySystray.SetTemplateIcon(macosIcon) - } else { - mySystray.SetIcon(icon) - } - myMenu := app.NewMenu() - myMenu.Add("Item 1") - myMenu.AddSeparator() - myMenu.Add("Kill this menu").OnClick(func(ctx *application.Context) { - mySystray.Destroy() - }) - mySystray.SetMenu(myMenu) + myMenu.Add("Create New Tray Menu"). + SetAccelerator("CmdOrCtrl+N"). + SetTooltip("ROFLCOPTER!!!!"). + OnClick(func(ctx *application.Context) { + mySystray := app.NewSystemTray() + mySystray.SetLabel("Wails") + if runtime.GOOS == "darwin" { + mySystray.SetTemplateIcon(macosIcon) + } else { + mySystray.SetIcon(icon) + } + myMenu := app.NewMenu() + myMenu.Add("Item 1") + myMenu.AddSeparator() + myMenu.Add("Kill this menu").OnClick(func(ctx *application.Context) { + mySystray.Destroy() + }) + mySystray.SetMenu(myMenu) - }) + }) myMenu.Add("Not Enabled").SetEnabled(false) myMenu.AddSeparator() myMenu.AddCheckbox("My checkbox", true).OnClick(menuCallback) diff --git a/exp/pkg/application/keys.go b/exp/pkg/application/keys.go new file mode 100644 index 000000000..a7d0515b0 --- /dev/null +++ b/exp/pkg/application/keys.go @@ -0,0 +1,114 @@ +package application + +import ( + "fmt" + "strconv" + "strings" + + "github.com/samber/lo" +) + +// modifier is actually a string +type modifier int + +const ( + // CmdOrCtrlKey represents Command on Mac and Control on other platforms + CmdOrCtrlKey modifier = 0 << iota + // OptionOrAltKey represents Option on Mac and Alt on other platforms + OptionOrAltKey modifier = 1 << iota + // ShiftKey represents the shift key on all systems + ShiftKey modifier = 2 << iota + // SuperKey represents Command on Mac and the Windows key on the other platforms + SuperKey modifier = 3 << iota + // ControlKey represents the control key on all systems + ControlKey modifier = 4 << iota +) + +var modifierMap = map[string]modifier{ + "cmdorctrl": CmdOrCtrlKey, + "optionoralt": OptionOrAltKey, + "shift": ShiftKey, + "super": SuperKey, + "ctrl": ControlKey, +} + +// accelerator holds the keyboard shortcut for a menu item +type accelerator struct { + Key string + Modifiers []modifier +} + +var namedKeys = []string{"backspace", "tab", "return", "enter", "escape", "left", "right", "up", "down", "space", "delete", "home", "end", "page up", "page down", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "f32", "f33", "f34", "f35", "numlock"} + +func parseKey(key string) (string, bool) { + + // Lowercase! + key = strings.ToLower(key) + + // Check special case + if key == "plus" { + return "+", true + } + + // Handle named keys + if lo.Contains(namedKeys, key) { + return key, true + } + + // Check we only have a single character + if len(key) != 1 { + return "", false + } + + runeKey := rune(key[0]) + + // This may be too inclusive + if strconv.IsPrint(runeKey) { + return key, true + } + + return "", false + +} + +// parseAccelerator parses a string into an accelerator +func parseAccelerator(shortcut string) (*accelerator, error) { + + var result accelerator + + // Split the shortcut by + + components := strings.Split(shortcut, "+") + + // If we only have one it should be a key + // We require components + if len(components) == 0 { + return nil, fmt.Errorf("no components given to validateComponents") + } + + // Check components + for index, component := range components { + + // If last component + if index == len(components)-1 { + processedKey, validKey := parseKey(component) + if !validKey { + return nil, fmt.Errorf("'%s' is not a valid key", component) + } + result.Key = processedKey + continue + } + + // Not last component - needs to be modifier + lowercaseComponent := strings.ToLower(component) + thisModifier, valid := modifierMap[lowercaseComponent] + if !valid { + return nil, fmt.Errorf("'%s' is not a valid modifier", component) + } + // Save this data + result.Modifiers = append(result.Modifiers, thisModifier) + } + + result.Modifiers = lo.Uniq(result.Modifiers) + + return &result, nil +} diff --git a/exp/pkg/application/keys_darwin.go b/exp/pkg/application/keys_darwin.go new file mode 100644 index 000000000..42e1c4686 --- /dev/null +++ b/exp/pkg/application/keys_darwin.go @@ -0,0 +1,28 @@ +//go:build darwin + +package application + +const ( + NSEventModifierFlagShift = 1 << 17 // Set if Shift key is pressed. + NSEventModifierFlagControl = 1 << 18 // Set if Control key is pressed. + NSEventModifierFlagOption = 1 << 19 // Set if Option or Alternate key is pressed. + NSEventModifierFlagCommand = 1 << 20 // Set if Command key is pressed. +) + +// macModifierMap maps accelerator modifiers to macOS modifiers. +var macModifierMap = map[modifier]int{ + CmdOrCtrlKey: NSEventModifierFlagCommand, + ControlKey: NSEventModifierFlagControl, + OptionOrAltKey: NSEventModifierFlagOption, + ShiftKey: NSEventModifierFlagShift, + SuperKey: NSEventModifierFlagCommand, +} + +// toMacModifier converts the accelerator to a macOS modifier. +func toMacModifier(modifiers []modifier) int { + result := 0 + for _, modifier := range modifiers { + result |= macModifierMap[modifier] + } + return result +} diff --git a/exp/pkg/application/menuitem.go b/exp/pkg/application/menuitem.go index 58733b722..e3820567b 100644 --- a/exp/pkg/application/menuitem.go +++ b/exp/pkg/application/menuitem.go @@ -36,17 +36,19 @@ type menuItemImpl interface { setLabel(s string) setDisabled(disabled bool) setChecked(checked bool) + setAccelerator(accelerator *accelerator) } type MenuItem struct { - id uint - label string - tooltip string - disabled bool - checked bool - submenu *Menu - callback func(*Context) - itemType menuItemType + id uint + label string + tooltip string + disabled bool + checked bool + submenu *Menu + callback func(*Context) + itemType menuItemType + accelerator *accelerator impl menuItemImpl radioGroupMembers []*MenuItem @@ -123,6 +125,19 @@ func (m *MenuItem) handleClick() { } } +func (m *MenuItem) SetAccelerator(shortcut string) *MenuItem { + accelerator, err := parseAccelerator(shortcut) + if err != nil { + println("ERROR: invalid accelerator", err) + return m + } + m.accelerator = accelerator + if m.impl != nil { + m.impl.setAccelerator(accelerator) + } + return m +} + func (m *MenuItem) SetTooltip(s string) *MenuItem { m.tooltip = s if m.impl != nil { @@ -147,6 +162,18 @@ func (m *MenuItem) SetEnabled(enabled bool) *MenuItem { return m } +func (m *MenuItem) SetChecked(checked bool) *MenuItem { + m.checked = checked + if m.impl != nil { + m.impl.setChecked(m.checked) + } + return m +} + +func (m *MenuItem) Checked() bool { + return m.checked +} + func (m *MenuItem) OnClick(f func(*Context)) *MenuItem { m.callback = f return m diff --git a/exp/pkg/application/menuitem_darwin.go b/exp/pkg/application/menuitem_darwin.go index acd2de5d9..725c3c598 100644 --- a/exp/pkg/application/menuitem_darwin.go +++ b/exp/pkg/application/menuitem_darwin.go @@ -69,6 +69,15 @@ void setMenuItemChecked(void* nsMenuItem, bool checked) { menuItem.state = checked ? NSControlStateValueOn : NSControlStateValueOff; } +// Set the menuitem key equivalent +void setMenuItemKeyEquivalent(void* nsMenuItem, char *key, int modifier) { + MenuItem *menuItem = (MenuItem *)nsMenuItem; + menuItem.keyEquivalent = [NSString stringWithUTF8String:key]; + menuItem.keyEquivalentModifierMask = modifier; + free(key); +} + + */ import "C" import ( @@ -97,6 +106,20 @@ func (m macosMenuItem) setChecked(checked bool) { C.setMenuItemChecked(m.nsMenuItem, C.bool(checked)) } +func (m macosMenuItem) setAccelerator(accelerator *accelerator) { + // Set the keyboard shortcut of the menu item + var modifier C.int + var key *C.char + if accelerator != nil { + modifier = C.int(toMacModifier(accelerator.Modifiers)) + key = C.CString(accelerator.Key) + } + + // Convert the key to a string + C.setMenuItemKeyEquivalent(m.nsMenuItem, key, modifier) + +} + func newMenuItemImpl(item *MenuItem) *macosMenuItem { result := &macosMenuItem{ menuItem: item, @@ -107,6 +130,9 @@ func newMenuItemImpl(item *MenuItem) *macosMenuItem { if item.itemType == checkbox || item.itemType == radio { C.setMenuItemChecked(result.nsMenuItem, C.bool(item.checked)) } + if item.accelerator != nil { + result.setAccelerator(item.accelerator) + } default: panic("WTF") } From dad7798da9c5fbff89c5445643e5b0b72e0e20d1 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Thu, 15 Dec 2022 08:01:21 +1100 Subject: [PATCH 27/85] New Systray example --- exp/examples/systray/macos_template_icon.png | Bin 0 -> 1212 bytes exp/examples/systray/main.go | 33 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 exp/examples/systray/macos_template_icon.png create mode 100644 exp/examples/systray/main.go diff --git a/exp/examples/systray/macos_template_icon.png b/exp/examples/systray/macos_template_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..659d860e141b3bbf9139c9290f0fe57a78fbe3e9 GIT binary patch literal 1212 zcmV;t1Vj6YP)#O?|gIZHH`tSTp#>6n{nBD>~F8L_Fi+YDN}m&>eZ`P zuU0EUm5EN^OOb3Qf0O>72n%PS(CCznS;45 zDZPie7#}IA4*7)`@1pd5T&m2#c%xF&G>msq>0e?t#HC1xdG3RHo99PThg|RbYDu60FOngUozP>yDE}aJo_nEZ z6{$hKk<2eX2{hmk83fr3Jr9x^WCQeUBQ?l#zQ;=f4cJcxK^}#kH%JYF1{@_d$ZFr? zC4mO)CW9cu!&x8CRDLEk$UUy-Lgg1y-}dC$0VMP1J%fd)KG212e*wYIkK1IaV)bg%I_$$LKe zXCf{MG++Z62w9P8uO+!0ccdQs#dwzFJrllVm?Y4ETggDk;Cb}#L6XZ+8!*b?Kb1uj zr#69-ht=20g(10t+V4jny?qibsUU{6vjrGct zB<^_~=gCO|4Om77^L#7Ss_Yq(vkR%mNZhztd7H#NgA-*NNuU9?XMlrw?8LW`#Elyz ze+1aSz$p^1IjPLVd2*6K18fIooD5j=sqzkqpH?nVHj$jMm&80raF!-XpaFJq({ycb z2H438tu;hvvF8DP@7pU99+ z{4Qy$O8-7Z@}oF}GmMf18(^OZ4%x(eu6HxZk796fRU!#C-~<`6iA}C|3&}U}l|tA3 znk2ynd_e}yaaLL4dY>jWP3-Zn-BuE8z%eptj$_cfmDJ=ISC;$!wvu22J|x5Dz$NlF ztGzX!`Q8#qumSIqVRNj6-Vy`0`rZ;rumNqBxsBtbx6PueVb>DFb4RHp*nl>BcE&-{ z`wXdLypO#ll3)W~CId6BBfV`6cm#V(B*6wePXyqrK9jUF;4SPcl>{5Giwuq2gncHB? Date: Thu, 15 Dec 2022 08:01:49 +1100 Subject: [PATCH 28/85] Refactor message processing functions --- exp/go.mod | 7 +- exp/go.sum | 9 ++ exp/pkg/application/app_delegate.m | 40 +++--- exp/pkg/application/application.go | 53 ++++++-- exp/pkg/application/application_darwin.go | 34 ++--- exp/pkg/application/window.go | 8 ++ exp/pkg/application/window_darwin.go | 15 +++ exp/pkg/application/window_delegate.m | 146 +++++++++++----------- exp/tasks/events/generate.go | 8 +- 9 files changed, 198 insertions(+), 122 deletions(-) diff --git a/exp/go.mod b/exp/go.mod index 1969eb348..19cc91829 100644 --- a/exp/go.mod +++ b/exp/go.mod @@ -2,4 +2,9 @@ module github.com/wailsapp/wails/exp go 1.19 -require github.com/leaanthony/clir v1.3.0 +require ( + github.com/leaanthony/clir v1.3.0 + github.com/samber/lo v1.36.0 +) + +require golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect diff --git a/exp/go.sum b/exp/go.sum index ec90627a4..eb2ed5fb8 100644 --- a/exp/go.sum +++ b/exp/go.sum @@ -1,2 +1,11 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/leaanthony/clir v1.3.0 h1:L9nPDWrmc/qU9UWZZvRaFajWYuO0np9V5p+5gxyYno0= github.com/leaanthony/clir v1.3.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/samber/lo v1.36.0 h1:4LaOxH1mHnbDGhTVE0i1z8v/lWaQW8AIfOD3HU4mSaw= +github.com/samber/lo v1.36.0/go.mod h1:HLeWcJRRyLKp3+/XBJvOrerCQn9mhdKMHyd7IRlgeQ8= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M= +golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM= +golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/exp/pkg/application/app_delegate.m b/exp/pkg/application/app_delegate.m index 55c4a9390..120efe38e 100644 --- a/exp/pkg/application/app_delegate.m +++ b/exp/pkg/application/app_delegate.m @@ -16,7 +16,7 @@ [NSApp activateIgnoringOtherApps:YES]; //callOnApplicationDidFinishLaunchingHandler(); - applicationEventHandler(EventApplicationDidFinishLaunching); + processApplicationEvent(EventApplicationDidFinishLaunching); } @@ -28,79 +28,79 @@ // GENERATED EVENTS START - (void)applicationDidBecomeActive:(NSNotification *)notification { - applicationEventHandler(EventApplicationDidBecomeActive); + processApplicationEvent(EventApplicationDidBecomeActive); } - (void)applicationDidChangeBackingProperties:(NSNotification *)notification { - applicationEventHandler(EventApplicationDidChangeBackingProperties); + processApplicationEvent(EventApplicationDidChangeBackingProperties); } - (void)applicationDidChangeEffectiveAppearance:(NSNotification *)notification { - applicationEventHandler(EventApplicationDidChangeEffectiveAppearance); + processApplicationEvent(EventApplicationDidChangeEffectiveAppearance); } - (void)applicationDidChangeIcon:(NSNotification *)notification { - applicationEventHandler(EventApplicationDidChangeIcon); + processApplicationEvent(EventApplicationDidChangeIcon); } - (void)applicationDidChangeOcclusionState:(NSNotification *)notification { - applicationEventHandler(EventApplicationDidChangeOcclusionState); + processApplicationEvent(EventApplicationDidChangeOcclusionState); } - (void)applicationDidChangeScreenParameters:(NSNotification *)notification { - applicationEventHandler(EventApplicationDidChangeScreenParameters); + processApplicationEvent(EventApplicationDidChangeScreenParameters); } - (void)applicationDidChangeStatusBarFrame:(NSNotification *)notification { - applicationEventHandler(EventApplicationDidChangeStatusBarFrame); + processApplicationEvent(EventApplicationDidChangeStatusBarFrame); } - (void)applicationDidChangeStatusBarOrientation:(NSNotification *)notification { - applicationEventHandler(EventApplicationDidChangeStatusBarOrientation); + processApplicationEvent(EventApplicationDidChangeStatusBarOrientation); } - (void)applicationDidHide:(NSNotification *)notification { - applicationEventHandler(EventApplicationDidHide); + processApplicationEvent(EventApplicationDidHide); } - (void)applicationDidResignActive:(NSNotification *)notification { - applicationEventHandler(EventApplicationDidResignActive); + processApplicationEvent(EventApplicationDidResignActive); } - (void)applicationDidUnhide:(NSNotification *)notification { - applicationEventHandler(EventApplicationDidUnhide); + processApplicationEvent(EventApplicationDidUnhide); } - (void)applicationDidUpdate:(NSNotification *)notification { - applicationEventHandler(EventApplicationDidUpdate); + processApplicationEvent(EventApplicationDidUpdate); } - (void)applicationWillBecomeActive:(NSNotification *)notification { - applicationEventHandler(EventApplicationWillBecomeActive); + processApplicationEvent(EventApplicationWillBecomeActive); } - (void)applicationWillFinishLaunching:(NSNotification *)notification { - applicationEventHandler(EventApplicationWillFinishLaunching); + processApplicationEvent(EventApplicationWillFinishLaunching); } - (void)applicationWillHide:(NSNotification *)notification { - applicationEventHandler(EventApplicationWillHide); + processApplicationEvent(EventApplicationWillHide); } - (void)applicationWillResignActive:(NSNotification *)notification { - applicationEventHandler(EventApplicationWillResignActive); + processApplicationEvent(EventApplicationWillResignActive); } - (void)applicationWillTerminate:(NSNotification *)notification { - applicationEventHandler(EventApplicationWillTerminate); + processApplicationEvent(EventApplicationWillTerminate); } - (void)applicationWillUnhide:(NSNotification *)notification { - applicationEventHandler(EventApplicationWillUnhide); + processApplicationEvent(EventApplicationWillUnhide); } - (void)applicationWillUpdate:(NSNotification *)notification { - applicationEventHandler(EventApplicationWillUpdate); + processApplicationEvent(EventApplicationWillUpdate); } // GENERATED EVENTS END diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index d12bd435f..f3144ea04 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -12,17 +12,18 @@ func init() { runtime.LockOSThread() } +type platformApp interface { + run() error + destroy() +} + // Messages sent from javascript get routed here type windowMessage struct { windowId uint message string } -var messageBuffer = make(chan *windowMessage) - -type Application interface { - Run() error -} +var windowMessageBuffer = make(chan *windowMessage) type App struct { options *options.Application @@ -46,6 +47,9 @@ type App struct { // Running running bool + + // platform app + app platformApp } func (a *App) getSystemTrayID() uint { @@ -122,8 +126,8 @@ func (a *App) Run() error { }() go func() { for { - event := <-messageBuffer - a.handleMessage(event) + event := <-windowMessageBuffer + a.handleWindowMessage(event) } }() @@ -147,7 +151,17 @@ func (a *App) Run() error { return a.run() } -func (a *App) handleMessage(event *windowMessage) { +func (a *App) handleApplicationEvent(event uint) { + listeners, ok := a.applicationEventListeners[event] + if !ok { + return + } + for _, listener := range listeners { + go listener() + } +} + +func (a *App) handleWindowMessage(event *windowMessage) { // Get window from window map a.windowsLock.Lock() window, ok := a.windows[event.windowId] @@ -180,3 +194,26 @@ func (a *App) handleMenuItemClicked(menuItemID uint) { } menuItem.handleClick() } + +func (a *App) Quit() { + var wg sync.WaitGroup + wg.Add(2) + go func() { + a.windowsLock.Lock() + for _, window := range a.windows { + window.Destroy() + } + a.windowsLock.Unlock() + wg.Done() + }() + go func() { + a.systemTraysLock.Lock() + for _, systray := range a.systemTrays { + systray.Destroy() + } + a.systemTraysLock.Unlock() + wg.Done() + }() + wg.Wait() + +} diff --git a/exp/pkg/application/application_darwin.go b/exp/pkg/application/application_darwin.go index 784c089c1..13f972263 100644 --- a/exp/pkg/application/application_darwin.go +++ b/exp/pkg/application/application_darwin.go @@ -14,7 +14,19 @@ import ( "github.com/wailsapp/wails/exp/pkg/options" ) -func New(options *options.Application) *App { +func New() *App { + C.Init() + return newApp() +} + +func newApp() *App { + return &App{ + applicationEventListeners: make(map[uint][]func()), + systemTrays: make(map[uint]*SystemTray), + } +} + +func NewWithOptions(options *options.Application) *App { C.Init() if options.Mac != nil { C.SetActivationPolicy(C.int(options.Mac.ActivationPolicy)) @@ -31,23 +43,13 @@ func (a *App) run() error { return nil } -func (a *App) handleApplicationEvent(event uint) { - listeners, ok := a.applicationEventListeners[event] - if !ok { - return - } - for _, listener := range listeners { - go listener() - } -} - -//export applicationEventHandler -func applicationEventHandler(eventID C.uint) { +//export processApplicationEvent +func processApplicationEvent(eventID C.uint) { applicationEvents <- uint(eventID) } -//export windowEventHandler -func windowEventHandler(windowID C.uint, eventID C.uint) { +//export processWindowEvent +func processWindowEvent(windowID C.uint, eventID C.uint) { windowEvents <- &WindowEvent{ WindowID: uint(windowID), EventID: uint(eventID), @@ -56,7 +58,7 @@ func windowEventHandler(windowID C.uint, eventID C.uint) { //export processMessage func processMessage(windowID C.uint, message *C.char) { - messageBuffer <- &windowMessage{ + windowMessageBuffer <- &windowMessage{ windowId: uint(windowID), message: C.GoString(message), } diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index 84d83cbcc..d966a6ae8 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -31,6 +31,7 @@ type windowImpl interface { width() int height() int position() (int, int) + destroy() } type Window struct { @@ -281,3 +282,10 @@ func (w *Window) Position() (int, int) { } return w.impl.position() } + +func (w *Window) Destroy() { + if w.impl == nil { + return + } + w.impl.destroy() +} diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index 4f7b21cf7..ba66210e6 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -451,6 +451,17 @@ void windowGetPosition(void* nsWindow, int* x, int* y) { *y = frame.origin.y; } +// Destroy window +void windowDestroy(void* nsWindow) { + // Destroy window on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + // get main window + NSWindow* window = (NSWindow*)nsWindow; + // close window + [window close]; + }); +} + */ import "C" @@ -675,3 +686,7 @@ func (w *macosWindow) position() (int, int) { wg.Wait() return int(x), int(y) } + +func (w *macosWindow) destroy() { + C.windowDestroy(w.nsWindow) +} diff --git a/exp/pkg/application/window_delegate.m b/exp/pkg/application/window_delegate.m index 1b50ea7f3..3d07620e6 100644 --- a/exp/pkg/application/window_delegate.m +++ b/exp/pkg/application/window_delegate.m @@ -44,295 +44,295 @@ // GENERATED EVENTS START - (void)windowDidBecomeKey:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidBecomeKey); + processWindowEvent(self.windowId, EventWindowDidBecomeKey); } - (void)windowDidBecomeMain:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidBecomeMain); + processWindowEvent(self.windowId, EventWindowDidBecomeMain); } - (void)windowDidBeginSheet:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidBeginSheet); + processWindowEvent(self.windowId, EventWindowDidBeginSheet); } - (void)windowDidChangeAlpha:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidChangeAlpha); + processWindowEvent(self.windowId, EventWindowDidChangeAlpha); } - (void)windowDidChangeBackingLocation:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidChangeBackingLocation); + processWindowEvent(self.windowId, EventWindowDidChangeBackingLocation); } - (void)windowDidChangeBackingProperties:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidChangeBackingProperties); + processWindowEvent(self.windowId, EventWindowDidChangeBackingProperties); } - (void)windowDidChangeCollectionBehavior:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidChangeCollectionBehavior); + processWindowEvent(self.windowId, EventWindowDidChangeCollectionBehavior); } - (void)windowDidChangeEffectiveAppearance:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidChangeEffectiveAppearance); + processWindowEvent(self.windowId, EventWindowDidChangeEffectiveAppearance); } - (void)windowDidChangeOcclusionState:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidChangeOcclusionState); + processWindowEvent(self.windowId, EventWindowDidChangeOcclusionState); } - (void)windowDidChangeOrderingMode:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidChangeOrderingMode); + processWindowEvent(self.windowId, EventWindowDidChangeOrderingMode); } - (void)windowDidChangeScreen:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidChangeScreen); + processWindowEvent(self.windowId, EventWindowDidChangeScreen); } - (void)windowDidChangeScreenParameters:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidChangeScreenParameters); + processWindowEvent(self.windowId, EventWindowDidChangeScreenParameters); } - (void)windowDidChangeScreenProfile:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidChangeScreenProfile); + processWindowEvent(self.windowId, EventWindowDidChangeScreenProfile); } - (void)windowDidChangeScreenSpace:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidChangeScreenSpace); + processWindowEvent(self.windowId, EventWindowDidChangeScreenSpace); } - (void)windowDidChangeScreenSpaceProperties:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidChangeScreenSpaceProperties); + processWindowEvent(self.windowId, EventWindowDidChangeScreenSpaceProperties); } - (void)windowDidChangeSharingType:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidChangeSharingType); + processWindowEvent(self.windowId, EventWindowDidChangeSharingType); } - (void)windowDidChangeSpace:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidChangeSpace); + processWindowEvent(self.windowId, EventWindowDidChangeSpace); } - (void)windowDidChangeSpaceOrderingMode:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidChangeSpaceOrderingMode); + processWindowEvent(self.windowId, EventWindowDidChangeSpaceOrderingMode); } - (void)windowDidChangeTitle:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidChangeTitle); + processWindowEvent(self.windowId, EventWindowDidChangeTitle); } - (void)windowDidChangeToolbar:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidChangeToolbar); + processWindowEvent(self.windowId, EventWindowDidChangeToolbar); } - (void)windowDidChangeVisibility:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidChangeVisibility); + processWindowEvent(self.windowId, EventWindowDidChangeVisibility); } - (void)windowDidClose:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidClose); + processWindowEvent(self.windowId, EventWindowDidClose); } - (void)windowDidDeminiaturize:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidDeminiaturize); + processWindowEvent(self.windowId, EventWindowDidDeminiaturize); } - (void)windowDidEndSheet:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidEndSheet); + processWindowEvent(self.windowId, EventWindowDidEndSheet); } - (void)windowDidEnterFullScreen:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidEnterFullScreen); + processWindowEvent(self.windowId, EventWindowDidEnterFullScreen); } - (void)windowDidEnterVersionBrowser:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidEnterVersionBrowser); + processWindowEvent(self.windowId, EventWindowDidEnterVersionBrowser); } - (void)windowDidExitFullScreen:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidExitFullScreen); + processWindowEvent(self.windowId, EventWindowDidExitFullScreen); } - (void)windowDidExitVersionBrowser:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidExitVersionBrowser); + processWindowEvent(self.windowId, EventWindowDidExitVersionBrowser); } - (void)windowDidExpose:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidExpose); + processWindowEvent(self.windowId, EventWindowDidExpose); } - (void)windowDidFocus:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidFocus); + processWindowEvent(self.windowId, EventWindowDidFocus); } - (void)windowDidMiniaturize:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidMiniaturize); + processWindowEvent(self.windowId, EventWindowDidMiniaturize); } - (void)windowDidMove:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidMove); + processWindowEvent(self.windowId, EventWindowDidMove); } - (void)windowDidOrderOffScreen:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidOrderOffScreen); + processWindowEvent(self.windowId, EventWindowDidOrderOffScreen); } - (void)windowDidOrderOnScreen:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidOrderOnScreen); + processWindowEvent(self.windowId, EventWindowDidOrderOnScreen); } - (void)windowDidResignKey:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidResignKey); + processWindowEvent(self.windowId, EventWindowDidResignKey); } - (void)windowDidResignMain:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidResignMain); + processWindowEvent(self.windowId, EventWindowDidResignMain); } - (void)windowDidResize:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidResize); + processWindowEvent(self.windowId, EventWindowDidResize); } - (void)windowDidUnfocus:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidUnfocus); + processWindowEvent(self.windowId, EventWindowDidUnfocus); } - (void)windowDidUpdate:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidUpdate); + processWindowEvent(self.windowId, EventWindowDidUpdate); } - (void)windowDidUpdateAlpha:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidUpdateAlpha); + processWindowEvent(self.windowId, EventWindowDidUpdateAlpha); } - (void)windowDidUpdateCollectionBehavior:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidUpdateCollectionBehavior); + processWindowEvent(self.windowId, EventWindowDidUpdateCollectionBehavior); } - (void)windowDidUpdateCollectionProperties:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidUpdateCollectionProperties); + processWindowEvent(self.windowId, EventWindowDidUpdateCollectionProperties); } - (void)windowDidUpdateShadow:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidUpdateShadow); + processWindowEvent(self.windowId, EventWindowDidUpdateShadow); } - (void)windowDidUpdateTitle:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidUpdateTitle); + processWindowEvent(self.windowId, EventWindowDidUpdateTitle); } - (void)windowDidUpdateToolbar:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidUpdateToolbar); + processWindowEvent(self.windowId, EventWindowDidUpdateToolbar); } - (void)windowDidUpdateVisibility:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowDidUpdateVisibility); + processWindowEvent(self.windowId, EventWindowDidUpdateVisibility); } - (void)windowWillBecomeKey:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillBecomeKey); + processWindowEvent(self.windowId, EventWindowWillBecomeKey); } - (void)windowWillBecomeMain:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillBecomeMain); + processWindowEvent(self.windowId, EventWindowWillBecomeMain); } - (void)windowWillBeginSheet:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillBeginSheet); + processWindowEvent(self.windowId, EventWindowWillBeginSheet); } - (void)windowWillChangeOrderingMode:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillChangeOrderingMode); + processWindowEvent(self.windowId, EventWindowWillChangeOrderingMode); } - (void)windowWillClose:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillClose); + processWindowEvent(self.windowId, EventWindowWillClose); } - (void)windowWillDeminiaturize:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillDeminiaturize); + processWindowEvent(self.windowId, EventWindowWillDeminiaturize); } - (void)windowWillEnterFullScreen:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillEnterFullScreen); + processWindowEvent(self.windowId, EventWindowWillEnterFullScreen); } - (void)windowWillEnterVersionBrowser:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillEnterVersionBrowser); + processWindowEvent(self.windowId, EventWindowWillEnterVersionBrowser); } - (void)windowWillExitFullScreen:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillExitFullScreen); + processWindowEvent(self.windowId, EventWindowWillExitFullScreen); } - (void)windowWillExitVersionBrowser:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillExitVersionBrowser); + processWindowEvent(self.windowId, EventWindowWillExitVersionBrowser); } - (void)windowWillFocus:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillFocus); + processWindowEvent(self.windowId, EventWindowWillFocus); } - (void)windowWillMiniaturize:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillMiniaturize); + processWindowEvent(self.windowId, EventWindowWillMiniaturize); } - (void)windowWillMove:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillMove); + processWindowEvent(self.windowId, EventWindowWillMove); } - (void)windowWillOrderOffScreen:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillOrderOffScreen); + processWindowEvent(self.windowId, EventWindowWillOrderOffScreen); } - (void)windowWillOrderOnScreen:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillOrderOnScreen); + processWindowEvent(self.windowId, EventWindowWillOrderOnScreen); } - (void)windowWillResignMain:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillResignMain); + processWindowEvent(self.windowId, EventWindowWillResignMain); } - (void)windowWillResize:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillResize); + processWindowEvent(self.windowId, EventWindowWillResize); } - (void)windowWillUnfocus:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillUnfocus); + processWindowEvent(self.windowId, EventWindowWillUnfocus); } - (void)windowWillUpdate:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillUpdate); + processWindowEvent(self.windowId, EventWindowWillUpdate); } - (void)windowWillUpdateAlpha:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillUpdateAlpha); + processWindowEvent(self.windowId, EventWindowWillUpdateAlpha); } - (void)windowWillUpdateCollectionBehavior:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillUpdateCollectionBehavior); + processWindowEvent(self.windowId, EventWindowWillUpdateCollectionBehavior); } - (void)windowWillUpdateCollectionProperties:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillUpdateCollectionProperties); + processWindowEvent(self.windowId, EventWindowWillUpdateCollectionProperties); } - (void)windowWillUpdateShadow:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillUpdateShadow); + processWindowEvent(self.windowId, EventWindowWillUpdateShadow); } - (void)windowWillUpdateTitle:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillUpdateTitle); + processWindowEvent(self.windowId, EventWindowWillUpdateTitle); } - (void)windowWillUpdateToolbar:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillUpdateToolbar); + processWindowEvent(self.windowId, EventWindowWillUpdateToolbar); } - (void)windowWillUpdateVisibility:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillUpdateVisibility); + processWindowEvent(self.windowId, EventWindowWillUpdateVisibility); } - (void)windowWillUseStandardFrame:(NSNotification *)notification { - windowEventHandler(self.windowId, EventWindowWillUseStandardFrame); + processWindowEvent(self.windowId, EventWindowWillUseStandardFrame); } // GENERATED EVENTS END diff --git a/exp/tasks/events/generate.go b/exp/tasks/events/generate.go index f97d1cda5..4b57e8453 100644 --- a/exp/tasks/events/generate.go +++ b/exp/tasks/events/generate.go @@ -25,8 +25,8 @@ var eventsH = `//go:build darwin #ifndef _events_h #define _events_h -extern void applicationEventHandler(unsigned int); -extern void windowEventHandler(unsigned int, unsigned int); +extern void processApplicationEvent(unsigned int); +extern void processWindowEvent(unsigned int, unsigned int); $$CHEADEREVENTS @@ -80,14 +80,14 @@ func main() { // Check if this is a window event if strings.HasPrefix(event, "Window") { windowDelegateEvents.WriteString(`- (void)` + delegateEventFunction + `:(NSNotification *)notification { - windowEventHandler(self.windowId, Event` + eventTitle + `); + processWindowEvent(self.windowId, Event` + eventTitle + `); } `) } if strings.HasPrefix(event, "Application") { applicationDelegateEvents.WriteString(`- (void)` + delegateEventFunction + `:(NSNotification *)notification { - applicationEventHandler(Event` + eventTitle + `); + processApplicationEvent(Event` + eventTitle + `); } `) From 14fcfb83489ad3032e6a33f3b1e083f5e79c8c6d Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Thu, 15 Dec 2022 18:03:01 +1100 Subject: [PATCH 29/85] Refactor event types --- exp/pkg/application/application.go | 3 +- exp/pkg/application/window.go | 4 +- exp/pkg/events/events.go | 235 +++++++++++++++++------------ exp/pkg/events/events.h | 27 +++- exp/tasks/events/generate.go | 9 +- 5 files changed, 180 insertions(+), 98 deletions(-) diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index f3144ea04..d3663a78c 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -58,7 +58,8 @@ func (a *App) getSystemTrayID() uint { a.systemTrayID++ return a.systemTrayID } -func (a *App) On(eventID uint, callback func()) { +func (a *App) On(eventType events.ApplicationEventType, callback func()) { + eventID := uint(eventType) a.applicationEventListeners[eventID] = append(a.applicationEventListeners[eventID], callback) } diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index d966a6ae8..944739d33 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -4,6 +4,7 @@ import ( "fmt" "sync" + "github.com/wailsapp/wails/exp/pkg/events" "github.com/wailsapp/wails/exp/pkg/options" ) @@ -242,7 +243,8 @@ func (w *Window) Center() { w.impl.center() } -func (w *Window) On(eventID uint, callback func()) { +func (w *Window) On(eventType events.WindowEventType, callback func()) { + eventID := uint(eventType) w.eventListenersLock.Lock() w.eventListeners[eventID] = append(w.eventListeners[eventID], callback) w.eventListenersLock.Unlock() diff --git a/exp/pkg/events/events.go b/exp/pkg/events/events.go index 5ecb93aa1..eaca310f8 100644 --- a/exp/pkg/events/events.go +++ b/exp/pkg/events/events.go @@ -1,101 +1,127 @@ package events +type ApplicationEventType uint +type WindowEventType uint + var Mac = newMacEvents() type macEvents struct { - ApplicationDidBecomeActive uint - ApplicationDidChangeBackingProperties uint - ApplicationDidChangeEffectiveAppearance uint - ApplicationDidChangeIcon uint - ApplicationDidChangeOcclusionState uint - ApplicationDidChangeScreenParameters uint - ApplicationDidChangeStatusBarFrame uint - ApplicationDidChangeStatusBarOrientation uint - ApplicationDidFinishLaunching uint - ApplicationDidHide uint - ApplicationDidResignActive uint - ApplicationDidUnhide uint - ApplicationDidUpdate uint - ApplicationWillBecomeActive uint - ApplicationWillFinishLaunching uint - ApplicationWillHide uint - ApplicationWillResignActive uint - ApplicationWillTerminate uint - ApplicationWillUnhide uint - ApplicationWillUpdate uint - WindowDidBecomeKey uint - WindowDidBecomeMain uint - WindowDidBeginSheet uint - WindowDidChangeAlpha uint - WindowDidChangeBackingLocation uint - WindowDidChangeBackingProperties uint - WindowDidChangeCollectionBehavior uint - WindowDidChangeEffectiveAppearance uint - WindowDidChangeOcclusionState uint - WindowDidChangeOrderingMode uint - WindowDidChangeScreen uint - WindowDidChangeScreenParameters uint - WindowDidChangeScreenProfile uint - WindowDidChangeScreenSpace uint - WindowDidChangeScreenSpaceProperties uint - WindowDidChangeSharingType uint - WindowDidChangeSpace uint - WindowDidChangeSpaceOrderingMode uint - WindowDidChangeTitle uint - WindowDidChangeToolbar uint - WindowDidChangeVisibility uint - WindowDidClose uint - WindowDidDeminiaturize uint - WindowDidEndSheet uint - WindowDidEnterFullScreen uint - WindowDidEnterVersionBrowser uint - WindowDidExitFullScreen uint - WindowDidExitVersionBrowser uint - WindowDidExpose uint - WindowDidFocus uint - WindowDidMiniaturize uint - WindowDidMove uint - WindowDidOrderOffScreen uint - WindowDidOrderOnScreen uint - WindowDidResignKey uint - WindowDidResignMain uint - WindowDidResize uint - WindowDidUnfocus uint - WindowDidUpdate uint - WindowDidUpdateAlpha uint - WindowDidUpdateCollectionBehavior uint - WindowDidUpdateCollectionProperties uint - WindowDidUpdateShadow uint - WindowDidUpdateTitle uint - WindowDidUpdateToolbar uint - WindowDidUpdateVisibility uint - WindowWillBecomeKey uint - WindowWillBecomeMain uint - WindowWillBeginSheet uint - WindowWillChangeOrderingMode uint - WindowWillClose uint - WindowWillDeminiaturize uint - WindowWillEnterFullScreen uint - WindowWillEnterVersionBrowser uint - WindowWillExitFullScreen uint - WindowWillExitVersionBrowser uint - WindowWillFocus uint - WindowWillMiniaturize uint - WindowWillMove uint - WindowWillOrderOffScreen uint - WindowWillOrderOnScreen uint - WindowWillResignMain uint - WindowWillResize uint - WindowWillUnfocus uint - WindowWillUpdate uint - WindowWillUpdateAlpha uint - WindowWillUpdateCollectionBehavior uint - WindowWillUpdateCollectionProperties uint - WindowWillUpdateShadow uint - WindowWillUpdateTitle uint - WindowWillUpdateToolbar uint - WindowWillUpdateVisibility uint - WindowWillUseStandardFrame uint + ApplicationDidBecomeActive ApplicationEventType + ApplicationDidChangeBackingProperties ApplicationEventType + ApplicationDidChangeEffectiveAppearance ApplicationEventType + ApplicationDidChangeIcon ApplicationEventType + ApplicationDidChangeOcclusionState ApplicationEventType + ApplicationDidChangeScreenParameters ApplicationEventType + ApplicationDidChangeStatusBarFrame ApplicationEventType + ApplicationDidChangeStatusBarOrientation ApplicationEventType + ApplicationDidFinishLaunching ApplicationEventType + ApplicationDidHide ApplicationEventType + ApplicationDidResignActive ApplicationEventType + ApplicationDidUnhide ApplicationEventType + ApplicationDidUpdate ApplicationEventType + ApplicationWillBecomeActive ApplicationEventType + ApplicationWillFinishLaunching ApplicationEventType + ApplicationWillHide ApplicationEventType + ApplicationWillResignActive ApplicationEventType + ApplicationWillTerminate ApplicationEventType + ApplicationWillUnhide ApplicationEventType + ApplicationWillUpdate ApplicationEventType + WindowDidBecomeKey WindowEventType + WindowDidBecomeMain WindowEventType + WindowDidBeginSheet WindowEventType + WindowDidChangeAlpha WindowEventType + WindowDidChangeBackingLocation WindowEventType + WindowDidChangeBackingProperties WindowEventType + WindowDidChangeCollectionBehavior WindowEventType + WindowDidChangeEffectiveAppearance WindowEventType + WindowDidChangeOcclusionState WindowEventType + WindowDidChangeOrderingMode WindowEventType + WindowDidChangeScreen WindowEventType + WindowDidChangeScreenParameters WindowEventType + WindowDidChangeScreenProfile WindowEventType + WindowDidChangeScreenSpace WindowEventType + WindowDidChangeScreenSpaceProperties WindowEventType + WindowDidChangeSharingType WindowEventType + WindowDidChangeSpace WindowEventType + WindowDidChangeSpaceOrderingMode WindowEventType + WindowDidChangeTitle WindowEventType + WindowDidChangeToolbar WindowEventType + WindowDidChangeVisibility WindowEventType + WindowDidClose WindowEventType + WindowDidDeminiaturize WindowEventType + WindowDidEndSheet WindowEventType + WindowDidEnterFullScreen WindowEventType + WindowDidEnterVersionBrowser WindowEventType + WindowDidExitFullScreen WindowEventType + WindowDidExitVersionBrowser WindowEventType + WindowDidExpose WindowEventType + WindowDidFocus WindowEventType + WindowDidMiniaturize WindowEventType + WindowDidMove WindowEventType + WindowDidOrderOffScreen WindowEventType + WindowDidOrderOnScreen WindowEventType + WindowDidResignKey WindowEventType + WindowDidResignMain WindowEventType + WindowDidResize WindowEventType + WindowDidUnfocus WindowEventType + WindowDidUpdate WindowEventType + WindowDidUpdateAlpha WindowEventType + WindowDidUpdateCollectionBehavior WindowEventType + WindowDidUpdateCollectionProperties WindowEventType + WindowDidUpdateShadow WindowEventType + WindowDidUpdateTitle WindowEventType + WindowDidUpdateToolbar WindowEventType + WindowDidUpdateVisibility WindowEventType + WindowWillBecomeKey WindowEventType + WindowWillBecomeMain WindowEventType + WindowWillBeginSheet WindowEventType + WindowWillChangeOrderingMode WindowEventType + WindowWillClose WindowEventType + WindowWillDeminiaturize WindowEventType + WindowWillEnterFullScreen WindowEventType + WindowWillEnterVersionBrowser WindowEventType + WindowWillExitFullScreen WindowEventType + WindowWillExitVersionBrowser WindowEventType + WindowWillFocus WindowEventType + WindowWillMiniaturize WindowEventType + WindowWillMove WindowEventType + WindowWillOrderOffScreen WindowEventType + WindowWillOrderOnScreen WindowEventType + WindowWillResignMain WindowEventType + WindowWillResize WindowEventType + WindowWillUnfocus WindowEventType + WindowWillUpdate WindowEventType + WindowWillUpdateAlpha WindowEventType + WindowWillUpdateCollectionBehavior WindowEventType + WindowWillUpdateCollectionProperties WindowEventType + WindowWillUpdateShadow WindowEventType + WindowWillUpdateTitle WindowEventType + WindowWillUpdateToolbar WindowEventType + WindowWillUpdateVisibility WindowEventType + WindowWillUseStandardFrame WindowEventType + MenuWillOpen ApplicationEventType + MenuDidOpen ApplicationEventType + MenuDidClose ApplicationEventType + MenuWillSendAction ApplicationEventType + MenuDidSendAction ApplicationEventType + MenuWillHighlightItem ApplicationEventType + MenuDidHighlightItem ApplicationEventType + MenuWillDisplayItem ApplicationEventType + MenuDidDisplayItem ApplicationEventType + MenuWillAddItem ApplicationEventType + MenuDidAddItem ApplicationEventType + MenuWillRemoveItem ApplicationEventType + MenuDidRemoveItem ApplicationEventType + MenuWillBeginTracking ApplicationEventType + MenuDidBeginTracking ApplicationEventType + MenuWillEndTracking ApplicationEventType + MenuDidEndTracking ApplicationEventType + MenuWillUpdate ApplicationEventType + MenuDidUpdate ApplicationEventType + MenuWillPopUp ApplicationEventType + MenuDidPopUp ApplicationEventType + MenuWillSendActionToItem ApplicationEventType + MenuDidSendActionToItem ApplicationEventType } func newMacEvents() macEvents { @@ -193,5 +219,28 @@ func newMacEvents() macEvents { WindowWillUpdateToolbar: 90, WindowWillUpdateVisibility: 91, WindowWillUseStandardFrame: 92, + MenuWillOpen: 93, + MenuDidOpen: 94, + MenuDidClose: 95, + MenuWillSendAction: 96, + MenuDidSendAction: 97, + MenuWillHighlightItem: 98, + MenuDidHighlightItem: 99, + MenuWillDisplayItem: 100, + MenuDidDisplayItem: 101, + MenuWillAddItem: 102, + MenuDidAddItem: 103, + MenuWillRemoveItem: 104, + MenuDidRemoveItem: 105, + MenuWillBeginTracking: 106, + MenuDidBeginTracking: 107, + MenuWillEndTracking: 108, + MenuDidEndTracking: 109, + MenuWillUpdate: 110, + MenuDidUpdate: 111, + MenuWillPopUp: 112, + MenuDidPopUp: 113, + MenuWillSendActionToItem: 114, + MenuDidSendActionToItem: 115, } } diff --git a/exp/pkg/events/events.h b/exp/pkg/events/events.h index de249b749..85e700a95 100644 --- a/exp/pkg/events/events.h +++ b/exp/pkg/events/events.h @@ -3,8 +3,8 @@ #ifndef _events_h #define _events_h -extern void applicationEventHandler(unsigned int); -extern void windowEventHandler(unsigned int, unsigned int); +extern void processApplicationEvent(unsigned int); +extern void processWindowEvent(unsigned int, unsigned int); #define EventApplicationDidBecomeActive 0 #define EventApplicationDidChangeBackingProperties 1 @@ -99,6 +99,29 @@ extern void windowEventHandler(unsigned int, unsigned int); #define EventWindowWillUpdateToolbar 90 #define EventWindowWillUpdateVisibility 91 #define EventWindowWillUseStandardFrame 92 +#define EventMenuWillOpen 93 +#define EventMenuDidOpen 94 +#define EventMenuDidClose 95 +#define EventMenuWillSendAction 96 +#define EventMenuDidSendAction 97 +#define EventMenuWillHighlightItem 98 +#define EventMenuDidHighlightItem 99 +#define EventMenuWillDisplayItem 100 +#define EventMenuDidDisplayItem 101 +#define EventMenuWillAddItem 102 +#define EventMenuDidAddItem 103 +#define EventMenuWillRemoveItem 104 +#define EventMenuDidRemoveItem 105 +#define EventMenuWillBeginTracking 106 +#define EventMenuDidBeginTracking 107 +#define EventMenuWillEndTracking 108 +#define EventMenuDidEndTracking 109 +#define EventMenuWillUpdate 110 +#define EventMenuDidUpdate 111 +#define EventMenuWillPopUp 112 +#define EventMenuDidPopUp 113 +#define EventMenuWillSendActionToItem 114 +#define EventMenuDidSendActionToItem 115 #endif \ No newline at end of file diff --git a/exp/tasks/events/generate.go b/exp/tasks/events/generate.go index 4b57e8453..6fbd018d0 100644 --- a/exp/tasks/events/generate.go +++ b/exp/tasks/events/generate.go @@ -9,6 +9,9 @@ import ( var eventsGo = `package events +type ApplicationEventType uint +type WindowEventType uint + var Mac = newMacEvents() type macEvents struct { @@ -71,7 +74,11 @@ func main() { // Add to buffer switch platform { case "mac": - macEventsDecl.WriteString("\t" + eventTitle + " uint\n") + eventType := "ApplicationEventType" + if strings.HasPrefix(event, "Window") { + eventType = "WindowEventType" + } + macEventsDecl.WriteString("\t" + eventTitle + " " + eventType + "\n") macEventsValues.WriteString("\t\t" + event + ": " + strconv.Itoa(id) + ",\n") cHeaderEvents.WriteString("#define Event" + eventTitle + " " + strconv.Itoa(id) + "\n") if ignoreEvent { From f35b8dfec52303413f08789cd045579f94823485 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Thu, 15 Dec 2022 18:06:09 +1100 Subject: [PATCH 30/85] Refactor Application Add SetActivationPolicy Added labels to menus --- exp/.gitignore | 3 +- exp/examples/systray/main.go | 6 + exp/examples/window/main.go | 33 +++++ exp/pkg/application/application.go | 62 ++++++-- exp/pkg/application/application.h | 6 +- exp/pkg/application/application.m | 22 --- exp/pkg/application/application_darwin.go | 84 ++++++++--- exp/pkg/application/menu.go | 5 + exp/pkg/application/menu_darwin.go | 11 +- exp/pkg/application/menuitem.go | 4 +- exp/pkg/application/menuitem_darwin.go | 168 +++++++++++++++++++++- exp/pkg/application/window_delegate.m | 2 + exp/pkg/options/application.go | 6 + exp/pkg/options/window.go | 8 ++ 14 files changed, 354 insertions(+), 66 deletions(-) create mode 100644 exp/examples/window/main.go delete mode 100644 exp/pkg/application/application.m diff --git a/exp/.gitignore b/exp/.gitignore index 5fbf23563..90fb937c0 100644 --- a/exp/.gitignore +++ b/exp/.gitignore @@ -1,2 +1,3 @@ examples/kitchensink/kitchensink -cmd/wails/wails \ No newline at end of file +cmd/wails/wails +/examples/systray/systray diff --git a/exp/examples/systray/main.go b/exp/examples/systray/main.go index da74bae56..c592a41b2 100644 --- a/exp/examples/systray/main.go +++ b/exp/examples/systray/main.go @@ -4,6 +4,8 @@ import ( _ "embed" "log" + "github.com/wailsapp/wails/exp/pkg/options" + "github.com/wailsapp/wails/exp/pkg/application" ) @@ -12,12 +14,16 @@ var macosIcon []byte func main() { app := application.New() + app.SetActivationPolicy(options.ActivationPolicyAccessory) + systemTray := app.NewSystemTray().SetIcon(macosIcon) myMenu := app.NewMenu() myMenu.Add("Hello World!").OnClick(func(ctx *application.Context) { ctx.ClickedMenuItem().SetLabel("Clicked!") }) + subMenu := myMenu.AddSubmenu("Submenu") + subMenu.Add("Submenu Item") myMenu.AddSeparator() myMenu.Add("Quit").OnClick(func(ctx *application.Context) { app.Quit() diff --git a/exp/examples/window/main.go b/exp/examples/window/main.go new file mode 100644 index 000000000..3c54679db --- /dev/null +++ b/exp/examples/window/main.go @@ -0,0 +1,33 @@ +package main + +import ( + _ "embed" + "log" + + "github.com/wailsapp/wails/exp/pkg/events" + + "github.com/wailsapp/wails/exp/pkg/application" +) + +func main() { + app := application.New() + + // Create menu + appMenu := app.NewMenu() + appMenu.AddSubmenu("") + fileMenu := appMenu.AddSubmenu("File") + fileMenu.Add("New") + app.SetMenu(appMenu) + + // Create window + myWindow := app.NewWindow() + myWindow.On(events.Mac.WindowDidBecomeMain, func() { + println("Window did become main") + }) + + err := app.Run() + + if err != nil { + log.Fatal(err) + } +} diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index d3663a78c..58846b636 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -1,10 +1,13 @@ package application +import "C" import ( "log" "runtime" "sync" + "github.com/wailsapp/wails/exp/pkg/events" + "github.com/wailsapp/wails/exp/pkg/options" ) @@ -12,9 +15,25 @@ func init() { runtime.LockOSThread() } +func New() *App { + return NewWithOptions(nil) +} + +func NewWithOptions(appOptions *options.Application) *App { + if appOptions == nil { + appOptions = options.ApplicationDefaults + } + return &App{ + options: appOptions, + applicationEventListeners: make(map[uint][]func()), + systemTrays: make(map[uint]*SystemTray), + } +} + type platformApp interface { run() error destroy() + setApplicationMenu(menu *Menu) } // Messages sent from javascript get routed here @@ -49,7 +68,10 @@ type App struct { running bool // platform app - app platformApp + impl platformApp + + // The main application menu + ApplicationMenu *Menu } func (a *App) getSystemTrayID() uint { @@ -62,17 +84,17 @@ func (a *App) On(eventType events.ApplicationEventType, callback func()) { eventID := uint(eventType) a.applicationEventListeners[eventID] = append(a.applicationEventListeners[eventID], callback) } +func (a *App) NewWindow() *Window { + return a.NewWindowWithOptions(nil) +} -func (a *App) NewWindow(options *options.Window) *Window { +func (a *App) NewWindowWithOptions(windowOptions *options.Window) *Window { // Ensure we have sane defaults - if options.Width == 0 { - options.Width = 1024 - } - if options.Height == 0 { - options.Height = 768 + if windowOptions == nil { + windowOptions = options.WindowDefaults } - newWindow := NewWindow(options) + newWindow := NewWindow(windowOptions) id := newWindow.id if a.windows == nil { a.windows = make(map[uint]*Window) @@ -81,12 +103,12 @@ func (a *App) NewWindow(options *options.Window) *Window { a.windows[id] = newWindow a.windowsLock.Unlock() - if options.Alias != "" { + if windowOptions.Alias != "" { if a.windowAliases == nil { a.windowAliases = make(map[string]uint) } a.windowAliasesLock.Lock() - a.windowAliases[options.Alias] = id + a.windowAliases[windowOptions.Alias] = id a.windowAliasesLock.Unlock() } if a.running { @@ -111,6 +133,7 @@ func (a *App) NewSystemTray() *SystemTray { } func (a *App) Run() error { + a.impl = newPlatformApp(a.options) a.running = true go func() { @@ -149,7 +172,11 @@ func (a *App) Run() error { go systray.Run() } - return a.run() + if a.ApplicationMenu != nil { + a.impl.setApplicationMenu(a.ApplicationMenu) + } + + return a.impl.run() } func (a *App) handleApplicationEvent(event uint) { @@ -216,5 +243,16 @@ func (a *App) Quit() { wg.Done() }() wg.Wait() - + a.impl.destroy() +} + +func (a *App) SetActivationPolicy(accessory options.ActivationPolicy) { + a.options.Mac.ActivationPolicy = accessory +} + +func (a *App) SetMenu(menu *Menu) { + a.ApplicationMenu = menu + if a.impl != nil { + a.impl.setApplicationMenu(menu) + } } diff --git a/exp/pkg/application/application.h b/exp/pkg/application/application.h index 6efc1825a..4955d468e 100644 --- a/exp/pkg/application/application.h +++ b/exp/pkg/application/application.h @@ -3,8 +3,8 @@ #ifndef application_h #define application_h -void Init(void); -void Run(void); -void SetActivationPolicy(int policy); +static void init(void); +static void run(void); +static void setActivationPolicy(int policy); #endif \ No newline at end of file diff --git a/exp/pkg/application/application.m b/exp/pkg/application/application.m deleted file mode 100644 index 3833b8deb..000000000 --- a/exp/pkg/application/application.m +++ /dev/null @@ -1,22 +0,0 @@ -//go:build darwin - -#import "app_delegate.h" - -AppDelegate *appDelegate = nil; - -void Init(void) { - [NSApplication sharedApplication]; - appDelegate = [[AppDelegate alloc] init]; - [NSApp setDelegate:appDelegate]; -} - -void SetActivationPolicy(int policy) { - [appDelegate setApplicationActivationPolicy:policy]; -} - -void Run(void) { - @autoreleasepool { - [NSApp run]; - [appDelegate release]; - } -} diff --git a/exp/pkg/application/application_darwin.go b/exp/pkg/application/application_darwin.go index 13f972263..2ed23ef8f 100644 --- a/exp/pkg/application/application_darwin.go +++ b/exp/pkg/application/application_darwin.go @@ -6,43 +6,83 @@ package application #cgo CFLAGS: -x objective-c #cgo LDFLAGS: -framework Cocoa -mmacosx-version-min=10.13 + #include "application.h" +#include "app_delegate.h" #include + +#import + +static AppDelegate *appDelegate = nil; + +static void init(void) { + [NSApplication sharedApplication]; + appDelegate = [[AppDelegate alloc] init]; + [NSApp setDelegate:appDelegate]; +} + +static void setActivationPolicy(int policy) { + [appDelegate setApplicationActivationPolicy:policy]; +} + +static void run(void) { + @autoreleasepool { + [NSApp run]; + [appDelegate release]; + } +} + +// Destroy application +static void destroyApp(void) { + [NSApp terminate:nil]; +} + +// Set the application menu +static void setApplicationMenu(void *menu) { + NSMenu *nsMenu = (__bridge NSMenu *)menu; + [NSApp setMainMenu:menu]; +} + */ import "C" import ( + "unsafe" + "github.com/wailsapp/wails/exp/pkg/options" ) -func New() *App { - C.Init() - return newApp() +type macosApp struct { + options *options.Application + applicationMenu unsafe.Pointer } -func newApp() *App { - return &App{ - applicationEventListeners: make(map[uint][]func()), - systemTrays: make(map[uint]*SystemTray), - } +func (m macosApp) setApplicationMenu(menu *Menu) { + menu.Update() + // Convert impl to macosMenu object + m.applicationMenu = (menu.impl).(*macosMenu).nsMenu + C.setApplicationMenu(m.applicationMenu) } -func NewWithOptions(options *options.Application) *App { - C.Init() - if options.Mac != nil { - C.SetActivationPolicy(C.int(options.Mac.ActivationPolicy)) - } - return &App{ - options: options, - applicationEventListeners: make(map[uint][]func()), - systemTrays: make(map[uint]*SystemTray), - } -} - -func (a *App) run() error { - C.Run() +func (m macosApp) run() error { + C.run() return nil } +func (m macosApp) destroy() { + C.destroyApp() +} + +func newPlatformApp(appOptions *options.Application) *macosApp { + if appOptions == nil { + appOptions = options.ApplicationDefaults + } + C.init() + C.setActivationPolicy(C.int(appOptions.Mac.ActivationPolicy)) + return &macosApp{ + options: appOptions, + } +} + //export processApplicationEvent func processApplicationEvent(eventID C.uint) { applicationEvents <- uint(eventID) diff --git a/exp/pkg/application/menu.go b/exp/pkg/application/menu.go index 49a2f2c96..db7e20bc0 100644 --- a/exp/pkg/application/menu.go +++ b/exp/pkg/application/menu.go @@ -6,6 +6,7 @@ type menuImpl interface { type Menu struct { items []*MenuItem + label string impl menuImpl } @@ -68,6 +69,10 @@ func (m *Menu) processRadioGroups() { } } +func (m *Menu) SetLabel(label string) { + m.label = label +} + func (a *App) NewMenu() *Menu { return &Menu{} } diff --git a/exp/pkg/application/menu_darwin.go b/exp/pkg/application/menu_darwin.go index 8c97dd98f..58a8f2a0e 100644 --- a/exp/pkg/application/menu_darwin.go +++ b/exp/pkg/application/menu_darwin.go @@ -18,8 +18,12 @@ void clearMenu(void* nsMenu) { // Create a new NSMenu -void* createNSMenu() { +void* createNSMenu(char* label) { NSMenu *menu = [[NSMenu alloc] init]; + if( label != NULL && strlen(label) > 0 ) { + menu.title = [NSString stringWithUTF8String:label]; + free(label); + } return (void*)menu; } @@ -60,7 +64,7 @@ func newMenuImpl(menu *Menu) *macosMenu { func (m *macosMenu) update() { if m.nsMenu == nil { - m.nsMenu = C.createNSMenu() + m.nsMenu = C.createNSMenu(C.CString(m.menu.label)) } else { C.clearMenu(m.nsMenu) } @@ -72,7 +76,7 @@ func (m *macosMenu) processMenu(parent unsafe.Pointer, menu *Menu) { switch item.itemType { case submenu: submenu := item.submenu - nsSubmenu := C.createNSMenu() + nsSubmenu := C.createNSMenu(C.CString(submenu.label)) m.processMenu(nsSubmenu, submenu) menuItem := newMenuItemImpl(item) item.impl = menuItem @@ -87,5 +91,4 @@ func (m *macosMenu) processMenu(parent unsafe.Pointer, menu *Menu) { } } - //C.setMenu(parent, m.nsMenu) } diff --git a/exp/pkg/application/menuitem.go b/exp/pkg/application/menuitem.go index e3820567b..7eaad2833 100644 --- a/exp/pkg/application/menuitem.go +++ b/exp/pkg/application/menuitem.go @@ -98,7 +98,9 @@ func newSubMenuItem(label string) *MenuItem { id: uint(atomic.AddUintptr(&menuItemID, 1)), label: label, itemType: submenu, - submenu: &Menu{}, + submenu: &Menu{ + label: label, + }, } addToMenuItemMap(result) return result diff --git a/exp/pkg/application/menuitem_darwin.go b/exp/pkg/application/menuitem_darwin.go index 725c3c598..adb7d5289 100644 --- a/exp/pkg/application/menuitem_darwin.go +++ b/exp/pkg/application/menuitem_darwin.go @@ -7,6 +7,8 @@ package application #include "Cocoa/Cocoa.h" #include "menuitem.h" +#define unicode(input) [NSString stringWithFormat:@"%C", input] + // Create menu item void* newMenuItem(unsigned int menuItemID, char *label, bool disabled, char* tooltip) { MenuItem *menuItem = [MenuItem new]; @@ -69,10 +71,174 @@ void setMenuItemChecked(void* nsMenuItem, bool checked) { menuItem.state = checked ? NSControlStateValueOn : NSControlStateValueOff; } +NSString* translateKey(NSString* key) { + + // Guard against no accelerator key + if( key == NULL ) { + return @""; + } + + if( [key isEqualToString:@"backspace"] ) { + return unicode(0x0008); + } + if( [key isEqualToString:@"tab"] ) { + return unicode(0x0009); + } + if( [key isEqualToString:@"return"] ) { + return unicode(0x000d); + } + if( [key isEqualToString:@"enter"] ) { + return unicode(0x000d); + } + if( [key isEqualToString:@"escape"] ) { + return unicode(0x001b); + } + if( [key isEqualToString:@"left"] ) { + return unicode(0x001c); + } + if( [key isEqualToString:@"right"] ) { + return unicode(0x001d); + } + if( [key isEqualToString:@"up"] ) { + return unicode(0x001e); + } + if( [key isEqualToString:@"down"] ) { + return unicode(0x001f); + } + if( [key isEqualToString:@"space"] ) { + return unicode(0x0020); + } + if( [key isEqualToString:@"delete"] ) { + return unicode(0x007f); + } + if( [key isEqualToString:@"home"] ) { + return unicode(0x2196); + } + if( [key isEqualToString:@"end"] ) { + return unicode(0x2198); + } + if( [key isEqualToString:@"page up"] ) { + return unicode(0x21de); + } + if( [key isEqualToString:@"page down"] ) { + return unicode(0x21df); + } + if( [key isEqualToString:@"f1"] ) { + return unicode(0xf704); + } + if( [key isEqualToString:@"f2"] ) { + return unicode(0xf705); + } + if( [key isEqualToString:@"f3"] ) { + return unicode(0xf706); + } + if( [key isEqualToString:@"f4"] ) { + return unicode(0xf707); + } + if( [key isEqualToString:@"f5"] ) { + return unicode(0xf708); + } + if( [key isEqualToString:@"f6"] ) { + return unicode(0xf709); + } + if( [key isEqualToString:@"f7"] ) { + return unicode(0xf70a); + } + if( [key isEqualToString:@"f8"] ) { + return unicode(0xf70b); + } + if( [key isEqualToString:@"f9"] ) { + return unicode(0xf70c); + } + if( [key isEqualToString:@"f10"] ) { + return unicode(0xf70d); + } + if( [key isEqualToString:@"f11"] ) { + return unicode(0xf70e); + } + if( [key isEqualToString:@"f12"] ) { + return unicode(0xf70f); + } + if( [key isEqualToString:@"f13"] ) { + return unicode(0xf710); + } + if( [key isEqualToString:@"f14"] ) { + return unicode(0xf711); + } + if( [key isEqualToString:@"f15"] ) { + return unicode(0xf712); + } + if( [key isEqualToString:@"f16"] ) { + return unicode(0xf713); + } + if( [key isEqualToString:@"f17"] ) { + return unicode(0xf714); + } + if( [key isEqualToString:@"f18"] ) { + return unicode(0xf715); + } + if( [key isEqualToString:@"f19"] ) { + return unicode(0xf716); + } + if( [key isEqualToString:@"f20"] ) { + return unicode(0xf717); + } + if( [key isEqualToString:@"f21"] ) { + return unicode(0xf718); + } + if( [key isEqualToString:@"f22"] ) { + return unicode(0xf719); + } + if( [key isEqualToString:@"f23"] ) { + return unicode(0xf71a); + } + if( [key isEqualToString:@"f24"] ) { + return unicode(0xf71b); + } + if( [key isEqualToString:@"f25"] ) { + return unicode(0xf71c); + } + if( [key isEqualToString:@"f26"] ) { + return unicode(0xf71d); + } + if( [key isEqualToString:@"f27"] ) { + return unicode(0xf71e); + } + if( [key isEqualToString:@"f28"] ) { + return unicode(0xf71f); + } + if( [key isEqualToString:@"f29"] ) { + return unicode(0xf720); + } + if( [key isEqualToString:@"f30"] ) { + return unicode(0xf721); + } + if( [key isEqualToString:@"f31"] ) { + return unicode(0xf722); + } + if( [key isEqualToString:@"f32"] ) { + return unicode(0xf723); + } + if( [key isEqualToString:@"f33"] ) { + return unicode(0xf724); + } + if( [key isEqualToString:@"f34"] ) { + return unicode(0xf725); + } + if( [key isEqualToString:@"f35"] ) { + return unicode(0xf726); + } + if( [key isEqualToString:@"numLock"] ) { + return unicode(0xf739); + } + return key; +} + // Set the menuitem key equivalent void setMenuItemKeyEquivalent(void* nsMenuItem, char *key, int modifier) { MenuItem *menuItem = (MenuItem *)nsMenuItem; - menuItem.keyEquivalent = [NSString stringWithUTF8String:key]; + NSString *nskey = [NSString stringWithUTF8String:key]; + menuItem.keyEquivalent = translateKey(nskey); menuItem.keyEquivalentModifierMask = modifier; free(key); } diff --git a/exp/pkg/application/window_delegate.m b/exp/pkg/application/window_delegate.m index 3d07620e6..a602500fc 100644 --- a/exp/pkg/application/window_delegate.m +++ b/exp/pkg/application/window_delegate.m @@ -349,3 +349,5 @@ + + diff --git a/exp/pkg/options/application.go b/exp/pkg/options/application.go index afc004245..d5226f6b5 100644 --- a/exp/pkg/options/application.go +++ b/exp/pkg/options/application.go @@ -3,3 +3,9 @@ package options type Application struct { Mac *Mac } + +var ApplicationDefaults = &Application{ + Mac: &Mac{ + ActivationPolicy: ActivationPolicyRegular, + }, +} diff --git a/exp/pkg/options/window.go b/exp/pkg/options/window.go index e1c44563f..f0f8c011f 100644 --- a/exp/pkg/options/window.go +++ b/exp/pkg/options/window.go @@ -34,6 +34,14 @@ type Window struct { Assets Assets } +var WindowDefaults = &Window{ + Title: "", + Width: 1024, + Height: 768, + URL: "https://wails.io", + EnableDevTools: true, +} + type Assets struct { // URL to load the `index.html` file from. If this is a relative path, it will be resolved relative to the `FS` filesystem URL string From faf418eac0f38bf39b1a43886ecb6c81a527637a Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Thu, 15 Dec 2022 21:21:19 +1100 Subject: [PATCH 31/85] Add global reference for application Add default application meu for Mac Add window example Fix invalid accelerator error logging --- exp/.gitignore | 1 + exp/examples/window/main.go | 7 -- exp/pkg/application/application.go | 17 ++- exp/pkg/application/application_darwin.go | 132 +++++++++++++++++++++- exp/pkg/application/menu.go | 4 + exp/pkg/application/menuitem.go | 2 +- 6 files changed, 148 insertions(+), 15 deletions(-) diff --git a/exp/.gitignore b/exp/.gitignore index 90fb937c0..a57f29269 100644 --- a/exp/.gitignore +++ b/exp/.gitignore @@ -1,3 +1,4 @@ examples/kitchensink/kitchensink cmd/wails/wails /examples/systray/systray +/examples/window/window diff --git a/exp/examples/window/main.go b/exp/examples/window/main.go index 3c54679db..f5f4b52a7 100644 --- a/exp/examples/window/main.go +++ b/exp/examples/window/main.go @@ -12,13 +12,6 @@ import ( func main() { app := application.New() - // Create menu - appMenu := app.NewMenu() - appMenu.AddSubmenu("") - fileMenu := appMenu.AddSubmenu("File") - fileMenu.Add("New") - app.SetMenu(appMenu) - // Create window myWindow := app.NewWindow() myWindow.On(events.Mac.WindowDidBecomeMain, func() { diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index 58846b636..7facd4721 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -11,23 +11,33 @@ import ( "github.com/wailsapp/wails/exp/pkg/options" ) +var globalApplication *App + func init() { runtime.LockOSThread() } func New() *App { + if globalApplication != nil { + return globalApplication + } return NewWithOptions(nil) } func NewWithOptions(appOptions *options.Application) *App { + if globalApplication != nil { + return globalApplication + } if appOptions == nil { appOptions = options.ApplicationDefaults } - return &App{ + result := &App{ options: appOptions, applicationEventListeners: make(map[uint][]func()), systemTrays: make(map[uint]*SystemTray), } + globalApplication = result + return result } type platformApp interface { @@ -172,9 +182,8 @@ func (a *App) Run() error { go systray.Run() } - if a.ApplicationMenu != nil { - a.impl.setApplicationMenu(a.ApplicationMenu) - } + // set the application menu + a.impl.setApplicationMenu(a.ApplicationMenu) return a.impl.run() } diff --git a/exp/pkg/application/application_darwin.go b/exp/pkg/application/application_darwin.go index 2ed23ef8f..ecfccebdf 100644 --- a/exp/pkg/application/application_darwin.go +++ b/exp/pkg/application/application_darwin.go @@ -43,6 +43,81 @@ static void setApplicationMenu(void *menu) { [NSApp setMainMenu:menu]; } +// Get the application name +static char *getAppName(void) { + NSString *appName = [NSRunningApplication currentApplication].localizedName; + if( appName == nil ) { + appName = [[NSProcessInfo processInfo] processName]; + } + return strdup([appName UTF8String]); +} + +// Call the copy selector on the pasteboard +static void copyToPasteboard(char *text) { + NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + [pasteboard clearContents]; + [pasteboard setString:[NSString stringWithUTF8String:text] forType:NSPasteboardTypeString]; +} + +// Call the paste selector on the pasteboard +static char *pasteFromPasteboard(void) { + NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + NSString *text = [pasteboard stringForType:NSPasteboardTypeString]; + if( text == nil ) { + return NULL; + } + return strdup([text UTF8String]); +} + +// Call paste selector to paste text +static void paste(void) { + [NSApp sendAction:@selector(paste:) to:nil from:nil]; +} + +// Call copy selector to copy text +static void copy(void) { + [NSApp sendAction:@selector(copy:) to:nil from:nil]; +} + +// Call cut selector to cut text +static void cut(void) { + [NSApp sendAction:@selector(cut:) to:nil from:nil]; +} + +// Call selectAll selector to select all text +static void selectAll(void) { + [NSApp sendAction:@selector(selectAll:) to:nil from:nil]; +} + +// Call delete selector to delete text +static void delete(void) { + [NSApp sendAction:@selector(delete:) to:nil from:nil]; +} + +// Call undo selector to undo text +static void undo(void) { + [NSApp sendAction:@selector(undo:) to:nil from:nil]; +} + +// Call redo selector to redo text +static void redo(void) { + [NSApp sendAction:@selector(redo:) to:nil from:nil]; +} + +// Call startSpeaking selector to start speaking text +static void startSpeaking(void) { + [NSApp sendAction:@selector(startSpeaking:) to:nil from:nil]; +} + +// Call stopSpeaking selector to stop speaking text +static void stopSpeaking(void) { + [NSApp sendAction:@selector(stopSpeaking:) to:nil from:nil]; +} + +static void pasteAndMatchStyle(void) { + [NSApp sendAction:@selector(pasteAndMatchStyle:) to:nil from:nil]; +} + */ import "C" import ( @@ -56,22 +131,73 @@ type macosApp struct { applicationMenu unsafe.Pointer } -func (m macosApp) setApplicationMenu(menu *Menu) { +func (m *macosApp) setApplicationMenu(menu *Menu) { + if menu == nil { + // Create a default menu for mac + menu = m.createDefaultApplicationMenu() + } menu.Update() // Convert impl to macosMenu object m.applicationMenu = (menu.impl).(*macosMenu).nsMenu C.setApplicationMenu(m.applicationMenu) } -func (m macosApp) run() error { +func (m *macosApp) run() error { C.run() return nil } -func (m macosApp) destroy() { +func (m *macosApp) destroy() { C.destroyApp() } +func (m *macosApp) createDefaultApplicationMenu() *Menu { + // Create a default menu for mac + menu := NewMenu() + cAppName := C.getAppName() + defer C.free(unsafe.Pointer(cAppName)) + appName := C.GoString(cAppName) + appMenu := menu.AddSubmenu(appName) + appMenu.Add("Quit " + appName).SetAccelerator("CmdOrCtrl+q").OnClick(func(ctx *Context) { + globalApplication.Quit() + }) + editMenu := menu.AddSubmenu("Edit") + editMenu.Add("Undo").SetAccelerator("CmdOrCtrl+z").OnClick(func(ctx *Context) { + C.undo() + }) + editMenu.Add("Redo").SetAccelerator("CmdOrCtrl+Shift+z").OnClick(func(ctx *Context) { + C.redo() + }) + editMenu.AddSeparator() + editMenu.Add("Cut").SetAccelerator("CmdOrCtrl+x").OnClick(func(ctx *Context) { + C.cut() + }) + editMenu.Add("Copy").SetAccelerator("CmdOrCtrl+c").OnClick(func(ctx *Context) { + C.copy() + }) + editMenu.Add("Paste").SetAccelerator("CmdOrCtrl+v").OnClick(func(ctx *Context) { + C.paste() + }) + editMenu.Add("Paste and Match Style").SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+v").OnClick(func(ctx *Context) { + C.pasteAndMatchStyle() + }) + editMenu.Add("Delete").SetAccelerator("backspace").OnClick(func(ctx *Context) { + C.delete() + }) + editMenu.Add("Select All").SetAccelerator("CmdOrCtrl+a").OnClick(func(ctx *Context) { + C.selectAll() + }) + editMenu.AddSeparator() + speechMenu := editMenu.AddSubmenu("Speech") + speechMenu.Add("Start Speaking").SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+.").OnClick(func(ctx *Context) { + C.startSpeaking() + }) + speechMenu.Add("Stop Speaking").SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+,").OnClick(func(ctx *Context) { + C.stopSpeaking() + }) + return menu +} + func newPlatformApp(appOptions *options.Application) *macosApp { if appOptions == nil { appOptions = options.ApplicationDefaults diff --git a/exp/pkg/application/menu.go b/exp/pkg/application/menu.go index db7e20bc0..d6d920e81 100644 --- a/exp/pkg/application/menu.go +++ b/exp/pkg/application/menu.go @@ -11,6 +11,10 @@ type Menu struct { impl menuImpl } +func NewMenu() *Menu { + return &Menu{} +} + func (m *Menu) Add(label string) *MenuItem { result := newMenuItem(label) m.items = append(m.items, result) diff --git a/exp/pkg/application/menuitem.go b/exp/pkg/application/menuitem.go index 7eaad2833..4105fd221 100644 --- a/exp/pkg/application/menuitem.go +++ b/exp/pkg/application/menuitem.go @@ -130,7 +130,7 @@ func (m *MenuItem) handleClick() { func (m *MenuItem) SetAccelerator(shortcut string) *MenuItem { accelerator, err := parseAccelerator(shortcut) if err != nil { - println("ERROR: invalid accelerator", err) + println("ERROR: invalid accelerator:", err.Error()) return m } m.accelerator = accelerator From 475880c0a8284d11dbe8d41f34b3812c6b80a325 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Fri, 16 Dec 2022 20:02:03 +1100 Subject: [PATCH 32/85] Add services, hide, hideothers, unhide role Add application.Name() refactor roles Add app menu role --- exp/examples/menu/main.go | 24 ++++ exp/pkg/application/TODO.md | 10 ++ exp/pkg/application/application.go | 9 ++ exp/pkg/application/application.h | 1 + exp/pkg/application/application_darwin.go | 118 ++-------------- exp/pkg/application/menu.go | 6 + exp/pkg/application/menu_darwin.go | 10 ++ exp/pkg/application/menuitem.go | 31 ++++ exp/pkg/application/menuitem_darwin.go | 163 +++++++++++++++++++++- exp/pkg/application/roles.go | 39 ++++++ exp/pkg/application/window_devtools.go | 43 ++++++ 11 files changed, 345 insertions(+), 109 deletions(-) create mode 100644 exp/examples/menu/main.go create mode 100644 exp/pkg/application/TODO.md create mode 100644 exp/pkg/application/roles.go create mode 100644 exp/pkg/application/window_devtools.go diff --git a/exp/examples/menu/main.go b/exp/examples/menu/main.go new file mode 100644 index 000000000..ea106a459 --- /dev/null +++ b/exp/examples/menu/main.go @@ -0,0 +1,24 @@ +package main + +import ( + _ "embed" + "log" + + "github.com/wailsapp/wails/exp/pkg/application" +) + +func main() { + app := application.New() + + myMenu := app.NewMenu() + myMenu.AddRole(application.AppMenu) + myMenu.AddRole(application.EditMenu) + + app.SetMenu(myMenu) + + err := app.Run() + + if err != nil { + log.Fatal(err) + } +} diff --git a/exp/pkg/application/TODO.md b/exp/pkg/application/TODO.md new file mode 100644 index 000000000..ae4700425 --- /dev/null +++ b/exp/pkg/application/TODO.md @@ -0,0 +1,10 @@ + +Features +- [ ] AssetServer +- [ ] Offline page if navigating to external URL +- [x] Application menu + +Bugs +- [ ] Resize Window +- [ ] Fullscreen/Maximise/Minimise/Restore + diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index 7facd4721..7a32653f6 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -44,6 +44,7 @@ type platformApp interface { run() error destroy() setApplicationMenu(menu *Menu) + name() string } // Messages sent from javascript get routed here @@ -55,6 +56,7 @@ type windowMessage struct { var windowMessageBuffer = make(chan *windowMessage) type App struct { + name string options *options.Application applicationEventListeners map[uint][]func() @@ -265,3 +267,10 @@ func (a *App) SetMenu(menu *Menu) { a.impl.setApplicationMenu(menu) } } + +func (a *App) Name() string { + if a.impl != nil && a.name == "" { + a.name = a.impl.name() + } + return a.name +} diff --git a/exp/pkg/application/application.h b/exp/pkg/application/application.h index 4955d468e..e67384397 100644 --- a/exp/pkg/application/application.h +++ b/exp/pkg/application/application.h @@ -6,5 +6,6 @@ static void init(void); static void run(void); static void setActivationPolicy(int policy); +static char *getAppName(void); #endif \ No newline at end of file diff --git a/exp/pkg/application/application_darwin.go b/exp/pkg/application/application_darwin.go index ecfccebdf..61abb4736 100644 --- a/exp/pkg/application/application_darwin.go +++ b/exp/pkg/application/application_darwin.go @@ -44,7 +44,7 @@ static void setApplicationMenu(void *menu) { } // Get the application name -static char *getAppName(void) { +static char* getAppName(void) { NSString *appName = [NSRunningApplication currentApplication].localizedName; if( appName == nil ) { appName = [[NSProcessInfo processInfo] processName]; @@ -52,72 +52,6 @@ static char *getAppName(void) { return strdup([appName UTF8String]); } -// Call the copy selector on the pasteboard -static void copyToPasteboard(char *text) { - NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; - [pasteboard clearContents]; - [pasteboard setString:[NSString stringWithUTF8String:text] forType:NSPasteboardTypeString]; -} - -// Call the paste selector on the pasteboard -static char *pasteFromPasteboard(void) { - NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; - NSString *text = [pasteboard stringForType:NSPasteboardTypeString]; - if( text == nil ) { - return NULL; - } - return strdup([text UTF8String]); -} - -// Call paste selector to paste text -static void paste(void) { - [NSApp sendAction:@selector(paste:) to:nil from:nil]; -} - -// Call copy selector to copy text -static void copy(void) { - [NSApp sendAction:@selector(copy:) to:nil from:nil]; -} - -// Call cut selector to cut text -static void cut(void) { - [NSApp sendAction:@selector(cut:) to:nil from:nil]; -} - -// Call selectAll selector to select all text -static void selectAll(void) { - [NSApp sendAction:@selector(selectAll:) to:nil from:nil]; -} - -// Call delete selector to delete text -static void delete(void) { - [NSApp sendAction:@selector(delete:) to:nil from:nil]; -} - -// Call undo selector to undo text -static void undo(void) { - [NSApp sendAction:@selector(undo:) to:nil from:nil]; -} - -// Call redo selector to redo text -static void redo(void) { - [NSApp sendAction:@selector(redo:) to:nil from:nil]; -} - -// Call startSpeaking selector to start speaking text -static void startSpeaking(void) { - [NSApp sendAction:@selector(startSpeaking:) to:nil from:nil]; -} - -// Call stopSpeaking selector to stop speaking text -static void stopSpeaking(void) { - [NSApp sendAction:@selector(stopSpeaking:) to:nil from:nil]; -} - -static void pasteAndMatchStyle(void) { - [NSApp sendAction:@selector(pasteAndMatchStyle:) to:nil from:nil]; -} - */ import "C" import ( @@ -131,6 +65,12 @@ type macosApp struct { applicationMenu unsafe.Pointer } +func (m *macosApp) name() string { + appName := C.getAppName() + defer C.free(unsafe.Pointer(appName)) + return C.GoString(appName) +} + func (m *macosApp) setApplicationMenu(menu *Menu) { if menu == nil { // Create a default menu for mac @@ -154,47 +94,9 @@ func (m *macosApp) destroy() { func (m *macosApp) createDefaultApplicationMenu() *Menu { // Create a default menu for mac menu := NewMenu() - cAppName := C.getAppName() - defer C.free(unsafe.Pointer(cAppName)) - appName := C.GoString(cAppName) - appMenu := menu.AddSubmenu(appName) - appMenu.Add("Quit " + appName).SetAccelerator("CmdOrCtrl+q").OnClick(func(ctx *Context) { - globalApplication.Quit() - }) - editMenu := menu.AddSubmenu("Edit") - editMenu.Add("Undo").SetAccelerator("CmdOrCtrl+z").OnClick(func(ctx *Context) { - C.undo() - }) - editMenu.Add("Redo").SetAccelerator("CmdOrCtrl+Shift+z").OnClick(func(ctx *Context) { - C.redo() - }) - editMenu.AddSeparator() - editMenu.Add("Cut").SetAccelerator("CmdOrCtrl+x").OnClick(func(ctx *Context) { - C.cut() - }) - editMenu.Add("Copy").SetAccelerator("CmdOrCtrl+c").OnClick(func(ctx *Context) { - C.copy() - }) - editMenu.Add("Paste").SetAccelerator("CmdOrCtrl+v").OnClick(func(ctx *Context) { - C.paste() - }) - editMenu.Add("Paste and Match Style").SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+v").OnClick(func(ctx *Context) { - C.pasteAndMatchStyle() - }) - editMenu.Add("Delete").SetAccelerator("backspace").OnClick(func(ctx *Context) { - C.delete() - }) - editMenu.Add("Select All").SetAccelerator("CmdOrCtrl+a").OnClick(func(ctx *Context) { - C.selectAll() - }) - editMenu.AddSeparator() - speechMenu := editMenu.AddSubmenu("Speech") - speechMenu.Add("Start Speaking").SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+.").OnClick(func(ctx *Context) { - C.startSpeaking() - }) - speechMenu.Add("Stop Speaking").SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+,").OnClick(func(ctx *Context) { - C.stopSpeaking() - }) + newAppMenu(menu) + newEditMenu(menu) + return menu } diff --git a/exp/pkg/application/menu.go b/exp/pkg/application/menu.go index d6d920e81..8bec6f01a 100644 --- a/exp/pkg/application/menu.go +++ b/exp/pkg/application/menu.go @@ -52,6 +52,12 @@ func (m *Menu) AddSubmenu(s string) *Menu { return result.submenu } +func (m *Menu) AddRole(role Role) *Menu { + result := newRole(m, role) + m.items = append(m.items, result) + return m +} + func (m *Menu) processRadioGroups() { var radioGroup []*MenuItem for _, item := range m.items { diff --git a/exp/pkg/application/menu_darwin.go b/exp/pkg/application/menu_darwin.go index 58a8f2a0e..0d25983d4 100644 --- a/exp/pkg/application/menu_darwin.go +++ b/exp/pkg/application/menu_darwin.go @@ -45,6 +45,13 @@ void setMenuItemSubmenu(void* nsMenuItem, void* nsMenu) { [menuItem setSubmenu:menu]; } +// Add services menu +static void addServicesMenu(void* menu) { + NSMenu *nsMenu = (__bridge NSMenu *)menu; + [NSApp setServicesMenu:nsMenu]; +} + + */ import "C" import "unsafe" @@ -82,6 +89,9 @@ func (m *macosMenu) processMenu(parent unsafe.Pointer, menu *Menu) { item.impl = menuItem C.addMenuItem(parent, menuItem.nsMenuItem) C.setMenuItemSubmenu(menuItem.nsMenuItem, nsSubmenu) + if item.role == ServicesMenu { + C.addServicesMenu(nsSubmenu) + } case text, checkbox, radio: menuItem := newMenuItemImpl(item) item.impl = menuItem diff --git a/exp/pkg/application/menuitem.go b/exp/pkg/application/menuitem.go index 4105fd221..746f61139 100644 --- a/exp/pkg/application/menuitem.go +++ b/exp/pkg/application/menuitem.go @@ -49,6 +49,7 @@ type MenuItem struct { callback func(*Context) itemType menuItemType accelerator *accelerator + role Role impl menuItemImpl radioGroupMembers []*MenuItem @@ -106,6 +107,36 @@ func newSubMenuItem(label string) *MenuItem { return result } +func newRole(parentMenu *Menu, role Role) *MenuItem { + var roleMenu *Menu + switch role { + case AppMenu: + roleMenu = newAppMenu(parentMenu) + case EditMenu: + roleMenu = newEditMenu(parentMenu) + case ServicesMenu: + roleMenu = newServicesMenu() + case Hide: + return newHideMenuItem() + case HideOthers: + return newHideOthersMenuItem() + case UnHide: + return newUnhideMenuItem() + } + return roleMenu.items[0] +} + +func newServicesMenu() *Menu { + serviceMenu := newSubMenuItem("Services") + serviceMenu.role = ServicesMenu + return &Menu{ + label: "Services", + items: []*MenuItem{ + serviceMenu, + }, + } +} + func (m *MenuItem) handleClick() { var ctx = newContext().withClickedMenuItem(m) if m.itemType == checkbox { diff --git a/exp/pkg/application/menuitem_darwin.go b/exp/pkg/application/menuitem_darwin.go index adb7d5289..9aca135b1 100644 --- a/exp/pkg/application/menuitem_darwin.go +++ b/exp/pkg/application/menuitem_darwin.go @@ -6,6 +6,7 @@ package application #include "Cocoa/Cocoa.h" #include "menuitem.h" +#include "application.h" #define unicode(input) [NSString stringWithFormat:@"%C", input] @@ -243,6 +244,85 @@ void setMenuItemKeyEquivalent(void* nsMenuItem, char *key, int modifier) { free(key); } +// Call the copy selector on the pasteboard +static void copyToPasteboard(char *text) { + NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + [pasteboard clearContents]; + [pasteboard setString:[NSString stringWithUTF8String:text] forType:NSPasteboardTypeString]; +} + +// Call the paste selector on the pasteboard +static char *pasteFromPasteboard(void) { + NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + NSString *text = [pasteboard stringForType:NSPasteboardTypeString]; + if( text == nil ) { + return NULL; + } + return strdup([text UTF8String]); +} + +// Call paste selector to paste text +static void paste(void) { + [NSApp sendAction:@selector(paste:) to:nil from:nil]; +} + +// Call copy selector to copy text +static void copy(void) { + [NSApp sendAction:@selector(copy:) to:nil from:nil]; +} + +// Call cut selector to cut text +static void cut(void) { + [NSApp sendAction:@selector(cut:) to:nil from:nil]; +} + +// Call selectAll selector to select all text +static void selectAll(void) { + [NSApp sendAction:@selector(selectAll:) to:nil from:nil]; +} + +// Call delete selector to delete text +static void delete(void) { + [NSApp sendAction:@selector(delete:) to:nil from:nil]; +} + +// Call undo selector to undo text +static void undo(void) { + [NSApp sendAction:@selector(undo:) to:nil from:nil]; +} + +// Call redo selector to redo text +static void redo(void) { + [NSApp sendAction:@selector(redo:) to:nil from:nil]; +} + +// Call startSpeaking selector to start speaking text +static void startSpeaking(void) { + [NSApp sendAction:@selector(startSpeaking:) to:nil from:nil]; +} + +// Call stopSpeaking selector to stop speaking text +static void stopSpeaking(void) { + [NSApp sendAction:@selector(stopSpeaking:) to:nil from:nil]; +} + +static void pasteAndMatchStyle(void) { + [NSApp sendAction:@selector(pasteAndMatchStyle:) to:nil from:nil]; +} + +static void hideApplication(void) { + [[NSApplication sharedApplication] hide:nil]; +} + +// hideOthers hides all other applications +static void hideOthers(void) { + [[NSApplication sharedApplication] hideOtherApplications:nil]; +} + +// showAll shows all hidden applications +static void showAll(void) { + [[NSApplication sharedApplication] unhideAllApplications:nil]; +} */ import "C" @@ -283,13 +363,13 @@ func (m macosMenuItem) setAccelerator(accelerator *accelerator) { // Convert the key to a string C.setMenuItemKeyEquivalent(m.nsMenuItem, key, modifier) - } func newMenuItemImpl(item *MenuItem) *macosMenuItem { result := &macosMenuItem{ menuItem: item, } + switch item.itemType { case text, checkbox, submenu, radio: result.nsMenuItem = unsafe.Pointer(C.newMenuItem(C.uint(item.id), C.CString(item.label), C.bool(item.disabled), C.CString(item.tooltip))) @@ -304,3 +384,84 @@ func newMenuItemImpl(item *MenuItem) *macosMenuItem { } return result } + +func newAppMenu(menu *Menu) *Menu { + appName := globalApplication.Name() + appMenu := menu.AddSubmenu(appName) + appMenu.Add("About " + appName).OnClick(func(*Context) { + //TODO: implement + }) + appMenu.AddSeparator() + appMenu.AddRole(ServicesMenu) + appMenu.AddSeparator() + appMenu.AddRole(Hide) + appMenu.AddRole(HideOthers) + appMenu.AddRole(UnHide) + appMenu.AddSeparator() + + appMenu.Add("Quit " + appName).SetAccelerator("CmdOrCtrl+q").OnClick(func(ctx *Context) { + globalApplication.Quit() + }) + return appMenu +} + +func newEditMenu(menu *Menu) *Menu { + editMenu := menu.AddSubmenu("Edit") + editMenu.Add("Undo").SetAccelerator("CmdOrCtrl+z").OnClick(func(ctx *Context) { + C.undo() + }) + editMenu.Add("Redo").SetAccelerator("CmdOrCtrl+Shift+z").OnClick(func(ctx *Context) { + C.redo() + }) + editMenu.AddSeparator() + editMenu.Add("Cut").SetAccelerator("CmdOrCtrl+x").OnClick(func(ctx *Context) { + C.cut() + }) + editMenu.Add("Copy").SetAccelerator("CmdOrCtrl+c").OnClick(func(ctx *Context) { + C.copy() + }) + editMenu.Add("Paste").SetAccelerator("CmdOrCtrl+v").OnClick(func(ctx *Context) { + C.paste() + }) + editMenu.Add("Paste and Match Style").SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+v").OnClick(func(ctx *Context) { + C.pasteAndMatchStyle() + }) + editMenu.Add("Delete").SetAccelerator("backspace").OnClick(func(ctx *Context) { + C.delete() + }) + editMenu.Add("Select All").SetAccelerator("CmdOrCtrl+a").OnClick(func(ctx *Context) { + C.selectAll() + }) + editMenu.AddSeparator() + speechMenu := editMenu.AddSubmenu("Speech") + speechMenu.Add("Start Speaking").SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+.").OnClick(func(ctx *Context) { + C.startSpeaking() + }) + speechMenu.Add("Stop Speaking").SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+,").OnClick(func(ctx *Context) { + C.stopSpeaking() + }) + return editMenu +} + +func newHideMenuItem() *MenuItem { + return newMenuItem("Hide " + globalApplication.Name()). + SetAccelerator("CmdOrCtrl+h"). + OnClick(func(ctx *Context) { + C.hideApplication() + }) +} + +func newHideOthersMenuItem() *MenuItem { + return newMenuItem("Hide Others"). + SetAccelerator("CmdOrCtrl+OptionOrAlt+h"). + OnClick(func(ctx *Context) { + C.hideOthers() + }) +} + +func newUnhideMenuItem() *MenuItem { + return newMenuItem("Show All"). + OnClick(func(ctx *Context) { + C.showAll() + }) +} diff --git a/exp/pkg/application/roles.go b/exp/pkg/application/roles.go new file mode 100644 index 000000000..dde21b5d1 --- /dev/null +++ b/exp/pkg/application/roles.go @@ -0,0 +1,39 @@ +package application + +// Heavily inspired by Electron (c) 2013-2020 Github Inc. +// Electron License: https://github.com/electron/electron/blob/master/LICENSE + +// Role is a type to identify menu roles +type Role uint + +// These constants need to be kept in sync with `v2/internal/frontend/desktop/darwin/Role.h` +const ( + NoRole Role = 0 + AppMenu Role = 1 + EditMenu Role = 2 + ServicesMenu Role = 3 + Hide Role = 4 + HideOthers Role = 5 + UnHide Role = 6 + //AboutRole Role = "about" + //UndoRole Role = "undo" + //RedoRole Role = "redo" + //CutRole Role = "cut" + //CopyRole Role = "copy" + //PasteRole Role = "paste" + //PasteAndMatchStyleRole Role = "pasteAndMatchStyle" + //SelectAllRole Role = "selectAll" + //DeleteRole Role = "delete" + //MinimizeRole Role = "minimize" + //QuitRole Role = "quit" + //TogglefullscreenRole Role = "togglefullscreen" + //FileMenuRole Role = "fileMenu" + //ViewMenuRole Role = "viewMenu" + //WindowMenuRole Role = "windowMenu" + + //FrontRole Role = "front" + //ZoomRole Role = "zoom" + //WindowSubMenuRole Role = "windowSubMenu" + //HelpSubMenuRole Role = "helpSubMenu" + //SeparatorItemRole Role = "separatorItem" +) diff --git a/exp/pkg/application/window_devtools.go b/exp/pkg/application/window_devtools.go new file mode 100644 index 000000000..d8382dfa1 --- /dev/null +++ b/exp/pkg/application/window_devtools.go @@ -0,0 +1,43 @@ +//go:build darwin && !production + +package application + +/* +#cgo CFLAGS: -mmacosx-version-min=10.13 -x objective-c +#cgo LDFLAGS: -framework Cocoa + +#import + +#include "window_delegate.h" + +@interface _WKInspector : NSObject +- (void)show; +- (void)detach; +@end + +@interface WKWebView () +- (_WKInspector *)_inspector; +@end + +void showDevTools(void *window) { + // Get the window delegate + WindowDelegate* delegate = (WindowDelegate*)[(NSWindow*)window delegate]; + dispatch_async(dispatch_get_main_queue(), ^{ + [delegate.webView._inspector show]; + //dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC); + //dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ + // // Detach must be deferred a little bit and is ignored directly after a show. + // [delegate.webView._inspector detach]; + //}); + }); +} + +*/ +import "C" +import "unsafe" + +func init() { + showDevTools = func(window unsafe.Pointer) { + C.showDevTools(window) + } +} From 88f6a3d1b9e20f76717ee9f4d045cc4b79cd3901 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Fri, 16 Dec 2022 21:09:31 +1100 Subject: [PATCH 33/85] Refactor and support more roles --- exp/examples/menu/main.go | 10 +- exp/pkg/application/app_delegate.h | 7 +- exp/pkg/application/application.go | 12 +- exp/pkg/application/application_darwin.go | 19 +- exp/pkg/application/keys.go | 6 +- exp/pkg/application/menu.go | 2 +- exp/pkg/application/menu_darwin.go | 2 +- exp/pkg/application/menuitem.go | 67 +++++-- exp/pkg/application/menuitem_darwin.go | 228 +++++++++++++++++----- exp/pkg/application/roles.go | 96 +++++++-- exp/pkg/application/window.go | 32 +++ exp/pkg/application/window_darwin.go | 31 ++- exp/pkg/application/window_delegate.h | 3 - exp/pkg/application/window_delegate.m | 2 + 14 files changed, 421 insertions(+), 96 deletions(-) diff --git a/exp/examples/menu/main.go b/exp/examples/menu/main.go index ea106a459..1556e9a09 100644 --- a/exp/examples/menu/main.go +++ b/exp/examples/menu/main.go @@ -1,7 +1,6 @@ package main import ( - _ "embed" "log" "github.com/wailsapp/wails/exp/pkg/application" @@ -10,15 +9,12 @@ import ( func main() { app := application.New() - myMenu := app.NewMenu() - myMenu.AddRole(application.AppMenu) - myMenu.AddRole(application.EditMenu) - - app.SetMenu(myMenu) + app.NewWindow() + app.NewWindow() err := app.Run() if err != nil { - log.Fatal(err) + log.Fatal(err.Error()) } } diff --git a/exp/pkg/application/app_delegate.h b/exp/pkg/application/app_delegate.h index 0a318f4ae..db8021543 100644 --- a/exp/pkg/application/app_delegate.h +++ b/exp/pkg/application/app_delegate.h @@ -1,8 +1,13 @@ //go:build darwin +#ifndef appdelegate_h +#define appdelegate_h + #import @interface AppDelegate : NSObject @property NSApplicationActivationPolicy activationPolicy; - (void)setApplicationActivationPolicy:(NSApplicationActivationPolicy)policy; -@end \ No newline at end of file +@end + +#endif diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index 7a32653f6..27274575e 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -7,7 +7,6 @@ import ( "sync" "github.com/wailsapp/wails/exp/pkg/events" - "github.com/wailsapp/wails/exp/pkg/options" ) @@ -45,6 +44,7 @@ type platformApp interface { destroy() setApplicationMenu(menu *Menu) name() string + getCurrentWindowID() uint } // Messages sent from javascript get routed here @@ -234,6 +234,16 @@ func (a *App) handleMenuItemClicked(menuItemID uint) { menuItem.handleClick() } +func (a *App) GetCurrentWindow() *Window { + if a.impl == nil { + return nil + } + id := a.impl.getCurrentWindowID() + a.windowsLock.Lock() + defer a.windowsLock.Unlock() + return a.windows[id] +} + func (a *App) Quit() { var wg sync.WaitGroup wg.Add(2) diff --git a/exp/pkg/application/application_darwin.go b/exp/pkg/application/application_darwin.go index 61abb4736..4dd54d027 100644 --- a/exp/pkg/application/application_darwin.go +++ b/exp/pkg/application/application_darwin.go @@ -9,6 +9,7 @@ package application #include "application.h" #include "app_delegate.h" +#include "window_delegate.h" #include #import @@ -52,6 +53,14 @@ static char* getAppName(void) { return strdup([appName UTF8String]); } +// get the current window ID +static unsigned int getCurrentWindowID(void) { + NSWindow *window = [NSApp keyWindow]; + // Get the window delegate + WindowDelegate *delegate = (WindowDelegate*)[window delegate]; + return delegate.windowId; +} + */ import "C" import ( @@ -71,6 +80,10 @@ func (m *macosApp) name() string { return C.GoString(appName) } +func (m *macosApp) getCurrentWindowID() uint { + return uint(C.getCurrentWindowID()) +} + func (m *macosApp) setApplicationMenu(menu *Menu) { if menu == nil { // Create a default menu for mac @@ -94,8 +107,10 @@ func (m *macosApp) destroy() { func (m *macosApp) createDefaultApplicationMenu() *Menu { // Create a default menu for mac menu := NewMenu() - newAppMenu(menu) - newEditMenu(menu) + menu.AddRole(AppMenu) + menu.AddRole(FileMenu) + menu.AddRole(EditMenu) + menu.AddRole(ViewMenu) return menu } diff --git a/exp/pkg/application/keys.go b/exp/pkg/application/keys.go index a7d0515b0..4670e1833 100644 --- a/exp/pkg/application/keys.go +++ b/exp/pkg/application/keys.go @@ -26,10 +26,14 @@ const ( var modifierMap = map[string]modifier{ "cmdorctrl": CmdOrCtrlKey, + "cmd": CmdOrCtrlKey, + "command": CmdOrCtrlKey, + "ctrl": CmdOrCtrlKey, "optionoralt": OptionOrAltKey, + "alt": OptionOrAltKey, + "option": OptionOrAltKey, "shift": ShiftKey, "super": SuperKey, - "ctrl": ControlKey, } // accelerator holds the keyboard shortcut for a menu item diff --git a/exp/pkg/application/menu.go b/exp/pkg/application/menu.go index 8bec6f01a..20c09e239 100644 --- a/exp/pkg/application/menu.go +++ b/exp/pkg/application/menu.go @@ -53,7 +53,7 @@ func (m *Menu) AddSubmenu(s string) *Menu { } func (m *Menu) AddRole(role Role) *Menu { - result := newRole(m, role) + result := newRole(role) m.items = append(m.items, result) return m } diff --git a/exp/pkg/application/menu_darwin.go b/exp/pkg/application/menu_darwin.go index 0d25983d4..fccf85559 100644 --- a/exp/pkg/application/menu_darwin.go +++ b/exp/pkg/application/menu_darwin.go @@ -83,7 +83,7 @@ func (m *macosMenu) processMenu(parent unsafe.Pointer, menu *Menu) { switch item.itemType { case submenu: submenu := item.submenu - nsSubmenu := C.createNSMenu(C.CString(submenu.label)) + nsSubmenu := C.createNSMenu(C.CString(item.label)) m.processMenu(nsSubmenu, submenu) menuItem := newMenuItemImpl(item) item.impl = menuItem diff --git a/exp/pkg/application/menuitem.go b/exp/pkg/application/menuitem.go index 746f61139..8be6d9ea0 100644 --- a/exp/pkg/application/menuitem.go +++ b/exp/pkg/application/menuitem.go @@ -1,6 +1,7 @@ package application import ( + "os" "sync" "sync/atomic" ) @@ -107,34 +108,74 @@ func newSubMenuItem(label string) *MenuItem { return result } -func newRole(parentMenu *Menu, role Role) *MenuItem { - var roleMenu *Menu +func newRole(role Role) *MenuItem { switch role { case AppMenu: - roleMenu = newAppMenu(parentMenu) + return newAppMenu() case EditMenu: - roleMenu = newEditMenu(parentMenu) + return newEditMenu() + case FileMenu: + return newFileMenu() + case ViewMenu: + return newViewMenu() case ServicesMenu: - roleMenu = newServicesMenu() + return newServicesMenu() + case SpeechMenu: + return newSpeechMenu() case Hide: return newHideMenuItem() case HideOthers: return newHideOthersMenuItem() case UnHide: return newUnhideMenuItem() + case Undo: + return newUndoMenuItem() + case Redo: + return newRedoMenuItem() + case Cut: + return newCutMenuItem() + case Copy: + return newCopyMenuItem() + case Paste: + return newPasteMenuItem() + case PasteAndMatchStyle: + return newPasteAndMatchStyleMenuItem() + case SelectAll: + return newSelectAllMenuItem() + case Delete: + return newDeleteMenuItem() + case Quit: + return newQuitMenuItem() + case Close: + return newCloseMenuItem() + case About: + return newAboutMenuItem() + case Reload: + return newReloadMenuItem() + case ForceReload: + return newForceReloadMenuItem() + case ToggleFullscreen: + return newToggleFullscreenMenuItem() + case ToggleDevTools: + return newToggleDevToolsMenuItem() + //case ResetZoom: + // return newResetZoomMenuItem() + //case ZoomIn: + // return newZoomInMenuItem() + //case ZoomOut: + // return newZoomOutMenuItem() + + default: + println("No support for role:", role) + os.Exit(1) } - return roleMenu.items[0] + return nil } -func newServicesMenu() *Menu { +func newServicesMenu() *MenuItem { serviceMenu := newSubMenuItem("Services") serviceMenu.role = ServicesMenu - return &Menu{ - label: "Services", - items: []*MenuItem{ - serviceMenu, - }, - } + return serviceMenu } func (m *MenuItem) handleClick() { diff --git a/exp/pkg/application/menuitem_darwin.go b/exp/pkg/application/menuitem_darwin.go index 9aca135b1..d4fa46296 100644 --- a/exp/pkg/application/menuitem_darwin.go +++ b/exp/pkg/application/menuitem_darwin.go @@ -44,7 +44,6 @@ void setMenuItemLabel(void* nsMenuItem, char *label) { menuItem.title = [NSString stringWithUTF8String:label]; } - // set menu item disabled void setMenuItemDisabled(void* nsMenuItem, bool disabled) { dispatch_async(dispatch_get_main_queue(), ^{ @@ -324,9 +323,16 @@ static void showAll(void) { [[NSApplication sharedApplication] unhideAllApplications:nil]; } +// closeWindow closes the current window +static void closeWindow(void) { + [NSApp sendAction:@selector(performClose:) to:nil from:nil]; +} + + */ import "C" import ( + "runtime" "unsafe" ) @@ -385,12 +391,9 @@ func newMenuItemImpl(item *MenuItem) *macosMenuItem { return result } -func newAppMenu(menu *Menu) *Menu { - appName := globalApplication.Name() - appMenu := menu.AddSubmenu(appName) - appMenu.Add("About " + appName).OnClick(func(*Context) { - //TODO: implement - }) +func newAppMenu() *MenuItem { + appMenu := NewMenu() + appMenu.AddRole(About) appMenu.AddSeparator() appMenu.AddRole(ServicesMenu) appMenu.AddSeparator() @@ -398,49 +401,45 @@ func newAppMenu(menu *Menu) *Menu { appMenu.AddRole(HideOthers) appMenu.AddRole(UnHide) appMenu.AddSeparator() - - appMenu.Add("Quit " + appName).SetAccelerator("CmdOrCtrl+q").OnClick(func(ctx *Context) { - globalApplication.Quit() - }) - return appMenu + appMenu.AddRole(Quit) + subMenu := newSubMenuItem(globalApplication.Name()) + subMenu.submenu = appMenu + return subMenu } -func newEditMenu(menu *Menu) *Menu { - editMenu := menu.AddSubmenu("Edit") - editMenu.Add("Undo").SetAccelerator("CmdOrCtrl+z").OnClick(func(ctx *Context) { - C.undo() - }) - editMenu.Add("Redo").SetAccelerator("CmdOrCtrl+Shift+z").OnClick(func(ctx *Context) { - C.redo() - }) +func newEditMenu() *MenuItem { + editMenu := NewMenu() + editMenu.AddRole(Undo) + editMenu.AddRole(Redo) editMenu.AddSeparator() - editMenu.Add("Cut").SetAccelerator("CmdOrCtrl+x").OnClick(func(ctx *Context) { - C.cut() - }) - editMenu.Add("Copy").SetAccelerator("CmdOrCtrl+c").OnClick(func(ctx *Context) { - C.copy() - }) - editMenu.Add("Paste").SetAccelerator("CmdOrCtrl+v").OnClick(func(ctx *Context) { - C.paste() - }) - editMenu.Add("Paste and Match Style").SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+v").OnClick(func(ctx *Context) { - C.pasteAndMatchStyle() - }) - editMenu.Add("Delete").SetAccelerator("backspace").OnClick(func(ctx *Context) { - C.delete() - }) - editMenu.Add("Select All").SetAccelerator("CmdOrCtrl+a").OnClick(func(ctx *Context) { - C.selectAll() - }) + editMenu.AddRole(Cut) + editMenu.AddRole(Copy) + editMenu.AddRole(Paste) + editMenu.AddRole(PasteAndMatchStyle) + editMenu.AddRole(Delete) + editMenu.AddRole(SelectAll) editMenu.AddSeparator() - speechMenu := editMenu.AddSubmenu("Speech") - speechMenu.Add("Start Speaking").SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+.").OnClick(func(ctx *Context) { - C.startSpeaking() - }) - speechMenu.Add("Stop Speaking").SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+,").OnClick(func(ctx *Context) { - C.stopSpeaking() - }) - return editMenu + editMenu.AddRole(SpeechMenu) + subMenu := newSubMenuItem("Edit") + subMenu.submenu = editMenu + return subMenu +} + +func newSpeechMenu() *MenuItem { + speechMenu := NewMenu() + speechMenu.Add("Start Speaking"). + SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+."). + OnClick(func(ctx *Context) { + C.startSpeaking() + }) + speechMenu.Add("Stop Speaking"). + SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+,"). + OnClick(func(ctx *Context) { + C.stopSpeaking() + }) + subMenu := newSubMenuItem("Speech") + subMenu.submenu = speechMenu + return subMenu } func newHideMenuItem() *MenuItem { @@ -465,3 +464,140 @@ func newUnhideMenuItem() *MenuItem { C.showAll() }) } + +func newUndoMenuItem() *MenuItem { + return newMenuItem("Undo"). + SetAccelerator("CmdOrCtrl+z"). + OnClick(func(ctx *Context) { + C.undo() + }) +} + +// newRedoMenuItem creates a new menu item for redoing the last action +func newRedoMenuItem() *MenuItem { + return newMenuItem("Redo"). + SetAccelerator("CmdOrCtrl+Shift+z"). + OnClick(func(ctx *Context) { + C.redo() + }) +} + +func newCutMenuItem() *MenuItem { + return newMenuItem("Cut"). + SetAccelerator("CmdOrCtrl+x"). + OnClick(func(ctx *Context) { + C.cut() + }) +} + +func newCopyMenuItem() *MenuItem { + return newMenuItem("Copy"). + SetAccelerator("CmdOrCtrl+c"). + OnClick(func(ctx *Context) { + C.copy() + }) +} + +func newPasteMenuItem() *MenuItem { + return newMenuItem("Paste"). + SetAccelerator("CmdOrCtrl+v"). + OnClick(func(ctx *Context) { + C.paste() + }) +} + +func newPasteAndMatchStyleMenuItem() *MenuItem { + return newMenuItem("Paste and Match Style"). + SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+v"). + OnClick(func(ctx *Context) { + C.pasteAndMatchStyle() + }) +} + +func newDeleteMenuItem() *MenuItem { + return newMenuItem("Delete"). + SetAccelerator("backspace"). + OnClick(func(ctx *Context) { + C.delete() + }) +} + +func newQuitMenuItem() *MenuItem { + return newMenuItem("Quit " + globalApplication.Name()). + SetAccelerator("CmdOrCtrl+q"). + OnClick(func(ctx *Context) { + globalApplication.Quit() + }) +} + +func newSelectAllMenuItem() *MenuItem { + return newMenuItem("Select All"). + SetAccelerator("CmdOrCtrl+a"). + OnClick(func(ctx *Context) { + C.selectAll() + }) +} + +func newAboutMenuItem() *MenuItem { + return newMenuItem("About " + globalApplication.Name()). + OnClick(func(ctx *Context) { + // globalApplication.About() + }) +} + +func newCloseMenuItem() *MenuItem { + return newMenuItem("Close"). + SetAccelerator("CmdOrCtrl+w"). + OnClick(func(ctx *Context) { + C.closeWindow() + }) +} + +func newReloadMenuItem() *MenuItem { + return newMenuItem("Reload"). + SetAccelerator("CmdOrCtrl+r"). + OnClick(func(ctx *Context) { + currentWindow := globalApplication.GetCurrentWindow() + if currentWindow != nil { + currentWindow.Reload() + } + }) +} + +func newForceReloadMenuItem() *MenuItem { + return newMenuItem("Force Reload"). + SetAccelerator("CmdOrCtrl+Shift+r"). + OnClick(func(ctx *Context) { + currentWindow := globalApplication.GetCurrentWindow() + if currentWindow != nil { + currentWindow.ForceReload() + } + }) +} + +func newToggleFullscreenMenuItem() *MenuItem { + result := newMenuItem("Toggle Full Screen"). + OnClick(func(ctx *Context) { + currentWindow := globalApplication.GetCurrentWindow() + if currentWindow != nil { + currentWindow.ToggleFullscreen() + } + }) + if runtime.GOOS == "darwin" { + result.SetAccelerator("Ctrl+Command+F") + } else { + result.SetAccelerator("F11") + } + return result +} + +func newToggleDevToolsMenuItem() *MenuItem { + return newMenuItem("Toggle Developer Tools"). + SetAccelerator("Alt+Command+I"). + OnClick(func(ctx *Context) { + currentWindow := globalApplication.GetCurrentWindow() + if currentWindow != nil { + currentWindow.ToggleDevTools() + } + }) +} diff --git a/exp/pkg/application/roles.go b/exp/pkg/application/roles.go index dde21b5d1..03ee7c958 100644 --- a/exp/pkg/application/roles.go +++ b/exp/pkg/application/roles.go @@ -1,5 +1,7 @@ package application +import "runtime" + // Heavily inspired by Electron (c) 2013-2020 Github Inc. // Electron License: https://github.com/electron/electron/blob/master/LICENSE @@ -8,26 +10,38 @@ type Role uint // These constants need to be kept in sync with `v2/internal/frontend/desktop/darwin/Role.h` const ( - NoRole Role = 0 - AppMenu Role = 1 - EditMenu Role = 2 - ServicesMenu Role = 3 - Hide Role = 4 - HideOthers Role = 5 - UnHide Role = 6 - //AboutRole Role = "about" - //UndoRole Role = "undo" - //RedoRole Role = "redo" - //CutRole Role = "cut" - //CopyRole Role = "copy" - //PasteRole Role = "paste" - //PasteAndMatchStyleRole Role = "pasteAndMatchStyle" - //SelectAllRole Role = "selectAll" - //DeleteRole Role = "delete" - //MinimizeRole Role = "minimize" - //QuitRole Role = "quit" + NoRole Role = iota + AppMenu Role = iota + EditMenu Role = iota + ViewMenu Role = iota + ServicesMenu Role = iota + Hide Role = iota + HideOthers Role = iota + UnHide Role = iota + About Role = iota + Undo Role = iota + Redo Role = iota + Cut Role = iota + Copy Role = iota + Paste Role = iota + PasteAndMatchStyle Role = iota + SelectAll Role = iota + Delete Role = iota + SpeechMenu Role = iota + Quit Role = iota + FileMenu Role = iota + Close Role = iota + Reload Role = iota + ForceReload Role = iota + ToggleDevTools Role = iota + ResetZoom Role = iota + ZoomIn Role = iota + ZoomOut Role = iota + ToggleFullscreen Role = iota + + //MinimizeRole Role = + //QuitRole Role = //TogglefullscreenRole Role = "togglefullscreen" - //FileMenuRole Role = "fileMenu" //ViewMenuRole Role = "viewMenu" //WindowMenuRole Role = "windowMenu" @@ -37,3 +51,47 @@ const ( //HelpSubMenuRole Role = "helpSubMenu" //SeparatorItemRole Role = "separatorItem" ) + +func newFileMenu() *MenuItem { + fileMenu := NewMenu() + if runtime.GOOS == "darwin" { + fileMenu.AddRole(Close) + } else { + fileMenu.AddRole(Quit) + } + subMenu := newSubMenuItem("File") + subMenu.submenu = fileMenu + return subMenu +} + +/* + { + label: 'View', + submenu: [ + { role: 'reload' }, + { role: 'forceReload' }, + { role: 'toggleDevTools' }, + { type: 'separator' }, + { role: 'resetZoom' }, + { role: 'zoomIn' }, + { role: 'zoomOut' }, + { type: 'separator' }, + { role: 'togglefullscreen' } + ] + }, +*/ +func newViewMenu() *MenuItem { + viewMenu := NewMenu() + viewMenu.AddRole(Reload) + viewMenu.AddRole(ForceReload) + viewMenu.AddRole(ToggleDevTools) + viewMenu.AddSeparator() + //viewMenu.AddRole(ResetZoom) + //viewMenu.AddRole(ZoomIn) + //viewMenu.AddRole(ZoomOut) + viewMenu.AddSeparator() + viewMenu.AddRole(ToggleFullscreen) + subMenu := newSubMenuItem("View") + subMenu.submenu = viewMenu + return subMenu +} diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index 944739d33..9280e312f 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -33,6 +33,10 @@ type windowImpl interface { height() int position() (int, int) destroy() + reload() + forceReload() + toggleFullscreen() + toggleDevTools() } type Window struct { @@ -291,3 +295,31 @@ func (w *Window) Destroy() { } w.impl.destroy() } + +func (w *Window) Reload() { + if w.impl == nil { + return + } + w.impl.reload() +} + +func (w *Window) ForceReload() { + if w.impl == nil { + return + } + w.impl.forceReload() +} + +func (w *Window) ToggleFullscreen() { + if w.impl == nil { + return + } + w.impl.toggleFullscreen() +} + +func (w *Window) ToggleDevTools() { + if w.impl == nil { + return + } + w.impl.toggleDevTools() +} diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index ba66210e6..aaa7e874f 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -248,6 +248,14 @@ void windowSetMaximised(void* nsWindow) { }); } +// toggle fullscreen +void windowToggleFullscreen(void* nsWindow) { + // Toggle fullscreen on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + [(NSWindow*)nsWindow toggleFullScreen:nil]; + }); +} + // Set Window fullscreen void windowSetFullscreen(void* nsWindow) { // Set window fullscreen on main thread @@ -462,7 +470,6 @@ void windowDestroy(void* nsWindow) { }); } - */ import "C" import ( @@ -472,10 +479,32 @@ import ( "github.com/wailsapp/wails/exp/pkg/options" ) +var showDevTools = func(window unsafe.Pointer) {} + type macosWindow struct { id uint nsWindow unsafe.Pointer options *options.Window + + // devtools +} + +func (w *macosWindow) toggleDevTools() { + showDevTools(w.nsWindow) +} + +func (w *macosWindow) toggleFullscreen() { + C.windowToggleFullscreen(w.nsWindow) +} + +func (w *macosWindow) reload() { + //TODO: Implement + println("reload called on Window", w.id) +} + +func (w *macosWindow) forceReload() { + //TODO: Implement + println("forceReload called on Window", w.id) } func (w *macosWindow) center() { diff --git a/exp/pkg/application/window_delegate.h b/exp/pkg/application/window_delegate.h index f6e91c15c..c0446abee 100644 --- a/exp/pkg/application/window_delegate.h +++ b/exp/pkg/application/window_delegate.h @@ -1,14 +1,11 @@ //go:build darwin - #ifndef WindowDelegate_h #define WindowDelegate_h #import #import -extern void processMessage(unsigned int, const char*); - @interface WindowDelegate : NSObject @property bool hideOnClose; diff --git a/exp/pkg/application/window_delegate.m b/exp/pkg/application/window_delegate.m index a602500fc..5a5488c4d 100644 --- a/exp/pkg/application/window_delegate.m +++ b/exp/pkg/application/window_delegate.m @@ -11,6 +11,8 @@ #import "window_delegate.h" #import "../events/events.h" +extern void processMessage(unsigned int, const char*); + @implementation WindowDelegate - (BOOL)windowShouldClose:(NSWindow *)sender { if( self.hideOnClose ) { From da5fa806d7386b1c1d3ded8f798daa5c5143ceb2 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Fri, 16 Dec 2022 21:28:16 +1100 Subject: [PATCH 34/85] Add Zoom In/Out & Actual size roles --- exp/pkg/application/menuitem.go | 12 +++---- exp/pkg/application/menuitem_darwin.go | 34 ++++++++++++++++++ exp/pkg/application/roles.go | 6 ++-- exp/pkg/application/window.go | 24 +++++++++++++ exp/pkg/application/window_darwin.go | 49 ++++++++++++++++++++++++++ 5 files changed, 116 insertions(+), 9 deletions(-) diff --git a/exp/pkg/application/menuitem.go b/exp/pkg/application/menuitem.go index 8be6d9ea0..0fe6409a7 100644 --- a/exp/pkg/application/menuitem.go +++ b/exp/pkg/application/menuitem.go @@ -158,12 +158,12 @@ func newRole(role Role) *MenuItem { return newToggleFullscreenMenuItem() case ToggleDevTools: return newToggleDevToolsMenuItem() - //case ResetZoom: - // return newResetZoomMenuItem() - //case ZoomIn: - // return newZoomInMenuItem() - //case ZoomOut: - // return newZoomOutMenuItem() + case ResetZoom: + return newResetZoomMenuItem() + case ZoomIn: + return newZoomInMenuItem() + case ZoomOut: + return newZoomOutMenuItem() default: println("No support for role:", role) diff --git a/exp/pkg/application/menuitem_darwin.go b/exp/pkg/application/menuitem_darwin.go index d4fa46296..b554da718 100644 --- a/exp/pkg/application/menuitem_darwin.go +++ b/exp/pkg/application/menuitem_darwin.go @@ -601,3 +601,37 @@ func newToggleDevToolsMenuItem() *MenuItem { } }) } + +func newResetZoomMenuItem() *MenuItem { + // reset zoom menu item + return newMenuItem("Actual Size"). + SetAccelerator("CmdOrCtrl+0"). + OnClick(func(ctx *Context) { + currentWindow := globalApplication.GetCurrentWindow() + if currentWindow != nil { + currentWindow.ResetZoom() + } + }) +} + +func newZoomInMenuItem() *MenuItem { + return newMenuItem("Zoom In"). + SetAccelerator("CmdOrCtrl+plus"). + OnClick(func(ctx *Context) { + currentWindow := globalApplication.GetCurrentWindow() + if currentWindow != nil { + currentWindow.ZoomIn() + } + }) +} + +func newZoomOutMenuItem() *MenuItem { + return newMenuItem("Zoom Out"). + SetAccelerator("CmdOrCtrl+-"). + OnClick(func(ctx *Context) { + currentWindow := globalApplication.GetCurrentWindow() + if currentWindow != nil { + currentWindow.ZoomOut() + } + }) +} diff --git a/exp/pkg/application/roles.go b/exp/pkg/application/roles.go index 03ee7c958..c36a8c45d 100644 --- a/exp/pkg/application/roles.go +++ b/exp/pkg/application/roles.go @@ -86,9 +86,9 @@ func newViewMenu() *MenuItem { viewMenu.AddRole(ForceReload) viewMenu.AddRole(ToggleDevTools) viewMenu.AddSeparator() - //viewMenu.AddRole(ResetZoom) - //viewMenu.AddRole(ZoomIn) - //viewMenu.AddRole(ZoomOut) + viewMenu.AddRole(ResetZoom) + viewMenu.AddRole(ZoomIn) + viewMenu.AddRole(ZoomOut) viewMenu.AddSeparator() viewMenu.AddRole(ToggleFullscreen) subMenu := newSubMenuItem("View") diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index 9280e312f..169c18892 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -37,6 +37,9 @@ type windowImpl interface { forceReload() toggleFullscreen() toggleDevTools() + resetZoom() + zoomIn() + zoomOut() } type Window struct { @@ -323,3 +326,24 @@ func (w *Window) ToggleDevTools() { } w.impl.toggleDevTools() } + +func (w *Window) ResetZoom() { + if w.impl == nil { + return + } + w.impl.resetZoom() +} + +func (w *Window) ZoomIn() { + if w.impl == nil { + return + } + w.impl.zoomIn() +} + +func (w *Window) ZoomOut() { + if w.impl == nil { + return + } + w.impl.zoomOut() +} diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index aaa7e874f..bf33fcf2b 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -184,6 +184,43 @@ void windowEnableDevTools(void* nsWindow) { }); } +// windowResetZoom +void windowResetZoom(void* nsWindow) { + // Reset zoom on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + // Get window delegate + WindowDelegate* delegate = (WindowDelegate*)[(NSWindow*)nsWindow delegate]; + // Reset zoom + [delegate.webView setMagnification:1.0]; + }); +} + +// windowZoomIn +void windowZoomIn(void* nsWindow) { + // Zoom in on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + // Get window delegate + WindowDelegate* delegate = (WindowDelegate*)[(NSWindow*)nsWindow delegate]; + // Zoom in + [delegate.webView setMagnification:delegate.webView.magnification + 0.05]; + }); +} + +// windowZoomOut +void windowZoomOut(void* nsWindow) { + // Zoom out on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + // Get window delegate + WindowDelegate* delegate = (WindowDelegate*)[(NSWindow*)nsWindow delegate]; + // Zoom out + if( delegate.webView.magnification > 1.05 ) { + [delegate.webView setMagnification:delegate.webView.magnification - 0.05]; + } else { + [delegate.webView setMagnification:1.0]; + } + }); +} + // Execute JS in NSWindow void windowExecJS(void* nsWindow, char* js) { // Execute JS on main thread @@ -489,6 +526,18 @@ type macosWindow struct { // devtools } +func (w *macosWindow) zoomIn() { + C.windowZoomIn(w.nsWindow) +} + +func (w *macosWindow) zoomOut() { + C.windowZoomOut(w.nsWindow) +} + +func (w *macosWindow) resetZoom() { + C.windowResetZoom(w.nsWindow) +} + func (w *macosWindow) toggleDevTools() { showDevTools(w.nsWindow) } From f8eb680559243c9596cd28485dd9ccd679fcb16b Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sat, 17 Dec 2022 19:56:29 +1100 Subject: [PATCH 35/85] Add Window & Help menus Fix min/max sizing --- exp/examples/window/main.go | 13 +++- exp/pkg/application/application_darwin.go | 13 +--- exp/pkg/application/menu.go | 11 +++ exp/pkg/application/menuitem.go | 8 ++ exp/pkg/application/menuitem_darwin.go | 66 ++++++---------- exp/pkg/application/roles.go | 95 +++++++++++++++++------ exp/pkg/application/window.go | 24 ++++++ exp/pkg/application/window_darwin.go | 62 ++++++++++++++- exp/pkg/options/mac.go | 50 +++++------- 9 files changed, 233 insertions(+), 109 deletions(-) diff --git a/exp/examples/window/main.go b/exp/examples/window/main.go index f5f4b52a7..bd0ebdced 100644 --- a/exp/examples/window/main.go +++ b/exp/examples/window/main.go @@ -4,6 +4,8 @@ import ( _ "embed" "log" + "github.com/wailsapp/wails/exp/pkg/options" + "github.com/wailsapp/wails/exp/pkg/events" "github.com/wailsapp/wails/exp/pkg/application" @@ -13,7 +15,16 @@ func main() { app := application.New() // Create window - myWindow := app.NewWindow() + myWindow := app.NewWindowWithOptions(&options.Window{ + Title: "My Window", + Width: 800, + Height: 600, + URL: "https://www.google.com", + Mac: &options.MacWindow{ + //Backdrop: options.MacBackdropTranslucent, + TitleBar: options.TitleBarHiddenInset, + }, + }) myWindow.On(events.Mac.WindowDidBecomeMain, func() { println("Window did become main") }) diff --git a/exp/pkg/application/application_darwin.go b/exp/pkg/application/application_darwin.go index 4dd54d027..d749dc327 100644 --- a/exp/pkg/application/application_darwin.go +++ b/exp/pkg/application/application_darwin.go @@ -87,7 +87,7 @@ func (m *macosApp) getCurrentWindowID() uint { func (m *macosApp) setApplicationMenu(menu *Menu) { if menu == nil { // Create a default menu for mac - menu = m.createDefaultApplicationMenu() + menu = defaultApplicationMenu() } menu.Update() // Convert impl to macosMenu object @@ -104,17 +104,6 @@ func (m *macosApp) destroy() { C.destroyApp() } -func (m *macosApp) createDefaultApplicationMenu() *Menu { - // Create a default menu for mac - menu := NewMenu() - menu.AddRole(AppMenu) - menu.AddRole(FileMenu) - menu.AddRole(EditMenu) - menu.AddRole(ViewMenu) - - return menu -} - func newPlatformApp(appOptions *options.Application) *macosApp { if appOptions == nil { appOptions = options.ApplicationDefaults diff --git a/exp/pkg/application/menu.go b/exp/pkg/application/menu.go index 20c09e239..fe90be88b 100644 --- a/exp/pkg/application/menu.go +++ b/exp/pkg/application/menu.go @@ -86,3 +86,14 @@ func (m *Menu) SetLabel(label string) { func (a *App) NewMenu() *Menu { return &Menu{} } + +func defaultApplicationMenu() *Menu { + menu := NewMenu() + menu.AddRole(AppMenu) + menu.AddRole(FileMenu) + menu.AddRole(EditMenu) + menu.AddRole(ViewMenu) + menu.AddRole(WindowMenu) + menu.AddRole(HelpMenu) + return menu +} diff --git a/exp/pkg/application/menuitem.go b/exp/pkg/application/menuitem.go index 0fe6409a7..5c4945953 100644 --- a/exp/pkg/application/menuitem.go +++ b/exp/pkg/application/menuitem.go @@ -122,6 +122,10 @@ func newRole(role Role) *MenuItem { return newServicesMenu() case SpeechMenu: return newSpeechMenu() + case WindowMenu: + return newWindowMenu() + case HelpMenu: + return newHelpMenu() case Hide: return newHideMenuItem() case HideOthers: @@ -164,6 +168,10 @@ func newRole(role Role) *MenuItem { return newZoomInMenuItem() case ZoomOut: return newZoomOutMenuItem() + case Minimize: + return newMinimizeMenuItem() + case Zoom: + return newZoomMenuItem() default: println("No support for role:", role) diff --git a/exp/pkg/application/menuitem_darwin.go b/exp/pkg/application/menuitem_darwin.go index b554da718..b26d9e7aa 100644 --- a/exp/pkg/application/menuitem_darwin.go +++ b/exp/pkg/application/menuitem_darwin.go @@ -323,12 +323,6 @@ static void showAll(void) { [[NSApplication sharedApplication] unhideAllApplications:nil]; } -// closeWindow closes the current window -static void closeWindow(void) { - [NSApp sendAction:@selector(performClose:) to:nil from:nil]; -} - - */ import "C" import ( @@ -391,40 +385,6 @@ func newMenuItemImpl(item *MenuItem) *macosMenuItem { return result } -func newAppMenu() *MenuItem { - appMenu := NewMenu() - appMenu.AddRole(About) - appMenu.AddSeparator() - appMenu.AddRole(ServicesMenu) - appMenu.AddSeparator() - appMenu.AddRole(Hide) - appMenu.AddRole(HideOthers) - appMenu.AddRole(UnHide) - appMenu.AddSeparator() - appMenu.AddRole(Quit) - subMenu := newSubMenuItem(globalApplication.Name()) - subMenu.submenu = appMenu - return subMenu -} - -func newEditMenu() *MenuItem { - editMenu := NewMenu() - editMenu.AddRole(Undo) - editMenu.AddRole(Redo) - editMenu.AddSeparator() - editMenu.AddRole(Cut) - editMenu.AddRole(Copy) - editMenu.AddRole(Paste) - editMenu.AddRole(PasteAndMatchStyle) - editMenu.AddRole(Delete) - editMenu.AddRole(SelectAll) - editMenu.AddSeparator() - editMenu.AddRole(SpeechMenu) - subMenu := newSubMenuItem("Edit") - subMenu.submenu = editMenu - return subMenu -} - func newSpeechMenu() *MenuItem { speechMenu := NewMenu() speechMenu.Add("Start Speaking"). @@ -549,7 +509,10 @@ func newCloseMenuItem() *MenuItem { return newMenuItem("Close"). SetAccelerator("CmdOrCtrl+w"). OnClick(func(ctx *Context) { - C.closeWindow() + currentWindow := globalApplication.GetCurrentWindow() + if currentWindow != nil { + currentWindow.Close() + } }) } @@ -635,3 +598,24 @@ func newZoomOutMenuItem() *MenuItem { } }) } + +func newMinimizeMenuItem() *MenuItem { + return newMenuItem("Minimize"). + SetAccelerator("CmdOrCtrl+M"). + OnClick(func(ctx *Context) { + currentWindow := globalApplication.GetCurrentWindow() + if currentWindow != nil { + currentWindow.Minimize() + } + }) +} + +func newZoomMenuItem() *MenuItem { + return newMenuItem("Zoom"). + OnClick(func(ctx *Context) { + currentWindow := globalApplication.GetCurrentWindow() + if currentWindow != nil { + currentWindow.Zoom() + } + }) +} diff --git a/exp/pkg/application/roles.go b/exp/pkg/application/roles.go index c36a8c45d..00f32148d 100644 --- a/exp/pkg/application/roles.go +++ b/exp/pkg/application/roles.go @@ -10,11 +10,14 @@ type Role uint // These constants need to be kept in sync with `v2/internal/frontend/desktop/darwin/Role.h` const ( - NoRole Role = iota - AppMenu Role = iota - EditMenu Role = iota - ViewMenu Role = iota - ServicesMenu Role = iota + NoRole Role = iota + AppMenu Role = iota + EditMenu Role = iota + ViewMenu Role = iota + WindowMenu Role = iota + ServicesMenu Role = iota + HelpMenu Role = iota + Hide Role = iota HideOthers Role = iota UnHide Role = iota @@ -39,7 +42,11 @@ const ( ZoomOut Role = iota ToggleFullscreen Role = iota - //MinimizeRole Role = + Minimize Role = iota + Zoom Role = iota + //Front Role = iota + //WindowRole Role = iota + //QuitRole Role = //TogglefullscreenRole Role = "togglefullscreen" //ViewMenuRole Role = "viewMenu" @@ -64,22 +71,6 @@ func newFileMenu() *MenuItem { return subMenu } -/* - { - label: 'View', - submenu: [ - { role: 'reload' }, - { role: 'forceReload' }, - { role: 'toggleDevTools' }, - { type: 'separator' }, - { role: 'resetZoom' }, - { role: 'zoomIn' }, - { role: 'zoomOut' }, - { type: 'separator' }, - { role: 'togglefullscreen' } - ] - }, -*/ func newViewMenu() *MenuItem { viewMenu := NewMenu() viewMenu.AddRole(Reload) @@ -95,3 +86,63 @@ func newViewMenu() *MenuItem { subMenu.submenu = viewMenu return subMenu } + +func newAppMenu() *MenuItem { + appMenu := NewMenu() + appMenu.AddRole(About) + appMenu.AddSeparator() + appMenu.AddRole(ServicesMenu) + appMenu.AddSeparator() + appMenu.AddRole(Hide) + appMenu.AddRole(HideOthers) + appMenu.AddRole(UnHide) + appMenu.AddSeparator() + appMenu.AddRole(Quit) + subMenu := newSubMenuItem(globalApplication.Name()) + subMenu.submenu = appMenu + return subMenu +} + +func newEditMenu() *MenuItem { + editMenu := NewMenu() + editMenu.AddRole(Undo) + editMenu.AddRole(Redo) + editMenu.AddSeparator() + editMenu.AddRole(Cut) + editMenu.AddRole(Copy) + editMenu.AddRole(Paste) + if runtime.GOOS == "darwin" { + editMenu.AddRole(PasteAndMatchStyle) + editMenu.AddRole(PasteAndMatchStyle) + editMenu.AddRole(Delete) + editMenu.AddRole(SelectAll) + editMenu.AddSeparator() + editMenu.AddRole(SpeechMenu) + } else { + editMenu.AddRole(Delete) + editMenu.AddSeparator() + editMenu.AddRole(SelectAll) + } + subMenu := newSubMenuItem("Edit") + subMenu.submenu = editMenu + return subMenu +} + +func newWindowMenu() *MenuItem { + menu := NewMenu() + menu.AddRole(Minimize) + menu.AddRole(Zoom) + subMenu := newSubMenuItem("Window") + subMenu.submenu = menu + return subMenu +} + +func newHelpMenu() *MenuItem { + menu := NewMenu() + menu.Add("Learn More").OnClick(func(ctx *Context) { + globalApplication.GetCurrentWindow().NavigateToURL("https://wails.io") + }) + subMenu := newSubMenuItem("Help") + subMenu.submenu = menu + return subMenu +} diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index 169c18892..64eb952b3 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -40,6 +40,9 @@ type windowImpl interface { resetZoom() zoomIn() zoomOut() + close() + zoom() + minimize() } type Window struct { @@ -347,3 +350,24 @@ func (w *Window) ZoomOut() { } w.impl.zoomOut() } + +func (w *Window) Close() { + if w.impl == nil { + return + } + w.impl.close() +} + +func (w *Window) Minimize() { + if w.impl == nil { + return + } + w.impl.minimize() +} + +func (w *Window) Zoom() { + if w.impl == nil { + return + } + w.impl.zoom() +} diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index bf33fcf2b..a039cf15f 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -44,9 +44,11 @@ void* windowNew(unsigned int id, int width, int height) { WKWebView* webView = [[WKWebView alloc] initWithFrame:frame configuration:config]; [view addSubview:webView]; + + // Ensure webview resizes with the window + [webView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + delegate.webView = webView; - - delegate.hideOnClose = false; return window; } @@ -507,6 +509,38 @@ void windowDestroy(void* nsWindow) { }); } + +// windowClose closes the current window +static void windowClose(void *window) { + dispatch_async(dispatch_get_main_queue(), ^{ + // close window + [(NSWindow*)window close]; + }); +} + +// windowZoom +static void windowZoom(void *window) { + dispatch_async(dispatch_get_main_queue(), ^{ + // zoom window + [(NSWindow*)window zoom:nil]; + }); +} + +// miniaturize +static void windowMiniaturize(void *window) { + dispatch_async(dispatch_get_main_queue(), ^{ + // miniaturize window + [(NSWindow*)window miniaturize:nil]; + }); +} + +// zoom maximizes the window to the screen dimensions +static void windowMaximize(void *window) { + dispatch_async(dispatch_get_main_queue(), ^{ + // maximize window + [(NSWindow*)window zoom:nil]; + }); +} */ import "C" import ( @@ -526,6 +560,22 @@ type macosWindow struct { // devtools } +func (w *macosWindow) zoom() { + C.windowZoom(w.nsWindow) +} + +func (w *macosWindow) minimize() { + C.windowMiniaturize(w.nsWindow) +} + +func (w *macosWindow) windowZoom() { + C.windowZoom(w.nsWindow) +} + +func (w *macosWindow) close() { + C.windowClose(w.nsWindow) +} + func (w *macosWindow) zoomIn() { C.windowZoomIn(w.nsWindow) } @@ -695,8 +745,12 @@ func (w *macosWindow) run() { w.setTitle(w.options.Title) w.setAlwaysOnTop(w.options.AlwaysOnTop) w.setResizable(!w.options.DisableResize) - w.setMinSize(w.options.MinWidth, w.options.MinHeight) - w.setMaxSize(w.options.MaxWidth, w.options.MaxHeight) + if w.options.MinWidth != 0 || w.options.MinHeight != 0 { + w.setMinSize(w.options.MinWidth, w.options.MinHeight) + } + if w.options.MaxWidth != 0 || w.options.MaxHeight != 0 { + w.setMaxSize(w.options.MaxWidth, w.options.MaxHeight) + } if w.options.EnableDevTools { w.enableDevTools() } diff --git a/exp/pkg/options/mac.go b/exp/pkg/options/mac.go index 40730bc7e..01a6c9d27 100644 --- a/exp/pkg/options/mac.go +++ b/exp/pkg/options/mac.go @@ -40,15 +40,13 @@ type TitleBar struct { } // TitleBarDefault results in the default Mac Titlebar -func TitleBarDefault() *TitleBar { - return &TitleBar{ - AppearsTransparent: false, - Hide: false, - HideTitle: false, - FullSizeContent: false, - UseToolbar: false, - HideToolbarSeparator: false, - } +var TitleBarDefault = &TitleBar{ + AppearsTransparent: false, + Hide: false, + HideTitle: false, + FullSizeContent: false, + UseToolbar: false, + HideToolbarSeparator: false, } // Credit: Comments from Electron site @@ -56,30 +54,24 @@ func TitleBarDefault() *TitleBar { // TitleBarHidden results in a hidden title bar and a full size content window, // yet the title bar still has the standard window controls (“traffic lights”) // in the top left. -func TitleBarHidden() *TitleBar { - return &TitleBar{ - AppearsTransparent: true, - Hide: false, - HideTitle: true, - FullSizeContent: true, - UseToolbar: false, - HideToolbarSeparator: false, - } +var TitleBarHidden = &TitleBar{ + AppearsTransparent: true, + Hide: false, + HideTitle: true, + FullSizeContent: true, + UseToolbar: false, + HideToolbarSeparator: false, } // TitleBarHiddenInset results in a hidden title bar with an alternative look where // the traffic light buttons are slightly more inset from the window edge. -func TitleBarHiddenInset() *TitleBar { - - return &TitleBar{ - AppearsTransparent: true, - Hide: false, - HideTitle: true, - FullSizeContent: true, - UseToolbar: true, - HideToolbarSeparator: true, - } - +var TitleBarHiddenInset = &TitleBar{ + AppearsTransparent: true, + Hide: false, + HideTitle: true, + FullSizeContent: true, + UseToolbar: true, + HideToolbarSeparator: true, } // MacAppearanceType is a type of Appearance for Cocoa windows From bbb418f98f6c820659be59e39242bc2a3dac0edf Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sat, 17 Dec 2022 20:49:04 +1100 Subject: [PATCH 36/85] Fix submenu radio processing --- exp/pkg/application/menu.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/exp/pkg/application/menu.go b/exp/pkg/application/menu.go index fe90be88b..5d56c3584 100644 --- a/exp/pkg/application/menu.go +++ b/exp/pkg/application/menu.go @@ -61,6 +61,10 @@ func (m *Menu) AddRole(role Role) *Menu { func (m *Menu) processRadioGroups() { var radioGroup []*MenuItem for _, item := range m.items { + if item.itemType == submenu { + item.submenu.processRadioGroups() + continue + } if item.itemType == radio { radioGroup = append(radioGroup, item) } else { From a8d5f185c28fd67412b809e15513217b8e852454 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sat, 17 Dec 2022 20:49:46 +1100 Subject: [PATCH 37/85] Fix resizing bug Refactor some application setters --- exp/pkg/application/window.go | 14 +++++++++----- exp/pkg/application/window_darwin.go | 7 ++++++- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index 64eb952b3..250767f58 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -116,13 +116,17 @@ func (w *Window) NavigateToURL(s string) { } func (w *Window) SetResizable(b bool) { + w.options.DisableResize = !b if w.impl == nil { - w.options.DisableResize = !b return } w.impl.setResizable(b) } +func (w *Window) Resizable() bool { + return !w.options.DisableResize +} + func (w *Window) SetMinSize(minWidth, minHeight int) { if w.impl == nil { w.options.MinWidth = minWidth @@ -171,8 +175,8 @@ func (w *Window) ExecJS(js string) { // Set Maximized func (w *Window) SetMaximized() { + w.options.StartState = options.WindowStateMaximised if w.impl == nil { - w.options.StartState = options.WindowStateMaximised return } w.impl.setMaximised() @@ -180,8 +184,8 @@ func (w *Window) SetMaximized() { // Set Minimized func (w *Window) SetMinimized() { + w.options.StartState = options.WindowStateMinimised if w.impl == nil { - w.options.StartState = options.WindowStateMinimised return } w.impl.setMinimised() @@ -189,8 +193,8 @@ func (w *Window) SetMinimized() { // Set Fullscreen func (w *Window) SetFullscreen() { + w.options.StartState = options.WindowStateFullscreen if w.impl == nil { - w.options.StartState = options.WindowStateFullscreen return } w.impl.setFullscreen() @@ -231,8 +235,8 @@ func (w *Window) IsFullscreen() bool { } func (w *Window) SetBackgroundColor(color *options.RGBA) { + w.options.BackgroundColour = color if w.impl == nil { - w.options.BackgroundColour = color return } w.impl.setBackgroundColor(color) diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index a039cf15f..595f813f7 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -140,7 +140,12 @@ void navigationLoadURL(void* nsWindow, char* url) { void windowSetResizable(void* nsWindow, bool resizable) { // Set window resizable on main thread dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)nsWindow setStyleMask:resizable ? NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable : NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable]; + NSWindow* window = (NSWindow*)nsWindow; + if (resizable) { + [window setStyleMask:[window styleMask] | NSWindowStyleMaskResizable]; + } else { + [window setStyleMask:[window styleMask] & ~NSWindowStyleMaskResizable]; + } }); } From 8f9eeb8055a7e41419142a94143902d02875e28b Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sat, 17 Dec 2022 20:49:58 +1100 Subject: [PATCH 38/85] Improve menu demo --- exp/examples/menu/main.go | 69 ++++++++++++++++++++++++++++++++++++- exp/examples/window/main.go | 11 +++--- 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/exp/examples/menu/main.go b/exp/examples/menu/main.go index 1556e9a09..de8be8f3a 100644 --- a/exp/examples/menu/main.go +++ b/exp/examples/menu/main.go @@ -9,7 +9,74 @@ import ( func main() { app := application.New() - app.NewWindow() + // Create a custom menu + menu := app.NewMenu() + menu.AddRole(application.AppMenu) + + // Let's make a "Demo" menu + myMenu := menu.AddSubmenu("Demo") + + // Disabled menu item + myMenu.Add("Not Enabled").SetEnabled(false) + + // Click callbacks + myMenu.Add("Click Me!").OnClick(func(ctx *application.Context) { + ctx.ClickedMenuItem().SetLabel("Thanks mate!") + }) + + // You can control the current window from the menu + myMenu.Add("Lock Window Resize").OnClick(func(ctx *application.Context) { + if app.GetCurrentWindow().Resizable() { + app.GetCurrentWindow().SetResizable(false) + ctx.ClickedMenuItem().SetLabel("Unlock Window Resize") + } else { + app.GetCurrentWindow().SetResizable(true) + ctx.ClickedMenuItem().SetLabel("Lock Window Resize") + } + }) + + myMenu.AddSeparator() + + // Checkboxes will tell you their new state so you don't need to track it + myMenu.AddCheckbox("My checkbox", true).OnClick(func(context *application.Context) { + println("Clicked checkbox. Checked:", context.ClickedMenuItem().Checked()) + }) + myMenu.AddSeparator() + + // Callbacks can be shared. This is useful for radio groups + radioCallback := func(ctx *application.Context) { + menuItem := ctx.ClickedMenuItem() + menuItem.SetLabel(menuItem.Label() + "!") + } + + // Radio groups are created implicitly by placing radio items next to each other in a menu + myMenu.AddRadio("Radio 1", true).OnClick(radioCallback) + myMenu.AddRadio("Radio 2", false).OnClick(radioCallback) + myMenu.AddRadio("Radio 3", false).OnClick(radioCallback) + + // Submenus are also supported + submenu := myMenu.AddSubmenu("Submenu") + submenu.Add("Submenu item 1") + submenu.Add("Submenu item 2") + submenu.Add("Submenu item 3") + + myMenu.AddSeparator() + + beatles := myMenu.Add("Hello").OnClick(func(*application.Context) { + println("The beatles would be proud") + }) + myMenu.Add("Toggle the menuitem above").OnClick(func(*application.Context) { + if beatles.Enabled() { + beatles.SetEnabled(false) + beatles.SetLabel("Goodbye") + } else { + beatles.SetEnabled(true) + beatles.SetLabel("Hello") + } + }) + + app.SetMenu(menu) + app.NewWindow() err := app.Run() diff --git a/exp/examples/window/main.go b/exp/examples/window/main.go index bd0ebdced..3ddaf6ebc 100644 --- a/exp/examples/window/main.go +++ b/exp/examples/window/main.go @@ -16,12 +16,13 @@ func main() { // Create window myWindow := app.NewWindowWithOptions(&options.Window{ - Title: "My Window", - Width: 800, - Height: 600, - URL: "https://www.google.com", + Title: "My Window", + Width: 800, + Height: 600, + URL: "https://wails.io", + EnableDevTools: true, Mac: &options.MacWindow{ - //Backdrop: options.MacBackdropTranslucent, + Backdrop: options.MacBackdropTranslucent, TitleBar: options.TitleBarHiddenInset, }, }) From 2409984aabec442437b2368954dcc735805d8830 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 18 Dec 2022 00:40:53 +1100 Subject: [PATCH 39/85] Add application about dialog Add application icon support --- exp/examples/menu/icon.png | Bin 0 -> 1622 bytes exp/examples/menu/main.go | 8 ++++ exp/pkg/application/application.go | 43 ++++++++++++++++++++-- exp/pkg/application/application_darwin.go | 20 ++++++++++ exp/pkg/application/dialogs_darwin.go | 43 ++++++++++++++++++++++ exp/pkg/application/menuitem_darwin.go | 2 +- 6 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 exp/examples/menu/icon.png create mode 100644 exp/pkg/application/dialogs_darwin.go diff --git a/exp/examples/menu/icon.png b/exp/examples/menu/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..fc492c9167cce9c272f98bf99207d0efff1d1c1a GIT binary patch literal 1622 zcmV-c2C4apP)?9E5by_tm=H)BK!2&G8Wn%g z1REfMKm>jvR4h%YDEwl01TgZle?-$?nBFt(Ztk8lvpYj`ldheUe8TR%=j?p%mzjHK z?ykvXgb_v$>U*@FR5X( zImyGEK7E?h0m2M;^5luMy}j*{j*bpeS6Nv}@_1nR#x?iv-zRyPuC6Xp2M9CZ`+N6@ z2uyQxGpXzE?#axiS!mW{$10bvHTwY3o;n2L%Dr<#I-0+NHt&vQ25`t|E12Xp)O zZKBVPFavJgxrl#^2vxT3J~kIXpj2PO_&R<Ak5LDN9Ejvgap#3 zMpo9}2EZNT=H@2p=fSIt62c5Pd-g05go%oZl5<;ITS=c9Sy@?fjXQ(a*ViSR%|>)# zgc*>Uno2}rEEbEL`)cYH=~Ls}xpQ*O-Me>5AI}T6JYr2s2s0olDT#>UfeFgj*H69- za37#HCuC-3%6D}$Gc%-*r?9Y)Xi`F$0mqLYC!%=P*4E_7k9`*D1JqW9GiT07M~)mJ z?L6?=X0w@SQbL#khYuen!gv-I7UaC);bGGE?%g}7w6v7818~1^<;oS(&hzNeBcewQ zVFpA-MiOB>v$M1EB(<@zLHgi9>hk5wq#ek}$dH~seM;JS>=UIHgc-1J-##LYXKHFn zD!Futv;(J3rK_F+a0x6fE|PXTaAv`6HP)ksFazKkgozFdv@<$7Dm{DljI=K;ElGZU zeo|Rk8R-LV-n>cLcwlwFT3jK_0QfJsdbS4xV6wvP4(y?hhlYko8xK4mU@fi? zW&kWztE;O-pdB@H>^nYc6P;Qe@b>Ln$;ZcsXmN!w1AzDM-xHCp`0(L_6ciLB*IvDP zmGrvT0ICg zz!NYG*o^^fg8Bwtehvig=68aVlapVv>+er^>*=t$WQL8&Y|;~~U~fc3#IWg~pPPCp zvi9WU$x zvFrgX?%%(EA}uYgijBbnmoy%m=73^`A6!EWDJj4;9oBmQUc7aDot UG_K_hc>n+a07*qoM6N<$g0pSuE&u=k literal 0 HcmV?d00001 diff --git a/exp/examples/menu/main.go b/exp/examples/menu/main.go index de8be8f3a..d994bbee1 100644 --- a/exp/examples/menu/main.go +++ b/exp/examples/menu/main.go @@ -1,13 +1,21 @@ package main import ( + _ "embed" "log" "github.com/wailsapp/wails/exp/pkg/application" ) +//go:embed icon.png +var icon []byte + func main() { + app := application.New() + app.SetName("Menu Demo") + app.SetDescription("A demo of the menu system") + app.SetIcon(icon) // Create a custom menu menu := app.NewMenu() diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index 27274575e..bf26c9fa9 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -45,6 +45,8 @@ type platformApp interface { setApplicationMenu(menu *Menu) name() string getCurrentWindowID() uint + showAboutDialog(name string, description string, icon []byte) + setIcon(icon []byte) } // Messages sent from javascript get routed here @@ -56,7 +58,6 @@ type windowMessage struct { var windowMessageBuffer = make(chan *windowMessage) type App struct { - name string options *options.Application applicationEventListeners map[uint][]func() @@ -84,6 +85,11 @@ type App struct { // The main application menu ApplicationMenu *Menu + + // About Dialog + name string + description string + icon []byte } func (a *App) getSystemTrayID() uint { @@ -187,6 +193,9 @@ func (a *App) Run() error { // set the application menu a.impl.setApplicationMenu(a.ApplicationMenu) + // set the application icon + a.impl.setIcon(a.icon) + return a.impl.run() } @@ -278,9 +287,35 @@ func (a *App) SetMenu(menu *Menu) { } } +func (a *App) SetName(name string) { + a.name = name +} + func (a *App) Name() string { - if a.impl != nil && a.name == "" { - a.name = a.impl.name() - } return a.name } + +func (a *App) SetIcon(icon []byte) { + a.icon = icon + if a.impl != nil { + a.impl.setIcon(icon) + } +} + +func (a *App) Icon() []byte { + return a.icon +} + +func (a *App) SetDescription(description string) { + a.description = description +} + +func (a *App) Description() string { + return a.description +} + +func (a *App) ShowAboutDialog() { + if a.impl != nil { + a.impl.showAboutDialog(a.name, a.description, a.icon) + } +} diff --git a/exp/pkg/application/application_darwin.go b/exp/pkg/application/application_darwin.go index d749dc327..355b37690 100644 --- a/exp/pkg/application/application_darwin.go +++ b/exp/pkg/application/application_darwin.go @@ -61,6 +61,15 @@ static unsigned int getCurrentWindowID(void) { return delegate.windowId; } +// Set the application icon +static void setApplicationIcon(void *icon, int length) { + // On main thread + dispatch_async(dispatch_get_main_queue(), ^{ + NSImage *image = [[NSImage alloc] initWithData:[NSData dataWithBytes:icon length:length]]; + [NSApp setApplicationIconImage:image]; + }); +} + */ import "C" import ( @@ -74,6 +83,10 @@ type macosApp struct { applicationMenu unsafe.Pointer } +func (m *macosApp) setIcon(icon []byte) { + C.setApplicationIcon(unsafe.Pointer(&icon[0]), C.int(len(icon))) +} + func (m *macosApp) name() string { appName := C.getAppName() defer C.free(unsafe.Pointer(appName)) @@ -140,3 +153,10 @@ func processMessage(windowID C.uint, message *C.char) { func processMenuItemClick(menuID C.uint) { menuItemClicked <- uint(menuID) } + +func setIcon(icon []byte) { + if icon == nil { + return + } + C.setApplicationIcon(unsafe.Pointer(&icon[0]), C.int(len(icon))) +} diff --git a/exp/pkg/application/dialogs_darwin.go b/exp/pkg/application/dialogs_darwin.go new file mode 100644 index 000000000..a17ea885a --- /dev/null +++ b/exp/pkg/application/dialogs_darwin.go @@ -0,0 +1,43 @@ +//go:build darwin + +package application + +/* +#cgo CFLAGS: -x objective-c +#cgo LDFLAGS: -framework Cocoa -mmacosx-version-min=10.13 + +#import + +static void showAboutBox(char* title, char *message, void *icon, int length) { + + // run on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + NSAlert *alert = [[NSAlert alloc] init]; + if (title != NULL) { + [alert setMessageText:[NSString stringWithUTF8String:title]]; + free(title); + } + if (message != NULL) { + [alert setInformativeText:[NSString stringWithUTF8String:message]]; + free(message); + } + if (icon != NULL) { + NSImage *image = [[NSImage alloc] initWithData:[NSData dataWithBytes:icon length:length]]; + [alert setIcon:image]; + } + [alert setAlertStyle:NSAlertStyleInformational]; + [alert runModal]; + }); +} + +*/ +import "C" +import "unsafe" + +func (a *macosApp) showAboutDialog(title string, message string, icon []byte) { + var iconData unsafe.Pointer + if icon != nil { + iconData = unsafe.Pointer(&icon[0]) + } + C.showAboutBox(C.CString(title), C.CString(message), iconData, C.int(len(icon))) +} diff --git a/exp/pkg/application/menuitem_darwin.go b/exp/pkg/application/menuitem_darwin.go index b26d9e7aa..0ec8e45d3 100644 --- a/exp/pkg/application/menuitem_darwin.go +++ b/exp/pkg/application/menuitem_darwin.go @@ -501,7 +501,7 @@ func newSelectAllMenuItem() *MenuItem { func newAboutMenuItem() *MenuItem { return newMenuItem("About " + globalApplication.Name()). OnClick(func(ctx *Context) { - // globalApplication.About() + globalApplication.ShowAboutDialog() }) } From 45adc49683a0cceef51a518050d78d0fc374ab8e Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 18 Dec 2022 13:06:03 +1100 Subject: [PATCH 40/85] Add application icon support Add message dialog support Add default icons Add png to byte slice task Fixed kitchen sink --- .gitignore | 2 + exp/examples/dialogs/main.go | 147 ++++++++++++++++++ exp/examples/kitchensink/main.go | 4 +- exp/examples/menu/icon.png | Bin 1622 -> 0 bytes exp/examples/menu/main.go | 4 - exp/examples/systray/macos_template_icon.png | Bin 1212 -> 0 bytes exp/examples/systray/main.go | 5 +- exp/pkg/application/application.go | 17 ++ exp/pkg/application/dialogs.go | 96 ++++++++++++ exp/pkg/application/dialogs_darwin.go | 154 ++++++++++++++++++- exp/pkg/application/icons.go | 8 + exp/tasks/png2bytes/macos_template_icon.png | Bin 0 -> 760 bytes exp/tasks/png2bytes/png2bytes.go | 38 +++++ 13 files changed, 464 insertions(+), 11 deletions(-) create mode 100644 exp/examples/dialogs/main.go delete mode 100644 exp/examples/menu/icon.png delete mode 100644 exp/examples/systray/macos_template_icon.png create mode 100644 exp/pkg/application/dialogs.go create mode 100644 exp/pkg/application/icons.go create mode 100644 exp/tasks/png2bytes/macos_template_icon.png create mode 100644 exp/tasks/png2bytes/png2bytes.go diff --git a/.gitignore b/.gitignore index 7da685641..8538f5c76 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,5 @@ v2/test/kitchensink/frontend/package.json.md5 v2/cmd/wails/internal/commands/initialise/templates/testtemplates/ .env /website/static/img/.cache.json +/exp/examples/dialogs/menu +/exp/examples/menu/menu diff --git a/exp/examples/dialogs/main.go b/exp/examples/dialogs/main.go new file mode 100644 index 000000000..f976f014f --- /dev/null +++ b/exp/examples/dialogs/main.go @@ -0,0 +1,147 @@ +package main + +import ( + _ "embed" + "log" + + "github.com/wailsapp/wails/exp/pkg/application" +) + +func main() { + + app := application.New() + app.SetName("Dialogs Demo") + app.SetDescription("A demo of the Wails dialogs") + + // Create a custom menu + menu := app.NewMenu() + menu.AddRole(application.AppMenu) + + // Let's make a "Demo" menu + infoMenu := menu.AddSubmenu("Info") + infoMenu.Add("Info").OnClick(func(ctx *application.Context) { + dialog := app.NewInfoDialog() + dialog.SetTitle("Custom Title") + dialog.SetMessage("This is a custom message") + dialog.Show() + }) + infoMenu.Add("Info (Title only)").OnClick(func(ctx *application.Context) { + dialog := app.NewInfoDialog() + dialog.SetTitle("Custom Title") + dialog.Show() + }) + infoMenu.Add("Info (Message only)").OnClick(func(ctx *application.Context) { + dialog := app.NewInfoDialog() + dialog.SetMessage("This is a custom message") + dialog.Show() + }) + infoMenu.Add("Info (Custom Icon)").OnClick(func(ctx *application.Context) { + dialog := app.NewInfoDialog() + dialog.SetTitle("Custom Icon Example") + dialog.SetMessage("Using a custom icon") + dialog.SetIcon(application.DefaultApplicationIcon) + dialog.Show() + }) + + questionMenu := menu.AddSubmenu("Question") + questionMenu.Add("Question (No default)").OnClick(func(ctx *application.Context) { + dialog := app.NewQuestionDialog() + dialog.SetMessage("No default button") + dialog.AddButton("Yes") + dialog.AddButton("No") + dialog.Show() + }) + questionMenu.Add("Question (With Default)").OnClick(func(ctx *application.Context) { + dialog := app.NewQuestionDialog() + dialog.SetTitle("Quit") + dialog.SetMessage("You have unsaved work. Are you sure you want to quit?") + dialog.AddButton("Yes").OnClick(func() { + app.Quit() + }) + no := dialog.AddButton("No") + dialog.SetDefaultButton(no) + dialog.Show() + }) + questionMenu.Add("Question (With Cancel)").OnClick(func(ctx *application.Context) { + dialog := app.NewQuestionDialog(). + SetTitle("Update"). + SetMessage("The cancel button is selected when pressing escape") + download := dialog.AddButton("📥 Download") + download.OnClick(func() { + app.NewInfoDialog().SetMessage("Downloading...").Show() + }) + no := dialog.AddButton("Cancel") + dialog.SetDefaultButton(download) + dialog.SetCancelButton(no) + dialog.Show() + }) + questionMenu.Add("Question (Custom Icon)").OnClick(func(ctx *application.Context) { + dialog := app.NewQuestionDialog() + dialog.SetTitle("Custom Icon Example") + dialog.SetMessage("Using a custom icon") + dialog.SetIcon(application.WailsLogoWhiteTransparent) + dialog.SetDefaultButton(dialog.AddButton("I like it!")) + dialog.AddButton("Not so keen...") + dialog.Show() + }) + + warningMenu := menu.AddSubmenu("Warning") + warningMenu.Add("Warning").OnClick(func(ctx *application.Context) { + dialog := app.NewWarningDialog() + dialog.SetTitle("Custom Title") + dialog.SetMessage("This is a custom message") + dialog.Show() + }) + warningMenu.Add("Warning (Title only)").OnClick(func(ctx *application.Context) { + dialog := app.NewWarningDialog() + dialog.SetTitle("Custom Title") + dialog.Show() + }) + warningMenu.Add("Warning (Message only)").OnClick(func(ctx *application.Context) { + dialog := app.NewWarningDialog() + dialog.SetMessage("This is a custom message") + dialog.Show() + }) + warningMenu.Add("Warning (Custom Icon)").OnClick(func(ctx *application.Context) { + dialog := app.NewWarningDialog() + dialog.SetTitle("Custom Icon Example") + dialog.SetMessage("Using a custom icon") + dialog.SetIcon(application.DefaultApplicationIcon) + dialog.Show() + }) + + errorMenu := menu.AddSubmenu("Error") + errorMenu.Add("Error").OnClick(func(ctx *application.Context) { + dialog := app.NewErrorDialog() + dialog.SetTitle("Ooops") + dialog.SetMessage("I accidentally the whole of Twitter") + dialog.Show() + }) + errorMenu.Add("Error (Title Only)").OnClick(func(ctx *application.Context) { + dialog := app.NewErrorDialog() + dialog.SetTitle("Custom Title") + dialog.Show() + }) + errorMenu.Add("Error (Custom Message)").OnClick(func(ctx *application.Context) { + dialog := app.NewErrorDialog() + dialog.SetMessage("This is a custom message") + dialog.Show() + }) + errorMenu.Add("Error (Custom Icon)").OnClick(func(ctx *application.Context) { + dialog := app.NewErrorDialog() + dialog.SetTitle("Custom Icon Example") + dialog.SetMessage("Using a custom icon") + dialog.SetIcon(application.WailsLogoWhite) + dialog.Show() + }) + + app.SetMenu(menu) + + app.NewWindow() + + err := app.Run() + + if err != nil { + log.Fatal(err.Error()) + } +} diff --git a/exp/examples/kitchensink/main.go b/exp/examples/kitchensink/main.go index 6731b86bb..db1faf731 100644 --- a/exp/examples/kitchensink/main.go +++ b/exp/examples/kitchensink/main.go @@ -114,7 +114,7 @@ func main() { mySystray.SetMenu(myMenu) mySystray.SetIconPosition(application.NSImageLeading) - myWindow := app.NewWindow(&options.Window{ + myWindow := app.NewWindowWithOptions(&options.Window{ Title: "Kitchen Sink", Width: 600, Height: 400, @@ -190,7 +190,7 @@ func main() { */ var myWindow2 *application.Window var myWindow2Lock sync.RWMutex - myWindow2 = app.NewWindow(&options.Window{ + myWindow2 = app.NewWindowWithOptions(&options.Window{ Title: "#2", Width: 1024, Height: 768, diff --git a/exp/examples/menu/icon.png b/exp/examples/menu/icon.png deleted file mode 100644 index fc492c9167cce9c272f98bf99207d0efff1d1c1a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1622 zcmV-c2C4apP)?9E5by_tm=H)BK!2&G8Wn%g z1REfMKm>jvR4h%YDEwl01TgZle?-$?nBFt(Ztk8lvpYj`ldheUe8TR%=j?p%mzjHK z?ykvXgb_v$>U*@FR5X( zImyGEK7E?h0m2M;^5luMy}j*{j*bpeS6Nv}@_1nR#x?iv-zRyPuC6Xp2M9CZ`+N6@ z2uyQxGpXzE?#axiS!mW{$10bvHTwY3o;n2L%Dr<#I-0+NHt&vQ25`t|E12Xp)O zZKBVPFavJgxrl#^2vxT3J~kIXpj2PO_&R<Ak5LDN9Ejvgap#3 zMpo9}2EZNT=H@2p=fSIt62c5Pd-g05go%oZl5<;ITS=c9Sy@?fjXQ(a*ViSR%|>)# zgc*>Uno2}rEEbEL`)cYH=~Ls}xpQ*O-Me>5AI}T6JYr2s2s0olDT#>UfeFgj*H69- za37#HCuC-3%6D}$Gc%-*r?9Y)Xi`F$0mqLYC!%=P*4E_7k9`*D1JqW9GiT07M~)mJ z?L6?=X0w@SQbL#khYuen!gv-I7UaC);bGGE?%g}7w6v7818~1^<;oS(&hzNeBcewQ zVFpA-MiOB>v$M1EB(<@zLHgi9>hk5wq#ek}$dH~seM;JS>=UIHgc-1J-##LYXKHFn zD!Futv;(J3rK_F+a0x6fE|PXTaAv`6HP)ksFazKkgozFdv@<$7Dm{DljI=K;ElGZU zeo|Rk8R-LV-n>cLcwlwFT3jK_0QfJsdbS4xV6wvP4(y?hhlYko8xK4mU@fi? zW&kWztE;O-pdB@H>^nYc6P;Qe@b>Ln$;ZcsXmN!w1AzDM-xHCp`0(L_6ciLB*IvDP zmGrvT0ICg zz!NYG*o^^fg8Bwtehvig=68aVlapVv>+er^>*=t$WQL8&Y|;~~U~fc3#IWg~pPPCp zvi9WU$x zvFrgX?%%(EA}uYgijBbnmoy%m=73^`A6!EWDJj4;9oBmQUc7aDot UG_K_hc>n+a07*qoM6N<$g0pSuE&u=k diff --git a/exp/examples/menu/main.go b/exp/examples/menu/main.go index d994bbee1..3f12f3962 100644 --- a/exp/examples/menu/main.go +++ b/exp/examples/menu/main.go @@ -7,15 +7,11 @@ import ( "github.com/wailsapp/wails/exp/pkg/application" ) -//go:embed icon.png -var icon []byte - func main() { app := application.New() app.SetName("Menu Demo") app.SetDescription("A demo of the menu system") - app.SetIcon(icon) // Create a custom menu menu := app.NewMenu() diff --git a/exp/examples/systray/macos_template_icon.png b/exp/examples/systray/macos_template_icon.png deleted file mode 100644 index 659d860e141b3bbf9139c9290f0fe57a78fbe3e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1212 zcmV;t1Vj6YP)#O?|gIZHH`tSTp#>6n{nBD>~F8L_Fi+YDN}m&>eZ`P zuU0EUm5EN^OOb3Qf0O>72n%PS(CCznS;45 zDZPie7#}IA4*7)`@1pd5T&m2#c%xF&G>msq>0e?t#HC1xdG3RHo99PThg|RbYDu60FOngUozP>yDE}aJo_nEZ z6{$hKk<2eX2{hmk83fr3Jr9x^WCQeUBQ?l#zQ;=f4cJcxK^}#kH%JYF1{@_d$ZFr? zC4mO)CW9cu!&x8CRDLEk$UUy-Lgg1y-}dC$0VMP1J%fd)KG212e*wYIkK1IaV)bg%I_$$LKe zXCf{MG++Z62w9P8uO+!0ccdQs#dwzFJrllVm?Y4ETggDk;Cb}#L6XZ+8!*b?Kb1uj zr#69-ht=20g(10t+V4jny?qibsUU{6vjrGct zB<^_~=gCO|4Om77^L#7Ss_Yq(vkR%mNZhztd7H#NgA-*NNuU9?XMlrw?8LW`#Elyz ze+1aSz$p^1IjPLVd2*6K18fIooD5j=sqzkqpH?nVHj$jMm&80raF!-XpaFJq({ycb z2H438tu;hvvF8DP@7pU99+ z{4Qy$O8-7Z@}oF}GmMf18(^OZ4%x(eu6HxZk796fRU!#C-~<`6iA}C|3&}U}l|tA3 znk2ynd_e}yaaLL4dY>jWP3-Zn-BuE8z%eptj$_cfmDJ=ISC;$!wvu22J|x5Dz$NlF ztGzX!`Q8#qumSIqVRNj6-Vy`0`rZ;rumNqBxsBtbx6PueVb>DFb4RHp*nl>BcE&-{ z`wXdLypO#ll3)W~CId6BBfV`6cm#V(B*6wePXyqrK9jUF;4SPcl>{5Giwuq2gncHB? 4 { + m.dialog.buttons = m.dialog.buttons[:4] + } + + if m.nsDialog != nil { + C.releaseDialog(m.nsDialog) + } + var title *C.char + if m.dialog.title != "" { + title = C.CString(m.dialog.title) + } + var message *C.char + if m.dialog.message != "" { + message = C.CString(m.dialog.message) + } + var iconData unsafe.Pointer + var iconLength C.int + if m.dialog.icon != nil { + iconData = unsafe.Pointer(&m.dialog.icon[0]) + iconLength = C.int(len(m.dialog.icon)) + } else { + // if it's an error, use the application icon + if m.dialog.dialogType == ErrorDialog { + iconData = unsafe.Pointer(&globalApplication.icon[0]) + iconLength = C.int(len(globalApplication.icon)) + } + } + + alertType, ok := alertTypeMap[m.dialog.dialogType] + if !ok { + alertType = C.NSAlertStyleInformational + } + + m.nsDialog = C.createAlert(alertType, title, message, iconData, iconLength) + + // Reverse the buttons so that the default is on the right + reversedButtons := make([]*Button, len(m.dialog.buttons)) + var count = 0 + for i := len(m.dialog.buttons) - 1; i >= 0; i-- { + button := m.dialog.buttons[i] + C.alertAddButton(m.nsDialog, C.CString(button.label), C.bool(button.isDefault), C.bool(button.isCancel)) + reversedButtons[count] = m.dialog.buttons[i] + count++ + } + + buttonPressed := int(C.dialogRunModal(m.nsDialog)) + if len(m.dialog.buttons) > buttonPressed { + button := reversedButtons[buttonPressed] + if button.callback != nil { + button.callback() + } + } + }) + +} + +func newDialogImpl(d *Dialog) *macosDialog { + return &macosDialog{ + dialog: d, + } +} diff --git a/exp/pkg/application/icons.go b/exp/pkg/application/icons.go new file mode 100644 index 000000000..13ef1f389 --- /dev/null +++ b/exp/pkg/application/icons.go @@ -0,0 +1,8 @@ +package application + +var DefaultApplicationIcon = []byte{137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 64, 0, 0, 0, 64, 8, 3, 0, 0, 0, 157, 183, 129, 236, 0, 0, 1, 2, 80, 76, 84, 69, 0, 0, 0, 255, 255, 255, 20, 20, 20, 14, 14, 14, 255, 255, 255, 9, 9, 9, 103, 103, 103, 255, 255, 255, 255, 255, 255, 185, 185, 185, 255, 255, 255, 16, 16, 16, 27, 27, 27, 2, 2, 2, 23, 23, 23, 62, 62, 62, 105, 105, 105, 12, 12, 12, 21, 21, 21, 36, 36, 36, 41, 41, 41, 51, 51, 51, 55, 55, 55, 78, 78, 78, 146, 146, 146, 226, 226, 226, 0, 0, 0, 225, 225, 225, 79, 79, 79, 17, 17, 17, 76, 76, 76, 221, 221, 221, 101, 101, 101, 64, 64, 64, 223, 223, 223, 217, 217, 217, 133, 133, 133, 104, 104, 104, 94, 94, 94, 6, 6, 6, 202, 202, 202, 198, 198, 198, 110, 110, 110, 97, 97, 97, 70, 70, 70, 55, 55, 55, 13, 13, 13, 211, 211, 211, 188, 188, 188, 176, 176, 176, 117, 117, 117, 91, 91, 91, 73, 73, 73, 34, 35, 34, 27, 27, 27, 21, 21, 21, 173, 173, 173, 166, 166, 166, 161, 162, 162, 150, 150, 150, 142, 143, 143, 136, 136, 136, 119, 119, 119, 90, 90, 90, 87, 87, 87, 50, 50, 50, 44, 44, 45, 41, 41, 41, 32, 32, 32, 4, 4, 4, 214, 214, 214, 178, 178, 178, 158, 158, 158, 153, 153, 153, 148, 148, 148, 123, 123, 123, 82, 82, 82, 67, 67, 67, 66, 66, 66, 208, 208, 208, 192, 192, 192, 190, 190, 190, 184, 184, 184, 127, 127, 127, 126, 126, 126, 60, 60, 61, 204, 47, 21, 237, 0, 0, 0, 26, 116, 82, 78, 83, 0, 12, 195, 213, 16, 227, 64, 19, 14, 29, 9, 198, 164, 248, 176, 96, 59, 213, 184, 145, 130, 110, 106, 78, 37, 20, 109, 186, 18, 188, 0, 0, 2, 46, 73, 68, 65, 84, 88, 195, 237, 150, 123, 83, 26, 49, 20, 197, 89, 107, 91, 10, 84, 251, 126, 220, 128, 91, 150, 151, 96, 65, 64, 121, 169, 80, 68, 169, 90, 31, 125, 233, 247, 255, 42, 206, 238, 222, 51, 73, 112, 38, 201, 50, 227, 140, 227, 120, 254, 217, 61, 155, 156, 223, 228, 113, 179, 147, 212, 147, 30, 153, 50, 158, 187, 50, 119, 227, 95, 63, 174, 173, 184, 43, 247, 217, 91, 200, 191, 202, 82, 50, 189, 79, 235, 195, 207, 81, 82, 173, 235, 3, 120, 157, 24, 176, 162, 77, 226, 13, 37, 214, 243, 85, 21, 240, 98, 9, 192, 203, 251, 1, 52, 243, 172, 89, 232, 10, 108, 250, 161, 233, 161, 169, 104, 2, 236, 11, 214, 255, 208, 109, 177, 201, 135, 230, 0, 77, 101, 3, 64, 246, 234, 134, 110, 196, 102, 35, 52, 155, 104, 106, 154, 0, 101, 244, 170, 132, 51, 240, 21, 192, 17, 90, 234, 100, 2, 156, 163, 91, 149, 136, 242, 66, 1, 124, 131, 153, 24, 1, 93, 116, 155, 98, 65, 0, 216, 131, 57, 50, 2, 26, 74, 166, 246, 19, 102, 87, 49, 109, 50, 1, 228, 64, 139, 68, 69, 161, 0, 154, 120, 111, 152, 1, 59, 202, 82, 151, 37, 64, 206, 45, 232, 155, 1, 23, 200, 204, 148, 125, 19, 223, 137, 78, 248, 117, 72, 102, 192, 6, 50, 61, 58, 20, 10, 160, 16, 96, 119, 44, 128, 75, 100, 250, 52, 81, 1, 0, 251, 3, 11, 224, 6, 153, 22, 181, 85, 192, 152, 223, 246, 200, 2, 192, 184, 131, 121, 47, 122, 198, 235, 112, 73, 117, 254, 126, 97, 3, 160, 96, 75, 84, 137, 158, 241, 78, 92, 29, 227, 115, 203, 6, 64, 207, 109, 26, 70, 3, 248, 17, 23, 69, 149, 63, 255, 34, 27, 160, 143, 19, 51, 240, 163, 1, 48, 224, 12, 139, 97, 5, 20, 80, 176, 211, 56, 25, 3, 174, 182, 121, 92, 53, 43, 160, 197, 251, 221, 57, 141, 2, 243, 184, 50, 113, 66, 198, 100, 5, 212, 124, 6, 148, 226, 41, 199, 128, 33, 234, 219, 14, 160, 18, 23, 12, 31, 201, 170, 226, 68, 125, 238, 0, 248, 45, 164, 74, 45, 6, 176, 206, 201, 14, 224, 138, 65, 217, 233, 128, 153, 11, 224, 143, 18, 216, 225, 255, 50, 235, 47, 185, 0, 254, 201, 64, 48, 208, 1, 13, 39, 64, 71, 6, 58, 164, 1, 130, 99, 39, 192, 72, 38, 42, 252, 139, 99, 157, 144, 19, 224, 84, 38, 122, 58, 96, 203, 13, 176, 47, 160, 54, 105, 0, 127, 224, 6, 56, 16, 208, 68, 7, 140, 200, 13, 48, 22, 208, 161, 14, 152, 58, 2, 174, 17, 216, 140, 108, 69, 86, 165, 35, 160, 139, 68, 89, 7, 156, 145, 35, 160, 129, 68, 81, 7, 236, 186, 2, 106, 5, 214, 162, 189, 11, 120, 88, 151, 172, 229, 239, 137, 203, 223, 84, 179, 158, 10, 240, 214, 18, 3, 62, 165, 52, 125, 121, 155, 48, 159, 75, 47, 222, 247, 63, 100, 159, 185, 235, 221, 58, 231, 85, 121, 233, 85, 87, 165, 51, 169, 39, 61, 36, 221, 2, 115, 72, 10, 51, 166, 156, 57, 80, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130} +var DefaultMacTemplateIcon = []byte{137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 64, 0, 0, 0, 64, 8, 3, 0, 0, 0, 157, 183, 129, 236, 0, 0, 0, 135, 80, 76, 84, 69, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 106, 145, 255, 17, 0, 0, 0, 45, 116, 82, 78, 83, 0, 225, 11, 16, 14, 7, 26, 18, 79, 65, 23, 221, 100, 91, 176, 74, 217, 118, 95, 34, 20, 211, 201, 133, 104, 69, 149, 110, 53, 189, 167, 161, 125, 86, 76, 45, 198, 154, 143, 136, 57, 41, 185, 203, 192, 69, 76, 133, 225, 0, 0, 1, 243, 73, 68, 65, 84, 88, 195, 237, 214, 109, 111, 130, 48, 16, 7, 240, 107, 41, 34, 48, 31, 65, 116, 62, 59, 231, 220, 220, 190, 255, 231, 155, 216, 187, 28, 213, 164, 61, 98, 150, 152, 197, 255, 27, 57, 219, 254, 44, 133, 34, 240, 204, 63, 139, 110, 145, 248, 118, 120, 146, 69, 70, 158, 40, 211, 224, 166, 212, 208, 46, 165, 113, 167, 159, 64, 219, 100, 158, 74, 20, 227, 204, 185, 211, 30, 136, 163, 123, 129, 228, 111, 128, 101, 23, 179, 175, 171, 8, 139, 75, 115, 65, 77, 169, 15, 152, 43, 204, 182, 174, 198, 88, 116, 235, 226, 131, 154, 166, 30, 128, 123, 141, 234, 106, 141, 197, 91, 93, 124, 83, 211, 210, 7, 76, 169, 215, 172, 62, 131, 188, 1, 124, 81, 203, 187, 119, 13, 182, 212, 109, 124, 46, 186, 84, 12, 206, 197, 11, 207, 205, 7, 140, 168, 219, 142, 22, 132, 128, 13, 21, 95, 94, 96, 161, 120, 214, 241, 164, 1, 196, 67, 60, 62, 121, 47, 35, 79, 52, 5, 72, 85, 3, 248, 164, 227, 133, 31, 232, 53, 150, 122, 202, 64, 227, 220, 58, 126, 96, 71, 253, 246, 0, 149, 162, 188, 2, 244, 241, 176, 15, 126, 96, 64, 99, 10, 216, 43, 6, 248, 138, 142, 3, 64, 202, 51, 29, 53, 1, 130, 243, 210, 15, 240, 90, 25, 88, 53, 129, 35, 30, 109, 130, 155, 137, 198, 64, 113, 249, 168, 16, 120, 167, 93, 225, 7, 248, 134, 29, 194, 204, 110, 28, 123, 77, 11, 250, 90, 135, 0, 234, 57, 177, 203, 94, 245, 44, 64, 87, 119, 14, 33, 160, 67, 59, 166, 204, 47, 19, 64, 224, 64, 139, 17, 4, 18, 236, 185, 218, 217, 145, 8, 76, 112, 94, 113, 16, 208, 116, 191, 28, 236, 0, 11, 208, 14, 57, 66, 16, 136, 115, 4, 134, 246, 148, 45, 64, 15, 150, 207, 48, 0, 184, 233, 172, 243, 134, 0, 170, 21, 8, 128, 137, 226, 12, 13, 62, 21, 49, 91, 9, 80, 41, 206, 6, 92, 96, 47, 1, 126, 20, 167, 231, 2, 43, 144, 0, 39, 30, 144, 103, 46, 176, 16, 1, 125, 30, 208, 199, 39, 20, 165, 16, 1, 107, 30, 48, 35, 128, 60, 17, 176, 105, 252, 162, 11, 188, 200, 128, 185, 187, 102, 12, 228, 153, 12, 248, 80, 148, 145, 11, 172, 65, 6, 28, 21, 101, 233, 2, 187, 48, 192, 255, 109, 124, 223, 206, 248, 174, 148, 1, 252, 40, 157, 186, 192, 1, 132, 192, 130, 70, 164, 46, 48, 144, 2, 113, 132, 185, 46, 111, 129, 199, 122, 201, 202, 238, 124, 79, 188, 255, 77, 85, 71, 173, 129, 236, 206, 183, 245, 196, 192, 149, 80, 26, 45, 143, 201, 204, 237, 162, 104, 19, 73, 99, 52, 60, 243, 72, 249, 5, 251, 207, 25, 192, 218, 106, 27, 249, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130} +var WailsLogoBlack = []byte{137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 128, 0, 0, 0, 128, 8, 3, 0, 0, 0, 244, 224, 145, 249, 0, 0, 3, 0, 80, 76, 84, 69, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 254, 254, 254, 8, 1, 1, 227, 49, 49, 255, 255, 255, 5, 5, 5, 0, 0, 0, 6, 1, 1, 203, 44, 44, 227, 50, 50, 35, 6, 6, 160, 22, 29, 244, 53, 53, 150, 17, 26, 234, 51, 51, 36, 6, 6, 7, 1, 1, 59, 10, 12, 255, 255, 255, 6, 5, 5, 13, 2, 2, 23, 4, 4, 212, 212, 212, 15, 2, 2, 234, 51, 51, 188, 35, 38, 171, 27, 33, 78, 17, 17, 240, 52, 52, 231, 231, 231, 51, 8, 10, 26, 26, 26, 76, 76, 76, 163, 163, 163, 171, 30, 34, 218, 42, 45, 210, 42, 44, 214, 45, 46, 23, 23, 23, 13, 13, 13, 195, 41, 42, 225, 49, 49, 135, 25, 28, 42, 7, 8, 66, 13, 14, 148, 29, 31, 111, 23, 23, 154, 154, 154, 225, 48, 48, 204, 39, 42, 198, 38, 41, 146, 28, 30, 131, 12, 21, 105, 17, 20, 186, 35, 38, 139, 139, 139, 88, 12, 16, 48, 7, 9, 186, 30, 36, 5, 5, 5, 219, 47, 47, 183, 31, 36, 35, 35, 35, 247, 246, 246, 209, 44, 45, 253, 252, 252, 116, 116, 116, 118, 23, 24, 11, 2, 2, 77, 14, 15, 126, 23, 25, 33, 5, 6, 253, 55, 55, 128, 5, 17, 55, 9, 10, 242, 242, 242, 145, 15, 24, 27, 4, 5, 238, 238, 238, 225, 225, 225, 179, 29, 35, 179, 179, 179, 20, 3, 3, 171, 34, 36, 40, 40, 40, 166, 33, 35, 89, 18, 18, 235, 235, 235, 207, 207, 207, 93, 93, 93, 43, 8, 9, 53, 8, 10, 230, 46, 48, 196, 33, 38, 115, 4, 16, 194, 194, 194, 60, 60, 60, 140, 18, 25, 170, 170, 170, 103, 103, 103, 160, 34, 34, 99, 20, 21, 135, 28, 29, 72, 14, 15, 146, 146, 146, 148, 30, 31, 206, 36, 40, 12, 12, 12, 64, 10, 12, 22, 3, 4, 191, 34, 38, 163, 23, 30, 163, 30, 33, 72, 11, 13, 217, 47, 47, 47, 47, 47, 153, 22, 28, 216, 216, 216, 156, 28, 32, 221, 221, 221, 51, 51, 51, 96, 17, 19, 178, 36, 38, 104, 17, 20, 38, 4, 6, 141, 26, 29, 222, 47, 48, 68, 68, 68, 131, 131, 131, 87, 87, 87, 114, 13, 19, 202, 202, 202, 24, 3, 4, 229, 229, 229, 189, 189, 189, 148, 148, 148, 91, 8, 15, 100, 17, 20, 125, 10, 19, 203, 40, 43, 145, 20, 27, 62, 62, 62, 191, 39, 41, 104, 20, 22, 194, 194, 194, 173, 173, 173, 85, 15, 17, 203, 203, 203, 206, 19, 21, 198, 198, 198, 159, 159, 159, 163, 24, 30, 126, 126, 126, 212, 44, 45, 108, 108, 108, 248, 248, 248, 134, 25, 27, 129, 23, 26, 141, 26, 29, 186, 116, 121, 64, 8, 12, 99, 16, 19, 250, 234, 235, 227, 80, 80, 227, 201, 204, 224, 103, 104, 35, 35, 35, 243, 187, 187, 163, 73, 80, 114, 114, 114, 183, 183, 183, 10, 0, 1, 255, 238, 238, 146, 40, 50, 212, 71, 73, 230, 148, 149, 0, 0, 0, 203, 53, 56, 86, 14, 17, 0, 0, 0, 227, 50, 50, 255, 255, 255, 5, 1, 1, 224, 48, 49, 216, 45, 46, 221, 47, 48, 218, 46, 47, 214, 44, 46, 210, 43, 45, 4, 4, 4, 2, 2, 2, 205, 41, 43, 225, 49, 49, 194, 36, 40, 212, 44, 45, 222, 48, 48, 184, 32, 36, 209, 42, 44, 219, 47, 47, 198, 37, 41, 177, 29, 34, 188, 34, 38, 192, 35, 39, 202, 39, 42, 204, 40, 42, 200, 39, 41, 251, 251, 251, 187, 33, 37, 180, 30, 35, 172, 27, 33, 182, 31, 36, 218, 48, 48, 247, 54, 54, 236, 51, 52, 229, 50, 50, 207, 41, 43, 190, 34, 38, 175, 28, 33, 129, 8, 19, 8, 8, 8, 196, 36, 40, 169, 25, 31, 245, 245, 245, 154, 34, 34, 164, 24, 30, 154, 19, 27, 133, 9, 20, 231, 50, 50, 167, 24, 31, 135, 11, 21, 120, 5, 17, 240, 52, 52, 125, 7, 18, 170, 26, 32, 141, 14, 23, 137, 12, 22, 214, 41, 44, 157, 20, 28, 145, 15, 24, 190, 31, 37, 211, 42, 44, 223, 43, 46, 203, 36, 40, 148, 31, 32, 173, 26, 32, 162, 22, 29, 199, 35, 40, 220, 43, 46, 210, 37, 40, 183, 27, 34, 153, 33, 33, 124, 0, 8, 252, 54, 55, 29, 193, 86, 184, 0, 0, 0, 182, 116, 82, 78, 83, 254, 251, 225, 249, 254, 254, 254, 249, 244, 246, 247, 245, 249, 248, 254, 254, 254, 254, 241, 251, 241, 246, 246, 246, 241, 239, 252, 250, 247, 247, 247, 251, 247, 243, 242, 241, 235, 230, 254, 250, 249, 248, 246, 244, 243, 242, 242, 241, 240, 240, 237, 252, 250, 247, 245, 244, 243, 241, 240, 233, 252, 251, 250, 249, 248, 248, 247, 245, 244, 243, 242, 242, 241, 239, 230, 251, 250, 249, 248, 247, 246, 245, 245, 245, 244, 244, 243, 242, 242, 242, 239, 237, 235, 235, 233, 254, 251, 251, 245, 245, 244, 243, 242, 240, 238, 236, 236, 235, 234, 253, 253, 252, 249, 248, 248, 246, 246, 245, 245, 245, 243, 243, 242, 240, 240, 239, 254, 254, 253, 250, 247, 246, 242, 241, 238, 234, 231, 231, 249, 249, 248, 248, 241, 239, 236, 235, 235, 234, 230, 226, 253, 252, 247, 246, 239, 236, 236, 235, 234, 229, 224, 220, 234, 224, 223, 246, 246, 243, 240, 239, 234, 234, 224, 223, 211, 248, 247, 244, 239, 229, 215, 214, 81, 124, 11, 18, 0, 0, 15, 238, 73, 68, 65, 84, 120, 218, 236, 152, 107, 72, 83, 97, 24, 199, 223, 211, 216, 106, 43, 117, 46, 73, 209, 173, 240, 131, 115, 160, 203, 162, 108, 134, 137, 146, 161, 89, 138, 129, 40, 245, 65, 81, 8, 180, 40, 74, 51, 36, 232, 250, 33, 250, 208, 141, 130, 8, 34, 232, 126, 161, 160, 123, 59, 109, 78, 151, 59, 187, 232, 212, 57, 156, 171, 188, 49, 97, 115, 154, 121, 77, 69, 187, 16, 61, 239, 57, 59, 30, 187, 88, 218, 205, 47, 253, 81, 16, 207, 129, 255, 239, 125, 222, 231, 242, 190, 7, 205, 81, 19, 234, 217, 212, 127, 128, 255, 0, 255, 1, 254, 3, 252, 7, 248, 71, 0, 104, 118, 1, 16, 31, 126, 103, 17, 64, 163, 81, 7, 75, 166, 66, 248, 251, 0, 176, 124, 34, 102, 7, 0, 168, 103, 7, 0, 150, 191, 104, 91, 244, 226, 41, 2, 240, 215, 1, 144, 6, 150, 31, 181, 49, 5, 169, 53, 234, 217, 0, 128, 85, 103, 239, 8, 123, 185, 143, 167, 230, 171, 103, 1, 0, 85, 169, 137, 245, 201, 1, 61, 81, 217, 106, 62, 154, 5, 0, 240, 12, 137, 8, 120, 229, 77, 140, 81, 107, 102, 167, 15, 8, 139, 162, 95, 82, 100, 216, 114, 2, 88, 254, 53, 0, 68, 31, 73, 14, 108, 12, 52, 147, 175, 10, 133, 120, 3, 48, 67, 213, 191, 2, 64, 8, 220, 68, 203, 23, 188, 212, 106, 201, 87, 243, 179, 185, 4, 252, 123, 0, 8, 49, 63, 85, 88, 154, 42, 88, 126, 208, 153, 141, 222, 26, 146, 244, 42, 194, 241, 83, 2, 17, 66, 132, 178, 119, 31, 202, 205, 221, 13, 239, 253, 62, 0, 226, 60, 17, 237, 249, 21, 76, 112, 90, 216, 75, 221, 10, 146, 36, 155, 183, 137, 114, 243, 50, 182, 159, 59, 158, 178, 163, 108, 79, 68, 97, 218, 245, 188, 96, 244, 7, 34, 128, 144, 70, 163, 249, 42, 232, 4, 15, 241, 230, 45, 12, 61, 22, 114, 72, 146, 23, 127, 102, 99, 243, 11, 18, 251, 39, 151, 149, 100, 37, 189, 29, 29, 144, 239, 148, 238, 75, 217, 181, 155, 248, 115, 91, 128, 64, 60, 33, 18, 166, 134, 134, 30, 243, 59, 148, 23, 180, 107, 125, 252, 241, 19, 105, 39, 79, 158, 206, 28, 186, 112, 113, 73, 143, 121, 5, 246, 23, 40, 100, 181, 111, 223, 214, 39, 200, 148, 251, 195, 131, 121, 4, 194, 131, 1, 253, 9, 0, 209, 134, 9, 207, 163, 5, 5, 42, 85, 103, 102, 230, 144, 88, 236, 1, 13, 122, 196, 171, 19, 189, 100, 13, 137, 69, 81, 249, 31, 19, 100, 167, 227, 130, 66, 132, 216, 67, 195, 231, 220, 127, 19, 96, 81, 124, 122, 65, 122, 122, 123, 123, 39, 86, 183, 79, 253, 253, 253, 125, 125, 253, 251, 78, 45, 32, 205, 102, 198, 63, 240, 212, 233, 184, 24, 63, 17, 161, 198, 238, 26, 244, 39, 199, 241, 238, 130, 55, 5, 175, 105, 189, 121, 243, 6, 147, 116, 131, 121, 223, 80, 95, 230, 234, 196, 102, 202, 76, 9, 40, 240, 215, 6, 22, 30, 19, 17, 104, 10, 243, 223, 173, 130, 77, 39, 95, 23, 48, 246, 237, 96, 15, 254, 24, 160, 255, 194, 41, 1, 44, 95, 75, 81, 20, 246, 143, 74, 85, 131, 176, 249, 95, 232, 3, 40, 60, 29, 251, 115, 0, 96, 159, 185, 250, 8, 105, 214, 105, 181, 0, 32, 32, 169, 230, 232, 60, 110, 233, 127, 161, 17, 17, 165, 221, 92, 0, 112, 4, 186, 47, 36, 11, 180, 58, 179, 150, 6, 32, 5, 100, 216, 89, 110, 4, 252, 149, 78, 184, 240, 120, 39, 11, 0, 9, 216, 9, 203, 167, 106, 106, 124, 0, 2, 129, 246, 213, 14, 33, 156, 65, 126, 21, 224, 167, 232, 56, 178, 217, 71, 59, 95, 183, 99, 125, 250, 212, 174, 186, 144, 76, 213, 84, 232, 116, 58, 179, 153, 142, 128, 182, 71, 26, 12, 254, 51, 7, 64, 124, 62, 193, 19, 206, 35, 112, 251, 6, 253, 120, 19, 36, 39, 219, 95, 127, 250, 244, 41, 253, 193, 213, 171, 79, 228, 84, 57, 172, 31, 0, 24, 127, 60, 2, 52, 232, 87, 0, 54, 169, 182, 166, 93, 186, 124, 244, 224, 193, 184, 179, 215, 175, 199, 239, 42, 45, 141, 217, 126, 45, 239, 208, 33, 63, 137, 100, 195, 177, 208, 208, 80, 209, 162, 212, 121, 72, 13, 112, 60, 30, 82, 19, 185, 233, 111, 148, 119, 175, 222, 90, 119, 231, 230, 200, 139, 242, 138, 10, 6, 0, 139, 92, 80, 132, 112, 6, 254, 194, 22, 160, 12, 255, 177, 241, 142, 177, 177, 177, 218, 90, 199, 199, 143, 31, 45, 9, 9, 197, 197, 197, 78, 75, 130, 116, 245, 153, 51, 189, 189, 178, 156, 136, 136, 136, 195, 135, 15, 43, 183, 93, 186, 28, 119, 240, 68, 220, 221, 91, 55, 230, 62, 187, 127, 251, 252, 7, 5, 248, 87, 112, 17, 104, 142, 141, 11, 23, 209, 37, 56, 243, 28, 64, 126, 153, 227, 98, 104, 169, 131, 254, 32, 183, 187, 171, 163, 183, 169, 13, 96, 156, 150, 186, 214, 122, 151, 235, 221, 104, 67, 203, 240, 192, 192, 128, 252, 253, 251, 145, 17, 106, 228, 230, 141, 103, 107, 31, 37, 159, 127, 145, 88, 201, 1, 128, 200, 72, 177, 71, 166, 138, 73, 5, 123, 254, 47, 148, 225, 26, 79, 151, 103, 124, 124, 220, 221, 213, 213, 1, 238, 77, 109, 224, 95, 235, 112, 56, 19, 18, 156, 22, 139, 165, 14, 4, 40, 245, 70, 163, 203, 101, 181, 157, 127, 120, 7, 150, 159, 88, 89, 89, 14, 0, 19, 57, 72, 30, 41, 233, 22, 123, 198, 146, 246, 109, 145, 16, 184, 13, 206, 16, 0, 8, 6, 59, 60, 254, 227, 110, 32, 96, 0, 176, 63, 152, 55, 54, 214, 181, 50, 214, 86, 171, 221, 214, 208, 96, 48, 24, 244, 45, 59, 63, 84, 42, 76, 12, 0, 36, 33, 179, 3, 130, 172, 118, 177, 103, 208, 191, 203, 146, 159, 149, 178, 148, 7, 81, 208, 160, 153, 1, 32, 76, 224, 198, 225, 159, 12, 192, 16, 176, 0, 118, 155, 13, 8, 90, 244, 38, 147, 105, 216, 4, 254, 44, 0, 16, 144, 177, 233, 125, 98, 241, 160, 187, 183, 169, 214, 245, 33, 118, 85, 204, 34, 64, 224, 207, 100, 22, 32, 32, 240, 239, 29, 252, 14, 64, 29, 7, 0, 254, 24, 160, 90, 175, 215, 211, 1, 96, 139, 192, 12, 9, 160, 234, 28, 26, 242, 248, 187, 155, 106, 157, 150, 86, 195, 123, 69, 206, 150, 84, 60, 138, 103, 116, 59, 6, 130, 49, 127, 102, 7, 32, 5, 113, 14, 50, 91, 80, 199, 248, 51, 0, 6, 12, 80, 173, 55, 49, 59, 48, 1, 144, 88, 246, 166, 175, 79, 76, 3, 88, 234, 140, 46, 123, 165, 96, 65, 212, 242, 16, 2, 16, 102, 52, 142, 215, 184, 219, 152, 44, 156, 148, 134, 190, 60, 0, 6, 216, 130, 9, 0, 253, 23, 0, 218, 21, 178, 130, 238, 254, 33, 0, 232, 162, 1, 108, 134, 106, 147, 206, 251, 106, 175, 146, 78, 6, 52, 109, 0, 32, 216, 179, 58, 43, 43, 43, 41, 33, 161, 177, 241, 109, 125, 126, 126, 254, 187, 119, 163, 163, 59, 119, 182, 128, 101, 245, 240, 176, 205, 138, 183, 224, 123, 17, 16, 72, 11, 218, 89, 0, 135, 165, 213, 101, 51, 232, 203, 43, 106, 4, 129, 61, 11, 10, 99, 132, 184, 49, 76, 23, 0, 169, 67, 54, 108, 200, 205, 13, 15, 207, 88, 179, 102, 77, 198, 185, 167, 231, 206, 197, 239, 223, 127, 226, 32, 116, 200, 43, 87, 174, 236, 136, 173, 182, 114, 57, 48, 25, 128, 74, 62, 249, 186, 179, 187, 111, 72, 60, 56, 222, 209, 230, 176, 212, 27, 49, 64, 141, 25, 247, 166, 158, 176, 213, 235, 1, 65, 141, 190, 5, 224, 205, 232, 32, 192, 227, 17, 68, 248, 202, 1, 43, 222, 2, 122, 7, 38, 85, 161, 54, 81, 166, 242, 1, 184, 59, 218, 156, 141, 70, 123, 67, 181, 169, 66, 167, 37, 177, 154, 123, 2, 78, 21, 225, 230, 132, 166, 57, 142, 159, 35, 172, 137, 171, 78, 149, 79, 106, 172, 140, 149, 3, 118, 22, 160, 210, 7, 160, 171, 209, 173, 144, 14, 150, 168, 218, 251, 251, 134, 60, 80, 133, 181, 206, 198, 122, 91, 165, 110, 133, 192, 27, 248, 106, 9, 86, 96, 96, 192, 198, 232, 109, 146, 175, 139, 238, 30, 63, 56, 52, 116, 33, 136, 199, 227, 137, 68, 11, 69, 172, 126, 120, 156, 0, 130, 114, 187, 1, 50, 2, 0, 184, 54, 160, 141, 245, 119, 119, 148, 165, 247, 251, 170, 208, 146, 180, 45, 38, 99, 87, 233, 226, 73, 42, 93, 124, 98, 123, 234, 215, 0, 126, 215, 226, 227, 142, 170, 84, 91, 105, 157, 62, 189, 108, 95, 225, 230, 205, 57, 57, 7, 138, 160, 114, 126, 72, 32, 183, 227, 28, 228, 0, 42, 180, 145, 37, 227, 80, 55, 101, 157, 108, 17, 180, 22, 175, 10, 18, 254, 236, 176, 129, 30, 171, 121, 68, 176, 36, 232, 248, 81, 149, 184, 107, 236, 227, 91, 16, 20, 154, 181, 97, 88, 113, 246, 199, 4, 187, 26, 228, 54, 253, 36, 128, 10, 115, 98, 150, 127, 71, 71, 83, 147, 44, 179, 143, 173, 66, 251, 251, 176, 168, 229, 18, 4, 61, 128, 147, 102, 138, 171, 25, 33, 20, 102, 47, 45, 221, 159, 86, 38, 75, 106, 117, 185, 92, 198, 122, 107, 228, 89, 248, 176, 242, 35, 2, 133, 220, 62, 169, 17, 234, 142, 72, 253, 59, 232, 190, 37, 203, 20, 15, 194, 159, 184, 8, 140, 182, 145, 192, 249, 105, 208, 3, 166, 60, 29, 48, 85, 192, 94, 245, 16, 1, 20, 219, 227, 148, 155, 165, 43, 203, 223, 143, 8, 224, 203, 194, 243, 41, 174, 101, 176, 20, 226, 92, 244, 136, 193, 196, 1, 196, 186, 25, 127, 135, 83, 70, 23, 129, 163, 177, 222, 218, 208, 98, 208, 55, 7, 68, 47, 163, 123, 0, 31, 253, 168, 19, 34, 196, 81, 240, 130, 253, 130, 138, 148, 133, 81, 209, 151, 133, 220, 134, 177, 239, 240, 225, 53, 166, 20, 136, 107, 23, 203, 171, 77, 62, 0, 93, 164, 172, 11, 252, 233, 174, 157, 80, 226, 113, 247, 182, 57, 49, 64, 53, 174, 144, 192, 128, 176, 156, 248, 96, 14, 97, 170, 50, 228, 40, 64, 4, 33, 10, 9, 143, 63, 6, 0, 236, 191, 153, 39, 204, 51, 158, 40, 91, 18, 180, 126, 255, 153, 247, 44, 64, 141, 34, 169, 11, 183, 108, 122, 110, 183, 38, 149, 184, 155, 218, 156, 117, 70, 12, 0, 109, 192, 108, 246, 6, 44, 129, 129, 128, 48, 194, 148, 0, 223, 82, 128, 24, 227, 42, 182, 7, 17, 194, 96, 73, 120, 204, 150, 229, 202, 85, 57, 210, 83, 43, 19, 229, 250, 106, 182, 13, 188, 40, 238, 98, 166, 22, 30, 23, 245, 198, 164, 146, 94, 60, 9, 236, 6, 26, 0, 174, 73, 230, 230, 158, 37, 201, 202, 92, 176, 226, 79, 243, 251, 192, 36, 10, 130, 71, 164, 238, 206, 13, 138, 143, 75, 91, 181, 39, 75, 26, 187, 50, 114, 120, 0, 107, 88, 15, 98, 27, 97, 108, 47, 187, 124, 60, 173, 92, 249, 73, 62, 0, 61, 13, 0, 162, 204, 100, 79, 64, 244, 62, 92, 150, 252, 233, 127, 33, 65, 161, 75, 243, 74, 139, 142, 42, 203, 54, 103, 73, 243, 173, 54, 251, 232, 168, 29, 132, 207, 35, 204, 56, 100, 59, 113, 69, 164, 108, 204, 193, 46, 31, 138, 216, 106, 139, 58, 0, 57, 232, 178, 1, 64, 141, 153, 34, 105, 9, 180, 100, 96, 79, 216, 129, 245, 244, 76, 154, 238, 205, 40, 116, 235, 78, 7, 238, 12, 173, 117, 220, 97, 208, 200, 29, 71, 216, 78, 172, 72, 106, 114, 56, 28, 190, 229, 27, 1, 208, 16, 123, 101, 207, 187, 58, 43, 51, 138, 40, 48, 247, 33, 80, 176, 19, 81, 69, 208, 11, 171, 208, 180, 0, 128, 224, 176, 177, 201, 193, 28, 136, 184, 3, 25, 119, 28, 193, 4, 176, 3, 197, 240, 142, 147, 243, 135, 199, 166, 148, 120, 104, 38, 13, 45, 166, 114, 157, 153, 244, 122, 155, 89, 145, 164, 183, 39, 96, 111, 202, 38, 52, 237, 187, 97, 72, 132, 177, 141, 61, 15, 77, 6, 96, 8, 32, 194, 90, 193, 138, 149, 109, 181, 240, 10, 216, 51, 143, 225, 97, 131, 60, 39, 68, 41, 55, 54, 84, 3, 0, 117, 68, 145, 184, 224, 11, 133, 45, 129, 153, 132, 166, 5, 128, 212, 104, 67, 132, 171, 118, 2, 192, 200, 0, 128, 108, 116, 130, 235, 20, 210, 194, 229, 65, 251, 243, 157, 206, 198, 137, 240, 211, 209, 49, 69, 6, 101, 23, 15, 219, 241, 59, 212, 197, 203, 75, 119, 111, 242, 155, 172, 77, 126, 25, 211, 4, 192, 95, 60, 55, 68, 188, 171, 229, 142, 196, 32, 60, 229, 7, 228, 242, 200, 216, 28, 229, 150, 165, 248, 27, 136, 48, 101, 212, 210, 200, 44, 31, 236, 153, 228, 88, 145, 198, 91, 127, 164, 133, 174, 66, 111, 216, 234, 45, 162, 95, 190, 158, 35, 13, 38, 248, 204, 174, 185, 252, 52, 17, 196, 113, 124, 38, 174, 84, 164, 166, 41, 143, 182, 1, 12, 175, 42, 65, 16, 75, 193, 70, 56, 152, 240, 8, 66, 72, 8, 120, 144, 34, 68, 14, 36, 42, 207, 152, 16, 12, 1, 73, 56, 233, 149, 40, 49, 49, 106, 248, 47, 102, 183, 11, 145, 214, 202, 74, 137, 138, 104, 210, 199, 5, 131, 135, 30, 122, 241, 32, 112, 49, 6, 127, 211, 97, 186, 45, 22, 221, 88, 123, 210, 111, 160, 205, 46, 179, 251, 253, 252, 126, 251, 155, 157, 71, 248, 72, 167, 196, 180, 18, 97, 142, 3, 75, 163, 242, 139, 179, 142, 154, 92, 203, 49, 122, 37, 188, 27, 201, 73, 219, 183, 215, 44, 252, 88, 223, 80, 102, 205, 216, 182, 3, 0, 10, 236, 86, 24, 58, 38, 219, 171, 161, 49, 29, 138, 92, 76, 90, 139, 80, 37, 128, 36, 188, 93, 31, 91, 43, 175, 131, 13, 191, 222, 106, 51, 70, 204, 28, 193, 55, 66, 119, 38, 190, 190, 97, 181, 17, 157, 166, 65, 207, 240, 149, 151, 144, 174, 74, 121, 53, 218, 9, 148, 229, 96, 160, 202, 118, 3, 140, 84, 103, 141, 0, 156, 96, 247, 195, 167, 221, 177, 186, 66, 231, 249, 123, 185, 93, 153, 204, 28, 162, 81, 111, 150, 93, 248, 229, 213, 59, 150, 126, 218, 47, 64, 25, 173, 152, 12, 235, 125, 62, 217, 43, 130, 106, 253, 198, 64, 129, 179, 205, 196, 7, 4, 237, 0, 156, 160, 238, 180, 173, 166, 173, 218, 124, 140, 5, 206, 205, 213, 90, 205, 173, 92, 123, 79, 195, 135, 236, 179, 57, 170, 56, 107, 34, 184, 61, 178, 228, 5, 0, 134, 16, 10, 20, 213, 223, 182, 16, 226, 1, 4, 205, 0, 188, 18, 31, 92, 224, 129, 67, 4, 220, 92, 149, 139, 228, 79, 236, 172, 179, 240, 95, 176, 85, 146, 119, 178, 132, 16, 115, 125, 196, 47, 114, 201, 203, 33, 67, 81, 86, 107, 54, 31, 16, 180, 3, 0, 1, 179, 57, 122, 215, 43, 103, 238, 236, 198, 75, 30, 62, 216, 43, 203, 74, 248, 18, 180, 45, 209, 135, 21, 49, 14, 65, 132, 215, 144, 35, 151, 47, 82, 52, 3, 0, 1, 247, 78, 174, 227, 142, 12, 88, 43, 67, 245, 113, 127, 89, 86, 140, 215, 192, 7, 215, 116, 200, 34, 23, 27, 147, 130, 17, 189, 115, 152, 141, 73, 26, 0, 180, 109, 91, 229, 56, 6, 54, 192, 159, 61, 125, 31, 91, 164, 203, 161, 201, 108, 226, 33, 57, 206, 125, 127, 72, 100, 226, 3, 130, 49, 2, 111, 134, 19, 108, 76, 210, 12, 240, 27, 127, 218, 249, 249, 211, 87, 162, 59, 133, 94, 111, 193, 67, 106, 80, 93, 101, 240, 139, 25, 92, 94, 250, 171, 200, 161, 96, 81, 22, 157, 160, 16, 148, 58, 0, 98, 254, 137, 225, 103, 208, 72, 141, 78, 12, 41, 192, 189, 29, 145, 112, 240, 144, 140, 198, 160, 97, 95, 111, 131, 9, 10, 74, 21, 0, 252, 109, 3, 60, 253, 44, 124, 176, 167, 242, 134, 154, 187, 8, 130, 252, 12, 85, 85, 102, 37, 213, 228, 179, 69, 75, 170, 25, 240, 80, 127, 216, 40, 137, 79, 63, 175, 55, 177, 160, 247, 96, 70, 117, 148, 112, 126, 126, 138, 0, 136, 249, 179, 244, 243, 167, 207, 229, 13, 223, 210, 176, 238, 77, 5, 0, 185, 96, 24, 26, 88, 75, 168, 190, 248, 122, 15, 53, 91, 216, 172, 250, 23, 74, 9, 32, 234, 175, 86, 191, 204, 253, 99, 210, 183, 241, 213, 93, 58, 50, 64, 227, 31, 13, 175, 172, 44, 169, 213, 39, 30, 82, 216, 129, 9, 74, 19, 128, 234, 207, 58, 95, 50, 127, 49, 148, 117, 37, 109, 0, 224, 111, 26, 53, 174, 174, 194, 184, 167, 246, 189, 159, 0, 244, 195, 196, 149, 182, 71, 144, 185, 88, 11, 239, 127, 190, 75, 229, 79, 170, 218, 33, 236, 65, 105, 2, 176, 156, 233, 8, 211, 55, 92, 36, 98, 160, 10, 36, 213, 126, 179, 153, 184, 210, 3, 128, 135, 39, 246, 230, 246, 162, 250, 78, 245, 57, 185, 246, 78, 165, 11, 0, 209, 159, 212, 245, 239, 252, 47, 217, 127, 128, 63, 1, 64, 160, 216, 167, 27, 190, 18, 254, 148, 112, 204, 26, 36, 30, 242, 99, 245, 148, 91, 109, 163, 61, 3, 232, 111, 197, 233, 38, 84, 110, 164, 29, 0, 97, 16, 251, 66, 236, 211, 67, 98, 194, 84, 241, 55, 75, 60, 102, 237, 19, 227, 192, 166, 113, 19, 189, 159, 102, 128, 138, 17, 171, 125, 164, 135, 148, 89, 173, 35, 165, 164, 127, 193, 110, 191, 137, 98, 87, 247, 88, 237, 118, 235, 211, 113, 226, 142, 53, 110, 128, 51, 119, 137, 231, 192, 13, 247, 47, 140, 88, 251, 85, 55, 184, 114, 222, 218, 55, 213, 247, 164, 236, 50, 65, 90, 1, 26, 243, 36, 65, 55, 136, 30, 233, 164, 150, 25, 60, 37, 8, 186, 6, 196, 19, 136, 26, 116, 146, 32, 52, 245, 144, 45, 126, 147, 153, 22, 104, 92, 198, 50, 12, 24, 231, 238, 11, 146, 206, 142, 1, 144, 19, 61, 207, 147, 64, 66, 119, 41, 217, 210, 12, 80, 44, 9, 197, 141, 21, 157, 210, 118, 119, 79, 69, 147, 180, 121, 85, 189, 182, 98, 90, 218, 222, 150, 174, 207, 147, 45, 78, 84, 166, 219, 20, 166, 27, 161, 1, 3, 104, 156, 146, 58, 117, 253, 60, 99, 112, 98, 48, 15, 174, 0, 130, 199, 38, 237, 0, 63, 168, 45, 99, 21, 213, 129, 40, 12, 79, 112, 96, 226, 237, 21, 210, 5, 99, 163, 229, 150, 22, 194, 138, 105, 5, 69, 16, 162, 85, 36, 54, 194, 150, 34, 110, 167, 178, 168, 213, 194, 46, 139, 203, 178, 246, 11, 187, 237, 240, 151, 201, 35, 204, 11, 92, 200, 155, 220, 99, 226, 36, 123, 183, 138, 183, 187, 163, 112, 156, 113, 78, 230, 227, 255, 231, 76, 166, 118, 34, 128, 209, 154, 200, 123, 31, 142, 0, 134, 250, 110, 17, 73, 234, 42, 142, 222, 58, 87, 192, 37, 128, 113, 83, 247, 217, 61, 1, 119, 215, 50, 210, 9, 198, 156, 43, 197, 173, 163, 56, 150, 101, 88, 24, 192, 3, 6, 139, 13, 143, 209, 31, 181, 0, 49, 203, 82, 141, 0, 92, 112, 116, 28, 166, 21, 48, 230, 136, 49, 44, 103, 0, 91, 194, 182, 111, 117, 66, 36, 219, 67, 174, 224, 151, 217, 84, 171, 82, 4, 224, 238, 5, 216, 57, 71, 156, 181, 246, 1, 175, 38, 67, 45, 112, 15, 202, 59, 161, 242, 158, 1, 220, 237, 17, 243, 86, 230, 185, 65, 130, 192, 106, 230, 0, 165, 128, 0, 6, 77, 201, 88, 84, 188, 12, 127, 19, 128, 53, 17, 226, 4, 251, 211, 6, 130, 220, 1, 87, 32, 174, 123, 168, 184, 122, 87, 178, 198, 18, 138, 207, 152, 190, 123, 148, 110, 56, 9, 82, 210, 0, 52, 62, 19, 32, 9, 170, 122, 164, 152, 2, 71, 240, 151, 3, 236, 39, 120, 207, 10, 149, 109, 38, 64, 213, 7, 6, 19, 114, 217, 101, 122, 133, 81, 7, 188, 235, 200, 76, 144, 33, 9, 50, 215, 130, 36, 101, 241, 68, 132, 252, 201, 148, 97, 113, 128, 182, 15, 238, 173, 48, 108, 225, 180, 67, 162, 95, 190, 163, 17, 80, 221, 137, 155, 242, 37, 149, 173, 207, 158, 47, 242, 42, 89, 34, 22, 239, 185, 221, 4, 90, 179, 160, 64, 46, 133, 172, 48, 192, 47, 130, 174, 8, 229, 186, 16, 21, 160, 174, 39, 69, 70, 139, 67, 109, 107, 4, 80, 215, 34, 147, 194, 228, 121, 67, 3, 176, 69, 15, 74, 57, 236, 219, 98, 68, 48, 64, 178, 13, 194, 194, 0, 213, 61, 20, 135, 125, 239, 10, 10, 194, 201, 78, 185, 198, 138, 192, 190, 158, 5, 240, 42, 53, 0, 213, 10, 39, 207, 53, 128, 83, 1, 149, 206, 247, 131, 153, 80, 182, 156, 6, 239, 105, 78, 81, 0, 227, 245, 108, 155, 111, 110, 132, 82, 176, 218, 23, 128, 136, 109, 5, 20, 0, 206, 243, 186, 107, 7, 228, 121, 114, 240, 229, 130, 172, 22, 237, 154, 113, 97, 110, 126, 58, 70, 121, 134, 43, 1, 228, 1, 28, 124, 99, 28, 206, 10, 80, 137, 233, 51, 37, 224, 160, 207, 249, 251, 160, 79, 158, 38, 25, 44, 222, 178, 11, 184, 177, 225, 10, 162, 223, 163, 255, 163, 36, 167, 102, 139, 253, 190, 3, 142, 101, 245, 10, 11, 216, 1, 49, 239, 79, 217, 129, 199, 113, 247, 81, 11, 32, 111, 7, 232, 197, 65, 107, 168, 98, 248, 119, 23, 128, 91, 15, 113, 103, 155, 21, 65, 187, 142, 158, 82, 128, 95, 74, 1, 216, 180, 15, 106, 49, 184, 126, 157, 20, 3, 184, 1, 176, 50, 101, 64, 193, 42, 167, 0, 209, 217, 110, 192, 54, 229, 26, 20, 244, 219, 97, 45, 128, 238, 52, 3, 104, 12, 144, 180, 186, 145, 102, 177, 73, 5, 49, 7, 196, 254, 170, 50, 100, 239, 187, 177, 245, 198, 34, 119, 247, 96, 205, 168, 155, 218, 89, 157, 83, 247, 77, 202, 233, 114, 108, 125, 125, 164, 0, 236, 145, 102, 62, 55, 50, 123, 107, 251, 213, 195, 120, 60, 182, 38, 68, 156, 42, 244, 106, 119, 85, 199, 114, 245, 250, 5, 1, 218, 166, 105, 150, 210, 144, 207, 48, 204, 164, 203, 74, 151, 152, 106, 78, 191, 203, 9, 99, 62, 231, 239, 172, 198, 98, 49, 106, 50, 90, 255, 95, 175, 100, 236, 231, 168, 142, 133, 90, 116, 9, 161, 44, 14, 160, 111, 145, 58, 100, 45, 76, 186, 58, 230, 51, 191, 63, 60, 76, 27, 251, 49, 240, 223, 93, 203, 255, 12, 59, 24, 117, 192, 168, 3, 70, 29, 48, 234, 128, 81, 7, 140, 58, 96, 212, 1, 84, 7, 0, 13, 207, 230, 190, 92, 185, 148, 184, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130} +var WailsLogoBlackTransparent = []byte{137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 128, 0, 0, 0, 128, 8, 3, 0, 0, 0, 244, 224, 145, 249, 0, 0, 2, 250, 80, 76, 84, 69, 0, 0, 0, 227, 50, 50, 36, 32, 32, 201, 41, 45, 29, 29, 29, 227, 50, 49, 153, 23, 31, 225, 45, 46, 30, 30, 30, 198, 33, 33, 226, 47, 47, 227, 50, 50, 30, 30, 30, 226, 50, 50, 206, 41, 43, 30, 30, 30, 183, 31, 36, 185, 32, 37, 30, 30, 30, 228, 50, 50, 30, 30, 30, 30, 30, 30, 219, 47, 47, 30, 30, 30, 228, 50, 50, 28, 28, 28, 192, 35, 38, 173, 27, 33, 187, 33, 37, 227, 50, 50, 228, 50, 50, 30, 30, 30, 205, 40, 43, 215, 44, 45, 208, 42, 44, 178, 29, 35, 29, 29, 29, 183, 31, 36, 29, 29, 29, 33, 33, 33, 197, 37, 40, 210, 43, 44, 197, 37, 40, 30, 30, 30, 29, 29, 29, 29, 29, 29, 226, 49, 49, 225, 49, 49, 220, 47, 47, 30, 30, 30, 29, 29, 29, 30, 30, 30, 29, 29, 29, 192, 36, 39, 29, 29, 29, 167, 24, 31, 212, 43, 45, 206, 41, 43, 29, 29, 29, 30, 30, 30, 222, 48, 48, 30, 30, 30, 163, 24, 27, 119, 5, 16, 204, 40, 43, 196, 37, 40, 178, 29, 35, 177, 29, 35, 227, 50, 50, 164, 23, 30, 226, 49, 49, 217, 45, 47, 162, 23, 30, 172, 27, 33, 228, 50, 50, 227, 49, 49, 200, 38, 40, 30, 30, 30, 29, 29, 29, 29, 29, 29, 31, 31, 31, 150, 18, 26, 166, 24, 31, 227, 50, 49, 178, 30, 34, 228, 50, 50, 190, 34, 38, 30, 30, 30, 205, 40, 43, 30, 30, 30, 207, 41, 43, 176, 28, 34, 226, 49, 49, 195, 37, 40, 30, 30, 30, 199, 38, 41, 30, 30, 30, 127, 8, 19, 28, 28, 28, 210, 34, 36, 214, 45, 46, 200, 38, 41, 131, 11, 21, 190, 34, 38, 227, 49, 49, 190, 34, 38, 191, 34, 39, 192, 35, 39, 186, 32, 37, 226, 49, 50, 30, 30, 30, 216, 46, 46, 171, 27, 32, 199, 37, 41, 146, 16, 26, 141, 14, 25, 211, 47, 48, 120, 0, 3, 136, 15, 25, 158, 21, 29, 203, 39, 42, 218, 46, 47, 208, 42, 43, 156, 20, 28, 227, 49, 49, 191, 34, 39, 172, 27, 33, 184, 31, 36, 30, 30, 30, 204, 40, 42, 208, 42, 44, 120, 5, 17, 207, 41, 44, 204, 41, 44, 186, 32, 37, 148, 17, 25, 227, 50, 49, 224, 48, 49, 227, 49, 49, 151, 18, 26, 228, 50, 50, 125, 7, 18, 156, 20, 28, 130, 4, 17, 152, 19, 27, 177, 29, 34, 151, 18, 26, 229, 50, 51, 204, 40, 43, 189, 34, 38, 213, 44, 45, 227, 49, 49, 126, 8, 19, 145, 16, 24, 130, 9, 20, 162, 23, 29, 232, 52, 51, 254, 253, 253, 219, 75, 77, 218, 46, 46, 196, 37, 40, 184, 32, 36, 211, 43, 44, 152, 19, 27, 201, 39, 41, 165, 24, 30, 175, 28, 34, 123, 7, 18, 182, 31, 35, 170, 26, 32, 212, 43, 45, 125, 7, 18, 172, 27, 33, 247, 217, 217, 127, 8, 19, 141, 14, 23, 198, 37, 40, 118, 4, 16, 220, 196, 199, 155, 61, 69, 226, 108, 109, 233, 151, 151, 188, 111, 117, 178, 86, 92, 130, 9, 20, 119, 5, 16, 122, 6, 18, 138, 13, 23, 238, 223, 225, 197, 142, 146, 237, 173, 174, 139, 19, 28, 220, 47, 48, 31, 31, 31, 227, 50, 50, 215, 45, 46, 219, 46, 47, 224, 48, 49, 213, 44, 45, 221, 47, 48, 209, 42, 44, 33, 33, 33, 222, 48, 48, 246, 54, 54, 207, 41, 43, 205, 40, 43, 192, 34, 38, 217, 45, 46, 226, 49, 49, 211, 42, 44, 200, 38, 41, 194, 36, 40, 190, 33, 38, 232, 51, 51, 203, 40, 42, 188, 33, 37, 186, 32, 37, 229, 50, 50, 197, 37, 40, 184, 32, 36, 131, 10, 21, 180, 29, 35, 169, 25, 32, 178, 29, 34, 199, 38, 41, 182, 31, 35, 123, 6, 17, 236, 51, 51, 174, 27, 33, 172, 26, 32, 164, 23, 30, 139, 13, 23, 128, 7, 18, 136, 11, 21, 242, 52, 53, 176, 28, 34, 202, 38, 41, 167, 24, 31, 143, 14, 24, 153, 18, 27, 148, 16, 25, 238, 52, 52, 223, 45, 47, 161, 22, 30, 219, 43, 46, 206, 38, 42, 199, 34, 39, 215, 41, 44, 158, 21, 28, 195, 35, 39, 183, 30, 35, 160, 21, 29, 250, 55, 55, 253, 55, 55, 105, 176, 83, 104, 0, 0, 0, 193, 116, 82, 78, 83, 0, 254, 5, 5, 8, 250, 7, 11, 252, 8, 27, 194, 246, 168, 18, 249, 251, 29, 241, 54, 233, 212, 23, 221, 170, 20, 252, 252, 249, 246, 225, 186, 177, 33, 252, 250, 56, 50, 38, 14, 253, 248, 248, 175, 156, 149, 89, 65, 251, 204, 194, 162, 127, 43, 25, 252, 251, 249, 226, 168, 124, 92, 22, 253, 247, 231, 208, 90, 83, 82, 38, 249, 248, 247, 234, 147, 146, 142, 114, 85, 31, 246, 239, 238, 229, 207, 201, 181, 160, 135, 119, 102, 98, 81, 74, 71, 66, 52, 44, 254, 251, 249, 246, 245, 229, 191, 180, 136, 126, 110, 107, 76, 74, 59, 37, 26, 10, 253, 252, 245, 241, 168, 168, 168, 159, 157, 136, 112, 99, 95, 88, 247, 243, 227, 221, 220, 214, 202, 187, 181, 133, 105, 48, 18, 15, 239, 233, 219, 215, 211, 198, 180, 151, 90, 74, 63, 47, 250, 245, 244, 239, 238, 233, 207, 197, 194, 191, 173, 171, 150, 139, 123, 119, 243, 211, 196, 108, 88, 250, 244, 243, 238, 235, 232, 231, 229, 190, 139, 246, 242, 239, 236, 219, 38, 121, 14, 209, 0, 0, 13, 162, 73, 68, 65, 84, 120, 218, 236, 152, 87, 76, 147, 97, 20, 134, 91, 177, 24, 52, 154, 18, 19, 98, 4, 13, 208, 144, 80, 46, 132, 27, 34, 77, 8, 171, 64, 41, 112, 131, 130, 33, 160, 33, 70, 89, 130, 1, 65, 209, 168, 64, 84, 196, 129, 162, 56, 113, 239, 189, 247, 30, 233, 78, 41, 180, 20, 126, 104, 75, 203, 42, 171, 12, 129, 150, 173, 38, 158, 239, 231, 47, 85, 131, 8, 13, 200, 133, 188, 225, 134, 64, 250, 62, 223, 251, 157, 239, 156, 3, 164, 25, 205, 104, 70, 51, 154, 209, 140, 254, 19, 217, 4, 146, 166, 85, 254, 33, 14, 164, 105, 148, 77, 200, 82, 127, 210, 52, 202, 63, 66, 123, 136, 52, 125, 10, 12, 89, 82, 180, 136, 68, 178, 32, 77, 131, 144, 233, 234, 253, 88, 81, 196, 220, 233, 241, 7, 157, 159, 79, 209, 98, 193, 41, 211, 226, 111, 69, 34, 205, 217, 184, 180, 27, 227, 112, 60, 73, 211, 36, 215, 211, 156, 110, 50, 5, 91, 132, 96, 44, 44, 44, 44, 173, 172, 172, 44, 73, 255, 72, 112, 124, 155, 67, 9, 221, 24, 133, 220, 186, 223, 129, 180, 153, 244, 111, 4, 135, 28, 22, 254, 246, 230, 41, 225, 248, 100, 236, 248, 249, 145, 31, 219, 184, 111, 138, 137, 217, 100, 61, 37, 158, 191, 23, 153, 67, 200, 74, 56, 62, 133, 163, 36, 71, 230, 167, 50, 163, 179, 147, 147, 110, 39, 174, 90, 149, 152, 25, 181, 198, 125, 193, 164, 24, 207, 154, 53, 90, 93, 91, 30, 73, 79, 203, 63, 119, 246, 204, 153, 168, 121, 152, 22, 142, 207, 225, 40, 233, 225, 126, 225, 5, 154, 242, 190, 190, 202, 220, 13, 201, 107, 156, 108, 38, 251, 57, 32, 203, 181, 96, 121, 248, 240, 189, 119, 133, 59, 242, 30, 61, 186, 182, 239, 216, 177, 240, 189, 75, 180, 24, 178, 39, 43, 47, 209, 106, 6, 251, 250, 20, 225, 96, 238, 126, 116, 18, 125, 143, 60, 121, 114, 248, 222, 189, 194, 194, 91, 183, 222, 62, 124, 248, 240, 245, 235, 184, 184, 12, 93, 243, 151, 47, 93, 93, 157, 157, 93, 157, 84, 46, 134, 201, 40, 28, 228, 175, 28, 28, 210, 132, 223, 204, 98, 66, 238, 147, 171, 163, 183, 234, 247, 120, 123, 215, 215, 183, 180, 180, 168, 213, 106, 29, 168, 25, 244, 5, 105, 197, 54, 10, 25, 132, 252, 57, 152, 239, 141, 59, 209, 78, 94, 164, 41, 208, 218, 55, 45, 224, 15, 26, 97, 192, 1, 154, 195, 174, 92, 34, 115, 248, 124, 25, 242, 39, 119, 207, 207, 79, 159, 178, 22, 120, 214, 27, 101, 96, 2, 192, 9, 208, 241, 101, 124, 144, 12, 252, 41, 221, 17, 54, 164, 41, 212, 225, 250, 250, 61, 166, 4, 192, 94, 167, 11, 187, 194, 226, 243, 197, 200, 95, 38, 227, 80, 176, 149, 174, 83, 58, 3, 45, 11, 213, 120, 21, 32, 0, 93, 70, 179, 78, 157, 177, 98, 155, 152, 47, 68, 254, 124, 228, 175, 84, 110, 52, 243, 131, 9, 89, 224, 26, 227, 4, 233, 111, 213, 40, 130, 22, 117, 70, 134, 26, 66, 8, 139, 103, 241, 133, 60, 49, 1, 64, 161, 104, 119, 78, 110, 195, 3, 89, 90, 90, 25, 101, 9, 223, 64, 33, 234, 226, 32, 253, 150, 45, 91, 182, 196, 125, 90, 225, 227, 38, 230, 241, 132, 4, 0, 153, 223, 122, 192, 198, 188, 252, 189, 242, 189, 188, 142, 28, 29, 223, 212, 58, 187, 7, 153, 111, 201, 120, 246, 242, 229, 94, 15, 49, 79, 202, 19, 10, 137, 43, 224, 99, 199, 93, 205, 188, 255, 180, 188, 125, 121, 121, 121, 59, 64, 119, 238, 100, 101, 101, 221, 191, 159, 29, 29, 205, 100, 6, 164, 166, 158, 219, 228, 228, 228, 238, 238, 96, 109, 237, 181, 96, 142, 149, 5, 81, 136, 123, 212, 207, 94, 125, 120, 250, 224, 197, 69, 55, 30, 87, 202, 35, 0, 64, 28, 178, 39, 196, 102, 105, 86, 216, 103, 194, 26, 7, 154, 154, 58, 144, 170, 65, 182, 182, 108, 118, 65, 65, 193, 149, 240, 240, 220, 220, 220, 147, 39, 97, 160, 36, 110, 216, 96, 191, 61, 50, 50, 52, 52, 212, 51, 244, 213, 211, 247, 23, 46, 60, 120, 206, 234, 151, 130, 191, 9, 128, 172, 116, 201, 59, 227, 133, 79, 101, 51, 20, 112, 172, 122, 235, 215, 175, 134, 166, 38, 0, 104, 108, 104, 107, 171, 209, 212, 13, 85, 41, 42, 203, 75, 74, 6, 7, 85, 125, 114, 121, 123, 123, 69, 49, 72, 34, 145, 136, 122, 47, 62, 184, 112, 225, 197, 197, 117, 235, 4, 92, 174, 212, 148, 128, 76, 73, 15, 235, 218, 122, 227, 126, 26, 170, 105, 51, 9, 12, 6, 67, 211, 114, 144, 45, 18, 141, 6, 16, 212, 42, 5, 80, 0, 70, 89, 153, 170, 182, 86, 14, 20, 18, 81, 233, 186, 139, 31, 159, 227, 246, 92, 34, 1, 188, 8, 57, 110, 65, 186, 78, 67, 245, 114, 191, 44, 39, 146, 89, 10, 216, 218, 24, 4, 9, 64, 4, 144, 193, 112, 8, 154, 186, 42, 72, 1, 0, 22, 47, 46, 43, 115, 118, 118, 150, 203, 43, 42, 42, 138, 29, 139, 123, 233, 224, 47, 16, 152, 0, 144, 63, 133, 173, 238, 234, 28, 104, 106, 24, 170, 203, 205, 140, 49, 155, 0, 1, 116, 252, 2, 96, 74, 0, 34, 0, 0, 252, 26, 214, 137, 192, 255, 215, 4, 148, 241, 234, 102, 4, 80, 221, 86, 53, 168, 242, 181, 223, 61, 199, 44, 130, 134, 32, 34, 129, 134, 134, 182, 26, 184, 1, 34, 1, 240, 71, 87, 128, 238, 0, 7, 16, 137, 68, 165, 35, 0, 66, 28, 128, 195, 200, 80, 127, 233, 234, 252, 218, 212, 88, 83, 87, 89, 214, 91, 154, 115, 106, 227, 92, 51, 8, 130, 218, 130, 140, 53, 64, 3, 81, 145, 236, 236, 22, 35, 193, 13, 212, 202, 127, 7, 144, 26, 1, 56, 172, 176, 250, 102, 2, 160, 170, 178, 76, 94, 204, 21, 178, 14, 120, 158, 55, 131, 64, 131, 178, 135, 240, 135, 134, 134, 80, 250, 40, 126, 120, 8, 144, 63, 4, 128, 106, 96, 4, 192, 84, 2, 32, 25, 101, 133, 183, 26, 7, 232, 0, 128, 242, 50, 185, 68, 196, 21, 43, 101, 199, 67, 22, 78, 148, 128, 185, 2, 196, 102, 179, 109, 109, 209, 67, 172, 82, 160, 103, 168, 130, 55, 216, 43, 1, 79, 73, 236, 31, 0, 196, 100, 59, 239, 22, 29, 2, 48, 116, 52, 104, 20, 37, 170, 118, 73, 41, 151, 39, 86, 106, 177, 132, 249, 254, 115, 240, 166, 62, 110, 130, 252, 212, 115, 169, 169, 169, 1, 1, 76, 38, 51, 58, 58, 58, 59, 59, 59, 57, 57, 57, 41, 41, 41, 20, 20, 233, 219, 31, 11, 254, 163, 0, 112, 114, 226, 188, 213, 8, 96, 192, 80, 13, 0, 139, 93, 124, 24, 116, 150, 155, 219, 146, 37, 176, 162, 5, 47, 90, 182, 224, 15, 43, 174, 229, 108, 203, 95, 101, 5, 115, 103, 172, 201, 180, 230, 114, 143, 15, 74, 64, 244, 27, 0, 159, 197, 142, 171, 71, 0, 248, 35, 168, 171, 108, 239, 239, 151, 234, 101, 24, 214, 221, 173, 213, 118, 23, 21, 97, 17, 135, 198, 127, 19, 99, 55, 177, 53, 219, 122, 124, 140, 1, 24, 1, 208, 48, 182, 27, 8, 138, 131, 43, 232, 26, 6, 176, 243, 245, 101, 8, 4, 44, 55, 10, 18, 74, 1, 163, 140, 130, 112, 36, 109, 45, 40, 45, 45, 221, 203, 203, 43, 221, 218, 164, 209, 8, 208, 13, 154, 8, 160, 13, 16, 1, 16, 9, 240, 93, 12, 77, 213, 91, 227, 116, 198, 71, 16, 191, 225, 113, 76, 204, 238, 213, 203, 140, 242, 247, 95, 182, 122, 217, 66, 139, 223, 1, 214, 62, 185, 87, 120, 235, 209, 62, 208, 181, 107, 55, 110, 220, 188, 121, 115, 21, 232, 250, 245, 168, 177, 23, 170, 221, 219, 244, 62, 224, 255, 51, 0, 159, 190, 220, 208, 81, 109, 27, 166, 30, 121, 4, 190, 246, 187, 108, 198, 49, 0, 143, 166, 175, 61, 123, 248, 221, 142, 107, 199, 6, 26, 135, 160, 216, 203, 203, 203, 161, 122, 69, 62, 127, 35, 200, 209, 231, 252, 2, 32, 102, 209, 12, 168, 115, 217, 134, 53, 119, 118, 26, 112, 0, 185, 132, 113, 10, 122, 192, 248, 118, 67, 171, 244, 252, 212, 232, 172, 29, 126, 5, 154, 193, 246, 222, 222, 10, 121, 113, 206, 223, 8, 124, 244, 116, 32, 32, 0, 164, 66, 183, 120, 3, 222, 185, 53, 236, 48, 226, 17, 148, 171, 42, 4, 122, 222, 231, 16, 87, 132, 48, 206, 209, 188, 32, 237, 28, 51, 57, 51, 209, 215, 69, 212, 163, 228, 221, 29, 251, 223, 47, 187, 24, 64, 48, 146, 128, 56, 118, 121, 117, 3, 248, 215, 212, 81, 217, 93, 80, 131, 168, 13, 56, 87, 56, 10, 120, 74, 14, 244, 128, 137, 253, 133, 62, 199, 218, 105, 205, 227, 80, 251, 189, 87, 61, 73, 99, 42, 229, 106, 143, 135, 17, 64, 76, 103, 119, 192, 220, 64, 99, 67, 97, 23, 212, 137, 191, 194, 18, 85, 133, 72, 32, 21, 202, 180, 216, 202, 131, 171, 109, 38, 188, 27, 45, 8, 76, 217, 109, 243, 199, 164, 28, 54, 165, 236, 138, 58, 209, 227, 65, 12, 67, 225, 122, 26, 225, 143, 150, 23, 187, 32, 67, 35, 0, 148, 213, 226, 0, 124, 50, 7, 211, 46, 57, 224, 25, 72, 50, 95, 38, 95, 167, 152, 93, 81, 73, 145, 246, 215, 79, 236, 189, 202, 112, 164, 27, 219, 0, 207, 45, 190, 3, 236, 9, 255, 146, 50, 234, 114, 124, 20, 213, 22, 227, 0, 28, 50, 66, 32, 239, 135, 129, 96, 166, 142, 90, 59, 197, 48, 179, 147, 50, 55, 36, 158, 244, 189, 236, 226, 220, 94, 12, 213, 95, 10, 222, 165, 4, 128, 148, 23, 107, 219, 48, 108, 143, 251, 171, 92, 168, 141, 26, 52, 138, 138, 69, 92, 30, 0, 112, 0, 129, 140, 105, 149, 9, 59, 83, 44, 38, 184, 165, 7, 48, 163, 179, 238, 220, 78, 244, 203, 189, 18, 111, 7, 31, 44, 71, 59, 161, 28, 223, 135, 24, 142, 142, 142, 198, 87, 200, 163, 211, 8, 127, 124, 101, 112, 86, 181, 95, 14, 71, 143, 0, 7, 16, 203, 0, 0, 103, 80, 66, 49, 156, 94, 141, 15, 132, 241, 114, 88, 223, 86, 208, 106, 170, 240, 85, 8, 215, 240, 58, 0, 4, 196, 44, 68, 1, 172, 103, 185, 121, 80, 27, 145, 61, 238, 143, 22, 22, 121, 241, 182, 204, 240, 190, 197, 42, 57, 62, 11, 101, 208, 135, 71, 186, 177, 114, 229, 193, 9, 45, 40, 78, 126, 125, 26, 90, 93, 29, 218, 70, 236, 42, 137, 149, 148, 88, 71, 192, 223, 145, 78, 95, 47, 224, 201, 120, 241, 13, 104, 103, 82, 24, 127, 1, 240, 74, 67, 239, 15, 170, 98, 43, 36, 2, 174, 80, 172, 108, 253, 86, 212, 218, 10, 95, 184, 190, 125, 111, 93, 26, 226, 58, 254, 61, 205, 221, 175, 132, 70, 197, 239, 214, 180, 17, 226, 254, 12, 6, 221, 81, 196, 147, 41, 149, 250, 75, 46, 192, 104, 58, 62, 242, 103, 72, 79, 185, 223, 134, 153, 45, 2, 0, 254, 202, 136, 136, 165, 193, 9, 75, 71, 148, 16, 156, 48, 207, 51, 112, 34, 25, 208, 168, 196, 78, 108, 220, 72, 99, 99, 125, 24, 162, 30, 189, 76, 95, 122, 245, 84, 100, 84, 74, 114, 165, 130, 10, 246, 68, 252, 40, 28, 71, 1, 221, 213, 250, 114, 41, 3, 111, 3, 193, 59, 253, 3, 29, 206, 187, 186, 46, 52, 201, 213, 213, 97, 66, 183, 64, 165, 42, 140, 43, 169, 179, 139, 139, 139, 92, 210, 175, 215, 11, 114, 78, 216, 223, 221, 181, 201, 1, 122, 156, 85, 102, 159, 194, 174, 196, 120, 124, 84, 28, 30, 30, 208, 70, 31, 247, 139, 28, 185, 168, 13, 4, 31, 220, 56, 138, 223, 4, 9, 126, 208, 102, 254, 46, 9, 132, 97, 28, 127, 95, 228, 56, 50, 12, 34, 184, 41, 67, 27, 29, 202, 37, 112, 144, 72, 8, 7, 215, 168, 73, 104, 17, 34, 155, 130, 38, 49, 154, 4, 149, 134, 64, 205, 177, 165, 169, 63, 227, 245, 39, 94, 200, 157, 118, 130, 173, 110, 210, 162, 120, 184, 40, 244, 220, 251, 88, 167, 114, 147, 220, 125, 254, 129, 239, 243, 189, 247, 121, 223, 231, 199, 225, 80, 112, 19, 248, 214, 167, 147, 105, 47, 243, 14, 198, 205, 213, 211, 105, 82, 55, 6, 6, 60, 28, 158, 155, 137, 198, 171, 72, 124, 227, 16, 228, 96, 141, 105, 35, 150, 53, 11, 194, 70, 17, 252, 236, 3, 95, 221, 158, 170, 234, 129, 162, 239, 14, 141, 47, 225, 191, 82, 3, 104, 31, 245, 225, 102, 190, 29, 147, 147, 140, 146, 128, 75, 64, 41, 132, 160, 29, 164, 121, 65, 216, 218, 48, 2, 189, 221, 209, 245, 110, 228, 246, 241, 201, 122, 215, 121, 31, 153, 6, 58, 61, 227, 243, 99, 125, 132, 238, 32, 12, 5, 179, 218, 10, 226, 194, 200, 120, 3, 98, 101, 94, 16, 92, 27, 69, 80, 106, 151, 146, 96, 124, 23, 76, 88, 115, 29, 81, 207, 254, 237, 131, 126, 176, 159, 119, 17, 215, 199, 40, 88, 91, 188, 66, 16, 194, 192, 187, 29, 222, 52, 25, 78, 76, 227, 214, 236, 22, 161, 71, 227, 250, 216, 32, 182, 148, 11, 120, 249, 221, 185, 161, 151, 33, 148, 23, 4, 108, 10, 29, 64, 242, 53, 209, 62, 232, 47, 134, 68, 190, 165, 58, 14, 14, 4, 70, 25, 194, 67, 96, 133, 52, 228, 163, 253, 250, 147, 207, 195, 191, 207, 143, 83, 178, 160, 149, 9, 16, 150, 153, 128, 242, 102, 65, 128, 9, 65, 36, 182, 114, 202, 245, 85, 44, 140, 184, 170, 82, 104, 63, 22, 53, 10, 120, 121, 238, 165, 43, 8, 76, 211, 176, 32, 216, 198, 142, 161, 175, 130, 125, 208, 71, 251, 138, 2, 94, 113, 83, 184, 23, 147, 189, 84, 88, 163, 175, 97, 131, 98, 155, 126, 147, 235, 163, 125, 220, 84, 66, 0, 240, 183, 200, 32, 62, 156, 13, 229, 53, 134, 242, 108, 46, 95, 120, 206, 37, 27, 86, 136, 168, 95, 95, 181, 111, 64, 251, 7, 126, 2, 136, 207, 217, 252, 182, 21, 151, 57, 79, 92, 178, 65, 63, 85, 85, 67, 120, 250, 11, 125, 243, 222, 197, 137, 193, 131, 223, 109, 133, 36, 185, 163, 81, 209, 6, 253, 70, 29, 245, 77, 251, 8, 156, 129, 135, 56, 137, 169, 111, 97, 31, 207, 160, 32, 17, 39, 65, 253, 74, 168, 178, 148, 125, 108, 9, 202, 132, 35, 226, 44, 47, 169, 49, 234, 155, 246, 87, 2, 208, 210, 196, 81, 196, 95, 1, 237, 79, 129, 122, 31, 110, 63, 74, 28, 116, 240, 49, 208, 16, 148, 68, 0, 237, 7, 91, 15, 45, 251, 48, 192, 33, 89, 90, 78, 156, 115, 70, 28, 135, 216, 15, 178, 30, 108, 63, 166, 3, 110, 122, 51, 208, 12, 40, 42, 188, 122, 12, 172, 226, 31, 127, 252, 248, 10, 216, 230, 198, 1, 254, 100, 240, 209, 44, 8, 226, 21, 42, 33, 128, 23, 9, 72, 192, 0, 136, 13, 130, 53, 110, 52, 115, 0, 59, 31, 39, 59, 17, 128, 153, 97, 20, 140, 2, 0, 113, 100, 172, 194, 48, 8, 69, 209, 71, 112, 232, 80, 40, 136, 82, 156, 178, 136, 25, 170, 67, 99, 112, 104, 201, 39, 164, 205, 154, 37, 148, 124, 64, 191, 33, 191, 246, 70, 255, 170, 134, 130, 74, 233, 144, 118, 201, 25, 174, 92, 148, 235, 125, 188, 191, 41, 2, 239, 35, 153, 252, 46, 247, 240, 197, 127, 198, 17, 66, 10, 216, 142, 34, 234, 102, 8, 39, 126, 170, 224, 58, 109, 58, 5, 163, 213, 67, 15, 173, 53, 122, 134, 136, 210, 218, 232, 70, 164, 52, 49, 88, 99, 100, 26, 183, 189, 118, 186, 133, 156, 209, 214, 231, 82, 223, 9, 172, 70, 81, 68, 42, 225, 228, 145, 77, 80, 123, 196, 91, 250, 175, 9, 22, 47, 10, 98, 156, 220, 35, 238, 31, 241, 65, 85, 250, 3, 14, 249, 184, 79, 138, 11, 220, 193, 234, 10, 61, 67, 164, 83, 21, 148, 41, 65, 23, 141, 121, 130, 47, 5, 152, 76, 97, 99, 240, 199, 84, 168, 231, 161, 192, 156, 237, 95, 82, 191, 67, 244, 158, 147, 245, 59, 112, 47, 118, 171, 29, 215, 65, 24, 8, 90, 145, 11, 23, 150, 44, 161, 32, 139, 138, 6, 133, 2, 40, 248, 40, 5, 136, 35, 240, 233, 80, 154, 40, 202, 1, 56, 67, 174, 54, 165, 111, 245, 214, 122, 47, 54, 148, 238, 223, 40, 10, 90, 203, 222, 157, 29, 47, 35, 180, 109, 242, 101, 43, 173, 54, 127, 113, 144, 19, 22, 215, 151, 39, 176, 83, 193, 38, 119, 113, 22, 65, 69, 78, 16, 194, 195, 64, 200, 52, 149, 105, 192, 16, 36, 177, 109, 170, 51, 17, 122, 250, 135, 248, 248, 163, 173, 17, 66, 33, 90, 60, 129, 201, 72, 12, 62, 249, 19, 150, 188, 63, 112, 25, 44, 65, 158, 63, 23, 10, 66, 8, 196, 89, 67, 153, 117, 182, 25, 232, 187, 203, 119, 187, 66, 196, 87, 68, 163, 35, 144, 23, 70, 30, 239, 124, 135, 64, 157, 83, 232, 41, 43, 232, 132, 5, 33, 175, 129, 122, 148, 232, 161, 71, 13, 180, 254, 66, 119, 32, 170, 52, 228, 238, 42, 220, 107, 40, 236, 204, 225, 44, 8, 225, 3, 72, 108, 57, 11, 1, 111, 12, 234, 9, 186, 128, 158, 20, 228, 226, 210, 241, 20, 208, 11, 169, 208, 185, 165, 183, 29, 216, 39, 133, 78, 144, 8, 211, 145, 64, 82, 24, 8, 12, 151, 16, 39, 226, 169, 17, 186, 198, 240, 192, 181, 6, 226, 196, 79, 180, 4, 218, 155, 192, 65, 243, 23, 128, 254, 205, 184, 19, 196, 72, 236, 39, 27, 92, 83, 16, 186, 32, 239, 44, 140, 144, 66, 204, 179, 81, 18, 168, 152, 195, 3, 80, 227, 10, 90, 115, 4, 62, 246, 206, 19, 198, 189, 32, 74, 45, 54, 244, 12, 222, 49, 4, 226, 60, 64, 2, 154, 92, 1, 244, 217, 108, 132, 128, 124, 186, 76, 119, 202, 36, 135, 18, 64, 235, 8, 116, 70, 161, 96, 182, 162, 23, 228, 206, 206, 24, 1, 107, 105, 1, 86, 216, 90, 2, 169, 77, 78, 237, 113, 71, 96, 1, 20, 0, 1, 20, 20, 126, 185, 202, 95, 61, 188, 32, 241, 107, 125, 187, 153, 152, 199, 11, 155, 45, 171, 32, 2, 165, 37, 208, 177, 201, 42, 240, 56, 242, 2, 96, 64, 72, 249, 95, 186, 164, 54, 226, 236, 212, 10, 50, 214, 69, 238, 140, 17, 195, 208, 67, 32, 192, 8, 9, 19, 164, 117, 187, 10, 82, 69, 153, 19, 224, 166, 33, 101, 53, 183, 56, 88, 223, 218, 67, 29, 108, 137, 151, 38, 34, 210, 104, 104, 255, 215, 24, 41, 84, 64, 23, 82, 159, 85, 134, 188, 251, 98, 59, 54, 181, 151, 183, 163, 85, 205, 217, 66, 143, 235, 250, 87, 243, 69, 129, 202, 252, 75, 160, 233, 8, 253, 202, 239, 169, 209, 252, 170, 54, 228, 65, 4, 198, 102, 219, 118, 186, 208, 166, 72, 71, 63, 154, 29, 133, 51, 53, 149, 110, 105, 249, 53, 71, 27, 84, 137, 39, 80, 54, 197, 182, 21, 155, 243, 221, 91, 21, 95, 163, 190, 153, 67, 172, 208, 127, 67, 217, 7, 243, 224, 126, 149, 159, 119, 158, 247, 156, 151, 242, 228, 158, 112, 246, 143, 127, 252, 108, 20, 140, 130, 81, 48, 10, 70, 193, 40, 24, 5, 88, 1, 0, 48, 20, 121, 13, 171, 25, 166, 148, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130} +var WailsLogoWhiteTransparent = []byte{137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 128, 0, 0, 0, 128, 8, 3, 0, 0, 0, 244, 224, 145, 249, 0, 0, 2, 244, 80, 76, 84, 69, 0, 0, 0, 190, 37, 40, 145, 21, 31, 222, 46, 46, 208, 42, 44, 228, 50, 50, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 227, 50, 49, 227, 50, 50, 207, 38, 39, 224, 48, 49, 255, 255, 255, 227, 48, 48, 227, 50, 50, 255, 255, 255, 214, 44, 45, 202, 40, 43, 210, 42, 44, 174, 27, 33, 206, 41, 43, 255, 255, 255, 186, 33, 37, 255, 255, 255, 186, 32, 37, 134, 12, 22, 183, 31, 36, 150, 19, 25, 228, 50, 50, 255, 255, 255, 187, 34, 37, 255, 255, 255, 142, 14, 23, 196, 37, 40, 169, 25, 31, 220, 47, 47, 215, 45, 46, 227, 50, 50, 203, 40, 42, 198, 37, 40, 255, 255, 255, 255, 255, 255, 255, 255, 255, 120, 5, 16, 227, 50, 49, 203, 40, 42, 255, 255, 255, 255, 255, 255, 161, 22, 29, 227, 49, 49, 189, 33, 37, 255, 255, 255, 192, 35, 39, 255, 255, 255, 225, 49, 49, 255, 255, 255, 255, 255, 255, 167, 24, 31, 255, 255, 255, 255, 255, 255, 188, 33, 38, 179, 30, 35, 227, 50, 50, 225, 48, 48, 151, 18, 26, 205, 40, 43, 228, 50, 50, 192, 35, 38, 184, 32, 36, 255, 255, 255, 255, 255, 255, 218, 46, 47, 224, 48, 49, 228, 49, 49, 221, 46, 48, 255, 255, 255, 130, 11, 22, 196, 36, 40, 227, 50, 50, 191, 34, 39, 255, 255, 255, 227, 50, 50, 176, 28, 34, 176, 29, 33, 148, 17, 25, 255, 255, 255, 121, 6, 17, 228, 50, 50, 255, 255, 255, 188, 33, 38, 255, 255, 255, 255, 255, 255, 221, 47, 48, 226, 49, 49, 206, 40, 43, 255, 255, 255, 191, 34, 38, 255, 255, 255, 151, 18, 26, 227, 50, 50, 195, 37, 40, 174, 28, 33, 216, 46, 46, 146, 16, 26, 255, 255, 255, 210, 34, 36, 180, 30, 35, 150, 18, 26, 227, 50, 50, 211, 43, 45, 227, 49, 49, 195, 36, 40, 206, 41, 43, 255, 255, 255, 186, 32, 37, 225, 48, 49, 208, 42, 44, 156, 20, 28, 195, 37, 39, 125, 7, 18, 196, 37, 40, 149, 16, 27, 119, 0, 3, 217, 46, 47, 203, 39, 42, 203, 41, 43, 149, 17, 26, 178, 29, 34, 207, 41, 44, 255, 255, 255, 167, 25, 31, 164, 23, 30, 205, 40, 43, 227, 49, 49, 198, 37, 39, 228, 50, 50, 216, 45, 46, 175, 28, 33, 127, 8, 19, 255, 255, 255, 206, 41, 43, 255, 255, 255, 255, 255, 255, 186, 33, 37, 177, 29, 34, 155, 20, 27, 255, 255, 255, 255, 255, 255, 182, 31, 35, 224, 48, 48, 211, 43, 45, 131, 10, 20, 186, 32, 37, 227, 49, 49, 173, 27, 33, 126, 8, 19, 255, 255, 255, 221, 47, 48, 116, 4, 16, 255, 255, 255, 255, 255, 255, 255, 255, 255, 234, 53, 51, 127, 8, 19, 139, 13, 23, 227, 50, 49, 133, 10, 21, 124, 6, 18, 255, 255, 255, 255, 255, 255, 234, 216, 218, 172, 81, 88, 146, 16, 25, 214, 44, 46, 178, 30, 34, 168, 24, 31, 122, 6, 18, 166, 24, 31, 255, 255, 255, 216, 67, 69, 251, 216, 216, 226, 108, 109, 233, 151, 151, 188, 111, 117, 142, 17, 26, 165, 24, 31, 199, 38, 41, 214, 184, 187, 219, 87, 90, 224, 79, 80, 197, 142, 146, 149, 48, 57, 237, 173, 174, 227, 50, 50, 255, 255, 255, 223, 48, 48, 215, 45, 46, 221, 47, 48, 218, 46, 47, 213, 44, 45, 211, 43, 45, 203, 39, 42, 193, 35, 39, 219, 46, 47, 191, 34, 38, 206, 41, 43, 188, 33, 38, 246, 54, 54, 183, 31, 36, 199, 38, 41, 186, 32, 37, 209, 42, 44, 173, 27, 33, 179, 29, 35, 197, 37, 40, 176, 28, 34, 229, 50, 50, 181, 30, 35, 233, 51, 51, 170, 26, 32, 168, 24, 31, 201, 38, 41, 164, 23, 30, 236, 52, 52, 124, 6, 17, 131, 11, 21, 242, 53, 53, 195, 35, 39, 161, 22, 29, 222, 45, 47, 147, 16, 25, 137, 12, 22, 128, 8, 19, 140, 13, 23, 153, 18, 26, 219, 43, 46, 157, 20, 28, 205, 39, 42, 200, 35, 40, 231, 50, 50, 207, 39, 42, 215, 41, 44, 252, 55, 55, 238, 52, 52, 217, 45, 46, 212, 40, 44, 132, 6, 18, 235, 51, 51, 226, 46, 48, 239, 50, 51, 194, 134, 147, 194, 0, 0, 0, 195, 116, 82, 78, 83, 0, 5, 7, 11, 254, 253, 7, 251, 9, 4, 250, 169, 8, 253, 248, 27, 194, 244, 22, 17, 249, 249, 246, 233, 251, 164, 29, 254, 249, 24, 226, 222, 45, 19, 254, 252, 252, 251, 250, 246, 249, 248, 179, 56, 38, 254, 237, 176, 156, 149, 247, 87, 53, 24, 247, 241, 203, 185, 173, 243, 213, 208, 208, 90, 55, 32, 246, 239, 221, 196, 134, 127, 93, 68, 62, 51, 38, 13, 243, 233, 211, 181, 132, 102, 102, 65, 48, 44, 247, 232, 226, 221, 202, 190, 168, 120, 120, 113, 110, 107, 89, 82, 81, 79, 76, 37, 29, 254, 231, 182, 181, 165, 160, 154, 145, 143, 125, 94, 88, 79, 73, 54, 33, 15, 254, 245, 229, 217, 216, 206, 198, 196, 193, 170, 159, 145, 139, 133, 130, 118, 111, 100, 96, 88, 84, 240, 239, 236, 218, 194, 191, 189, 178, 169, 166, 151, 151, 151, 138, 111, 93, 78, 72, 67, 41, 221, 201, 173, 134, 74, 64, 33, 244, 237, 225, 224, 224, 209, 187, 139, 120, 245, 244, 243, 238, 235, 234, 228, 167, 254, 245, 245, 242, 240, 239, 163, 91, 109, 90, 0, 0, 13, 94, 73, 68, 65, 84, 120, 218, 236, 152, 105, 72, 147, 113, 28, 199, 159, 212, 17, 44, 87, 177, 182, 33, 186, 137, 168, 51, 247, 66, 3, 19, 19, 4, 205, 19, 52, 209, 36, 21, 195, 23, 133, 88, 41, 105, 165, 216, 97, 167, 69, 183, 18, 84, 208, 29, 245, 162, 19, 186, 163, 251, 238, 105, 30, 59, 156, 186, 195, 185, 205, 99, 78, 55, 231, 60, 166, 166, 89, 175, 250, 253, 159, 103, 143, 51, 203, 114, 166, 249, 34, 63, 136, 40, 27, 251, 126, 254, 191, 231, 247, 255, 255, 254, 12, 155, 101, 150, 89, 102, 153, 101, 150, 255, 4, 102, 34, 54, 163, 44, 61, 18, 137, 205, 32, 204, 139, 158, 75, 177, 25, 100, 93, 168, 254, 24, 54, 115, 36, 94, 92, 92, 59, 15, 195, 230, 96, 51, 0, 10, 93, 181, 82, 87, 187, 50, 114, 102, 242, 129, 21, 243, 232, 122, 93, 96, 206, 140, 228, 187, 98, 152, 243, 149, 24, 125, 31, 142, 175, 193, 102, 136, 132, 77, 248, 32, 78, 215, 205, 67, 50, 115, 230, 204, 113, 114, 117, 117, 117, 194, 254, 17, 176, 124, 230, 49, 207, 65, 29, 157, 214, 22, 19, 137, 57, 99, 255, 6, 88, 36, 9, 177, 247, 22, 106, 244, 56, 29, 215, 197, 92, 27, 121, 153, 233, 149, 182, 99, 71, 176, 251, 180, 100, 142, 109, 178, 200, 35, 129, 131, 125, 116, 26, 174, 161, 109, 78, 223, 16, 145, 154, 85, 20, 119, 225, 76, 120, 120, 74, 193, 218, 245, 94, 139, 166, 40, 248, 87, 125, 237, 180, 139, 151, 155, 158, 182, 61, 59, 251, 202, 66, 157, 30, 167, 225, 56, 174, 225, 60, 120, 152, 119, 74, 91, 109, 181, 214, 100, 166, 20, 173, 247, 98, 78, 233, 118, 160, 34, 139, 111, 103, 151, 149, 221, 186, 117, 249, 124, 126, 254, 141, 146, 146, 123, 47, 95, 237, 93, 172, 239, 163, 161, 124, 218, 30, 118, 125, 187, 213, 170, 200, 75, 137, 67, 75, 159, 58, 118, 93, 189, 122, 181, 236, 214, 229, 203, 231, 31, 61, 186, 113, 253, 250, 245, 164, 164, 36, 15, 179, 197, 187, 163, 163, 163, 171, 171, 163, 139, 91, 222, 167, 131, 229, 3, 26, 141, 164, 174, 62, 239, 76, 92, 4, 25, 62, 149, 2, 231, 91, 51, 2, 2, 2, 90, 91, 59, 59, 13, 134, 97, 15, 15, 179, 217, 108, 177, 88, 188, 189, 59, 188, 189, 195, 162, 225, 209, 51, 112, 2, 93, 242, 193, 75, 169, 193, 60, 108, 26, 40, 78, 26, 38, 4, 64, 1, 57, 120, 32, 7, 16, 176, 68, 157, 220, 67, 195, 133, 66, 28, 65, 211, 207, 75, 231, 77, 219, 17, 120, 59, 0, 213, 128, 18, 48, 160, 124, 139, 25, 150, 207, 128, 120, 82, 128, 174, 15, 101, 98, 211, 72, 89, 107, 107, 70, 235, 40, 1, 139, 217, 3, 150, 207, 16, 10, 25, 164, 0, 93, 23, 152, 48, 173, 51, 208, 233, 242, 112, 64, 6, 228, 35, 1, 244, 0, 12, 222, 97, 28, 134, 176, 162, 66, 72, 128, 211, 52, 154, 43, 147, 252, 96, 27, 115, 72, 176, 113, 225, 61, 26, 70, 37, 64, 241, 195, 195, 195, 134, 168, 147, 126, 194, 10, 233, 72, 62, 93, 191, 101, 106, 15, 60, 192, 201, 201, 149, 194, 9, 254, 193, 138, 175, 155, 51, 160, 250, 157, 187, 119, 239, 78, 122, 25, 198, 225, 11, 43, 237, 249, 140, 182, 80, 230, 228, 234, 207, 75, 231, 241, 22, 237, 154, 216, 212, 186, 157, 49, 12, 225, 1, 73, 119, 95, 188, 216, 199, 98, 84, 66, 190, 237, 9, 224, 12, 93, 76, 252, 36, 159, 127, 110, 126, 73, 126, 126, 254, 33, 224, 210, 165, 199, 143, 227, 74, 75, 75, 83, 83, 35, 34, 54, 108, 216, 145, 150, 22, 28, 236, 229, 181, 211, 221, 157, 185, 200, 217, 213, 246, 217, 87, 51, 12, 31, 238, 190, 191, 115, 231, 249, 59, 190, 180, 124, 200, 46, 192, 192, 105, 107, 160, 108, 78, 147, 42, 118, 118, 148, 170, 167, 165, 165, 165, 9, 104, 68, 176, 217, 236, 83, 167, 78, 229, 229, 229, 61, 200, 204, 12, 15, 15, 143, 141, 141, 77, 73, 89, 242, 250, 245, 225, 130, 194, 194, 227, 71, 239, 190, 185, 51, 119, 254, 211, 103, 123, 6, 134, 32, 127, 84, 5, 52, 130, 252, 108, 30, 57, 149, 29, 103, 251, 233, 166, 32, 163, 209, 8, 14, 96, 160, 106, 104, 168, 175, 215, 214, 41, 20, 53, 213, 213, 146, 246, 118, 181, 85, 222, 220, 44, 22, 247, 246, 202, 100, 253, 253, 50, 151, 254, 39, 79, 63, 45, 123, 254, 100, 227, 198, 170, 242, 242, 202, 81, 2, 26, 86, 84, 71, 208, 193, 210, 92, 212, 211, 127, 99, 224, 139, 80, 177, 217, 224, 0, 18, 117, 10, 183, 26, 164, 33, 105, 87, 203, 229, 200, 66, 230, 34, 218, 248, 246, 227, 51, 34, 158, 20, 160, 10, 192, 15, 50, 119, 25, 155, 124, 247, 199, 5, 99, 192, 100, 12, 26, 131, 32, 31, 149, 0, 106, 0, 69, 104, 128, 124, 16, 168, 1, 1, 137, 68, 226, 227, 227, 67, 24, 136, 101, 80, 7, 214, 198, 47, 85, 85, 200, 0, 242, 109, 2, 56, 141, 109, 232, 232, 234, 105, 81, 105, 235, 50, 11, 118, 76, 210, 64, 21, 68, 246, 1, 41, 0, 5, 64, 21, 80, 80, 21, 80, 83, 2, 46, 202, 141, 74, 17, 228, 255, 32, 160, 9, 241, 176, 32, 1, 223, 134, 186, 118, 117, 242, 146, 109, 206, 147, 49, 8, 66, 6, 68, 62, 41, 96, 175, 0, 249, 8, 40, 1, 23, 165, 136, 18, 160, 90, 0, 231, 120, 27, 188, 59, 186, 140, 45, 141, 13, 117, 53, 237, 189, 34, 206, 217, 43, 11, 28, 55, 200, 14, 106, 8, 242, 69, 176, 17, 245, 92, 192, 13, 64, 2, 62, 192, 79, 2, 246, 30, 196, 249, 81, 173, 150, 17, 1, 137, 92, 86, 110, 226, 135, 30, 191, 54, 9, 3, 45, 90, 58, 85, 124, 98, 245, 228, 242, 209, 3, 240, 25, 71, 0, 12, 232, 97, 1, 6, 16, 232, 49, 54, 169, 234, 161, 2, 114, 153, 75, 185, 80, 35, 140, 57, 146, 224, 176, 193, 171, 48, 0, 150, 175, 106, 176, 237, 67, 8, 183, 54, 139, 123, 251, 251, 149, 95, 250, 253, 199, 171, 0, 206, 13, 232, 244, 48, 219, 4, 20, 213, 106, 177, 76, 84, 46, 101, 104, 244, 186, 213, 91, 214, 57, 19, 135, 250, 132, 13, 210, 211, 210, 210, 54, 0, 17, 17, 17, 169, 169, 169, 89, 89, 165, 69, 69, 69, 113, 113, 71, 143, 22, 22, 20, 28, 222, 59, 224, 111, 107, 194, 49, 2, 56, 39, 41, 192, 128, 122, 16, 9, 104, 21, 33, 2, 127, 14, 203, 143, 207, 95, 188, 152, 142, 227, 171, 111, 110, 93, 52, 206, 233, 231, 52, 22, 87, 152, 59, 191, 155, 76, 235, 163, 187, 253, 33, 159, 18, 176, 111, 2, 62, 59, 169, 213, 96, 70, 2, 208, 2, 218, 154, 230, 47, 3, 67, 38, 188, 79, 167, 31, 212, 235, 7, 107, 107, 117, 43, 143, 173, 112, 100, 48, 99, 227, 131, 12, 144, 0, 202, 167, 4, 42, 164, 66, 134, 91, 79, 80, 82, 39, 37, 80, 231, 150, 156, 236, 47, 170, 242, 227, 51, 232, 0, 170, 130, 142, 30, 250, 179, 194, 174, 220, 226, 226, 226, 244, 220, 92, 30, 194, 221, 14, 24, 252, 98, 241, 163, 12, 56, 35, 45, 64, 85, 128, 33, 48, 182, 52, 69, 121, 152, 169, 77, 16, 146, 146, 21, 31, 191, 109, 235, 214, 165, 54, 214, 45, 221, 186, 106, 235, 242, 177, 93, 192, 43, 190, 90, 118, 249, 252, 141, 146, 123, 247, 74, 74, 30, 30, 4, 206, 156, 137, 5, 14, 172, 253, 253, 133, 106, 91, 180, 137, 51, 70, 64, 200, 242, 53, 54, 53, 250, 70, 121, 128, 0, 180, 0, 236, 194, 228, 37, 39, 152, 19, 24, 128, 187, 120, 233, 183, 203, 110, 157, 191, 113, 186, 71, 85, 87, 77, 32, 81, 139, 149, 254, 127, 50, 224, 152, 56, 74, 165, 253, 32, 172, 20, 250, 177, 141, 232, 236, 102, 71, 89, 186, 200, 93, 88, 45, 239, 231, 28, 56, 142, 106, 62, 145, 222, 119, 229, 165, 111, 79, 125, 124, 232, 225, 41, 173, 4, 198, 157, 88, 46, 227, 252, 217, 128, 53, 170, 2, 21, 252, 16, 34, 191, 65, 203, 142, 178, 239, 194, 42, 83, 229, 253, 139, 241, 72, 97, 130, 163, 121, 81, 110, 90, 68, 209, 133, 216, 76, 129, 178, 187, 79, 122, 252, 247, 95, 191, 156, 0, 3, 74, 0, 122, 80, 208, 210, 164, 82, 17, 167, 70, 88, 71, 15, 252, 173, 69, 2, 46, 34, 169, 6, 247, 156, 7, 103, 128, 35, 56, 187, 7, 175, 207, 42, 60, 119, 63, 26, 12, 126, 71, 78, 116, 55, 139, 18, 168, 96, 177, 33, 159, 24, 156, 10, 183, 176, 46, 98, 23, 74, 144, 192, 80, 5, 254, 85, 23, 184, 105, 21, 211, 225, 187, 17, 51, 49, 103, 27, 115, 220, 74, 237, 12, 206, 57, 177, 118, 95, 55, 85, 129, 10, 63, 46, 228, 19, 115, 27, 14, 77, 110, 144, 145, 156, 4, 98, 151, 170, 202, 10, 6, 142, 235, 244, 139, 67, 215, 36, 98, 127, 15, 228, 238, 56, 177, 246, 232, 225, 37, 7, 246, 237, 141, 230, 176, 88, 34, 234, 28, 226, 135, 64, 219, 147, 249, 48, 53, 124, 184, 190, 141, 245, 132, 128, 18, 4, 132, 56, 78, 3, 5, 124, 229, 145, 229, 147, 206, 117, 247, 74, 139, 200, 138, 43, 72, 137, 13, 207, 76, 22, 200, 197, 50, 232, 126, 18, 242, 28, 26, 146, 10, 124, 81, 62, 117, 121, 83, 251, 112, 209, 38, 128, 89, 168, 44, 39, 4, 144, 66, 159, 94, 227, 185, 37, 199, 193, 187, 50, 15, 190, 222, 136, 187, 4, 223, 110, 100, 158, 60, 233, 86, 221, 174, 38, 174, 132, 205, 232, 151, 191, 204, 197, 126, 12, 72, 89, 108, 85, 61, 181, 124, 137, 68, 173, 22, 39, 231, 161, 30, 108, 70, 163, 8, 70, 52, 9, 77, 163, 135, 102, 32, 7, 194, 68, 61, 220, 15, 41, 216, 245, 104, 85, 36, 232, 66, 6, 128, 6, 53, 11, 161, 0, 126, 126, 124, 63, 46, 149, 15, 239, 1, 77, 121, 111, 244, 133, 7, 214, 16, 155, 0, 14, 231, 48, 157, 58, 141, 53, 129, 103, 87, 57, 114, 65, 9, 222, 111, 37, 238, 4, 110, 192, 152, 251, 144, 11, 192, 98, 249, 85, 73, 241, 202, 16, 21, 188, 135, 92, 62, 188, 1, 189, 44, 42, 44, 109, 87, 11, 160, 7, 203, 43, 24, 154, 182, 207, 181, 109, 109, 240, 67, 240, 249, 115, 155, 231, 197, 248, 137, 111, 75, 175, 253, 18, 46, 151, 188, 16, 218, 111, 132, 98, 192, 159, 195, 97, 137, 164, 223, 250, 52, 166, 61, 130, 122, 120, 7, 185, 124, 9, 121, 95, 148, 13, 29, 72, 188, 48, 64, 10, 8, 3, 87, 134, 198, 172, 94, 237, 105, 35, 38, 102, 117, 160, 231, 194, 53, 137, 14, 24, 180, 107, 145, 129, 77, 0, 229, 203, 253, 1, 101, 183, 233, 155, 73, 116, 255, 192, 225, 181, 57, 69, 53, 10, 238, 200, 242, 229, 196, 211, 169, 98, 197, 239, 12, 249, 226, 79, 108, 130, 192, 45, 235, 174, 69, 174, 72, 72, 88, 110, 99, 197, 138, 229, 9, 9, 145, 152, 3, 6, 86, 46, 81, 1, 178, 7, 4, 2, 129, 92, 57, 96, 50, 85, 113, 246, 157, 59, 122, 34, 33, 210, 21, 78, 241, 75, 86, 133, 27, 188, 72, 45, 31, 53, 167, 180, 16, 203, 26, 80, 178, 208, 38, 160, 5, 110, 186, 242, 139, 60, 199, 12, 190, 179, 103, 126, 47, 77, 133, 97, 28, 127, 198, 233, 44, 221, 60, 169, 103, 146, 205, 11, 115, 196, 92, 178, 161, 103, 168, 115, 133, 25, 130, 165, 230, 194, 95, 23, 33, 253, 16, 10, 111, 118, 161, 150, 4, 34, 164, 23, 65, 81, 32, 94, 133, 222, 86, 130, 23, 221, 246, 31, 236, 40, 153, 118, 177, 139, 32, 14, 131, 24, 76, 118, 37, 75, 157, 12, 245, 166, 231, 153, 239, 122, 183, 154, 180, 214, 14, 122, 225, 231, 226, 236, 98, 135, 243, 121, 190, 103, 239, 251, 62, 239, 57, 187, 144, 44, 192, 227, 185, 244, 45, 182, 179, 185, 179, 54, 77, 193, 107, 100, 96, 200, 253, 219, 30, 30, 159, 252, 181, 81, 175, 0, 13, 81, 44, 0, 39, 65, 104, 23, 215, 128, 91, 172, 33, 228, 85, 65, 219, 143, 228, 32, 220, 88, 75, 36, 98, 117, 51, 13, 24, 124, 74, 128, 116, 166, 218, 18, 158, 84, 252, 51, 56, 55, 113, 102, 62, 235, 6, 223, 244, 126, 45, 205, 66, 17, 75, 216, 170, 30, 31, 33, 125, 126, 37, 52, 181, 197, 214, 191, 111, 199, 54, 122, 111, 60, 126, 56, 89, 99, 201, 118, 70, 239, 78, 93, 42, 254, 106, 242, 81, 113, 255, 53, 54, 204, 79, 203, 118, 90, 5, 68, 145, 214, 0, 214, 16, 12, 249, 85, 176, 126, 183, 255, 230, 245, 166, 170, 35, 3, 76, 78, 39, 46, 51, 127, 178, 57, 218, 181, 121, 3, 24, 158, 28, 216, 37, 182, 10, 5, 180, 112, 216, 81, 54, 220, 158, 239, 56, 248, 219, 155, 206, 170, 153, 205, 243, 164, 39, 255, 225, 115, 106, 125, 15, 64, 169, 55, 226, 8, 48, 68, 106, 8, 38, 218, 151, 234, 129, 220, 240, 149, 173, 140, 232, 39, 189, 36, 105, 195, 0, 208, 109, 15, 155, 2, 12, 214, 147, 58, 104, 131, 82, 120, 255, 38, 234, 41, 62, 243, 47, 75, 166, 208, 40, 32, 195, 65, 212, 166, 67, 15, 41, 75, 141, 130, 14, 126, 212, 179, 219, 191, 76, 72, 218, 208, 34, 53, 210, 209, 184, 35, 163, 0, 17, 119, 231, 33, 106, 8, 5, 247, 243, 248, 8, 253, 228, 218, 32, 32, 61, 67, 65, 135, 136, 152, 232, 64, 31, 216, 149, 68, 45, 132, 27, 148, 69, 40, 16, 22, 244, 211, 230, 144, 199, 63, 140, 26, 90, 2, 98, 48, 18, 143, 4, 127, 35, 18, 140, 199, 131, 245, 230, 17, 25, 254, 27, 3, 249, 63, 87, 172, 102, 196, 103, 237, 191, 186, 29, 16, 225, 85, 223, 124, 89, 54, 188, 94, 243, 160, 92, 8, 255, 23, 242, 163, 62, 211, 79, 99, 239, 41, 16, 37, 237, 165, 217, 144, 229, 82, 159, 79, 40, 128, 63, 154, 242, 51, 61, 39, 100, 6, 125, 33, 255, 88, 116, 181, 34, 51, 62, 71, 235, 144, 65, 47, 184, 127, 165, 118, 37, 109, 242, 5, 50, 48, 53, 130, 174, 112, 63, 143, 159, 193, 214, 56, 232, 138, 64, 254, 172, 241, 25, 90, 159, 5, 56, 250, 248, 217, 75, 106, 73, 146, 184, 151, 47, 253, 14, 61, 255, 56, 47, 121, 129, 126, 54, 250, 146, 126, 241, 207, 2, 180, 151, 160, 27, 83, 11, 145, 61, 109, 111, 47, 188, 123, 16, 65, 130, 217, 137, 87, 91, 116, 187, 5, 221, 11, 11, 99, 15, 24, 230, 163, 88, 26, 247, 233, 86, 128, 96, 41, 17, 114, 192, 0, 167, 156, 114, 82, 40, 54, 22, 25, 139, 225, 248, 40, 134, 99, 199, 230, 183, 253, 83, 33, 205, 19, 138, 123, 194, 5, 239, 172, 202, 128, 31, 230, 172, 110, 101, 150, 127, 231, 82, 20, 183, 210, 105, 3, 35, 48, 108, 3, 86, 183, 219, 201, 227, 118, 89, 39, 148, 46, 72, 3, 175, 243, 230, 222, 125, 101, 206, 8, 57, 227, 106, 81, 213, 114, 39, 92, 85, 213, 202, 59, 240, 92, 85, 213, 143, 220, 215, 169, 34, 23, 93, 80, 4, 12, 103, 57, 158, 252, 254, 215, 9, 182, 43, 234, 57, 117, 0, 210, 120, 212, 162, 18, 173, 126, 200, 185, 4, 127, 37, 169, 111, 211, 209, 101, 43, 167, 35, 191, 126, 171, 138, 84, 58, 121, 1, 111, 169, 32, 126, 194, 135, 86, 44, 96, 22, 56, 206, 22, 245, 172, 138, 92, 43, 202, 189, 128, 230, 159, 237, 85, 49, 143, 178, 64, 20, 220, 138, 93, 155, 77, 182, 34, 84, 132, 22, 45, 160, 32, 6, 162, 181, 52, 52, 54, 38, 70, 10, 66, 103, 235, 79, 176, 190, 156, 133, 182, 151, 124, 94, 167, 237, 253, 132, 247, 195, 190, 217, 83, 246, 97, 114, 133, 244, 76, 162, 102, 55, 207, 157, 121, 51, 111, 33, 36, 218, 206, 110, 150, 233, 126, 197, 119, 33, 0, 166, 195, 246, 55, 11, 104, 65, 120, 172, 132, 199, 124, 218, 220, 122, 121, 175, 137, 164, 174, 115, 147, 15, 24, 130, 12, 109, 158, 103, 43, 50, 144, 1, 203, 229, 7, 107, 15, 72, 74, 73, 243, 127, 44, 224, 11, 101, 129, 64, 69, 223, 16, 230, 242, 10, 24, 112, 84, 213, 245, 52, 100, 104, 151, 112, 108, 122, 193, 201, 225, 52, 199, 121, 153, 59, 111, 230, 147, 92, 248, 100, 74, 71, 168, 10, 148, 125, 113, 119, 45, 248, 118, 21, 150, 44, 89, 211, 57, 18, 131, 80, 237, 32, 160, 68, 255, 20, 150, 72, 35, 224, 11, 221, 18, 205, 211, 144, 76, 235, 24, 178, 37, 8, 90, 1, 176, 33, 69, 223, 237, 15, 66, 65, 60, 76, 129, 186, 64, 192, 129, 194, 152, 194, 131, 38, 205, 230, 41, 235, 199, 39, 92, 88, 57, 134, 141, 79, 72, 196, 25, 82, 117, 134, 176, 157, 5, 193, 148, 224, 189, 252, 153, 71, 134, 75, 42, 214, 228, 195, 139, 69, 36, 250, 87, 46, 152, 73, 2, 69, 135, 111, 155, 249, 70, 40, 54, 196, 244, 13, 129, 178, 123, 77, 192, 106, 208, 179, 51, 38, 105, 164, 108, 26, 210, 96, 76, 69, 127, 162, 117, 185, 39, 236, 185, 30, 75, 155, 121, 36, 20, 27, 162, 97, 153, 234, 43, 216, 44, 81, 179, 192, 92, 188, 47, 192, 78, 46, 109, 167, 13, 97, 226, 245, 149, 111, 7, 78, 210, 65, 66, 176, 193, 9, 88, 217, 132, 45, 13, 27, 178, 205, 196, 43, 62, 177, 233, 179, 75, 111, 32, 176, 2, 114, 123, 56, 218, 227, 255, 157, 108, 154, 246, 195, 148, 30, 134, 156, 253, 176, 35, 39, 233, 124, 219, 111, 186, 117, 213, 148, 19, 209, 88, 85, 131, 4, 36, 150, 100, 37, 14, 214, 129, 117, 95, 87, 135, 218, 123, 10, 136, 118, 40, 253, 97, 119, 215, 208, 99, 22, 231, 184, 35, 219, 47, 168, 40, 182, 54, 2, 53, 32, 2, 48, 27, 242, 111, 34, 37, 163, 231, 83, 126, 69, 132, 100, 76, 218, 216, 158, 47, 213, 179, 159, 123, 72, 122, 126, 114, 9, 120, 9, 205, 33, 154, 234, 215, 7, 177, 70, 59, 67, 248, 193, 140, 225, 159, 252, 118, 188, 123, 25, 65, 10, 213, 35, 209, 189, 80, 46, 115, 61, 229, 75, 112, 166, 95, 36, 28, 255, 3, 129, 18, 67, 80, 30, 227, 184, 69, 160, 199, 56, 47, 121, 156, 127, 176, 108, 208, 84, 29, 231, 73, 246, 108, 218, 46, 82, 44, 58, 1, 201, 165, 136, 227, 56, 63, 57, 215, 210, 165, 239, 111, 235, 38, 18, 131, 48, 81, 202, 155, 216, 31, 207, 19, 12, 79, 121, 234, 177, 171, 186, 109, 94, 112, 13, 128, 50, 135, 42, 202, 34, 37, 70, 140, 24, 49, 98, 196, 136, 17, 35, 70, 252, 137, 255, 156, 118, 125, 151, 11, 217, 82, 191, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130} +var WailsLogoWhite = []byte{137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 128, 0, 0, 0, 128, 8, 3, 0, 0, 0, 244, 224, 145, 249, 0, 0, 3, 0, 80, 76, 84, 69, 255, 255, 255, 255, 255, 255, 252, 252, 252, 26, 26, 26, 255, 255, 255, 250, 250, 250, 255, 254, 254, 228, 57, 57, 161, 22, 30, 225, 39, 40, 255, 254, 254, 230, 72, 72, 2, 2, 2, 14, 14, 14, 253, 247, 247, 173, 11, 16, 183, 32, 37, 227, 49, 49, 51, 51, 51, 252, 243, 243, 249, 249, 249, 160, 5, 12, 251, 224, 224, 253, 246, 246, 42, 42, 42, 185, 36, 41, 207, 32, 34, 254, 249, 249, 31, 31, 31, 215, 47, 49, 221, 28, 28, 228, 228, 228, 209, 42, 44, 243, 196, 197, 198, 19, 22, 204, 18, 20, 236, 236, 236, 252, 235, 236, 73, 73, 73, 248, 248, 248, 244, 244, 244, 60, 60, 60, 227, 53, 53, 202, 202, 202, 129, 129, 129, 239, 215, 217, 113, 113, 113, 213, 36, 37, 151, 2, 9, 227, 44, 44, 246, 186, 186, 230, 63, 63, 45, 45, 45, 197, 67, 71, 174, 174, 174, 66, 66, 66, 178, 18, 24, 108, 0, 0, 252, 239, 239, 228, 189, 191, 82, 82, 82, 232, 82, 82, 242, 189, 190, 193, 30, 34, 184, 23, 28, 198, 37, 41, 195, 49, 53, 192, 37, 40, 250, 220, 221, 94, 94, 94, 162, 23, 30, 221, 102, 104, 242, 163, 163, 122, 122, 122, 231, 114, 115, 219, 54, 55, 121, 0, 6, 220, 47, 48, 72, 72, 72, 5, 5, 5, 239, 207, 208, 216, 99, 101, 148, 17, 25, 37, 37, 37, 237, 122, 122, 235, 106, 107, 245, 245, 245, 117, 2, 13, 250, 230, 230, 181, 34, 39, 216, 216, 216, 22, 22, 22, 248, 229, 230, 222, 163, 165, 238, 152, 152, 223, 223, 223, 174, 54, 60, 213, 213, 213, 225, 131, 132, 236, 181, 182, 216, 139, 141, 245, 235, 236, 172, 27, 33, 130, 9, 20, 163, 7, 14, 152, 152, 152, 254, 253, 253, 110, 110, 110, 248, 204, 204, 184, 184, 184, 164, 164, 164, 103, 103, 103, 225, 187, 189, 209, 65, 68, 239, 133, 133, 235, 167, 168, 235, 200, 201, 185, 44, 49, 51, 51, 51, 221, 151, 153, 221, 37, 37, 244, 181, 182, 208, 52, 55, 142, 34, 44, 189, 58, 62, 249, 217, 217, 209, 104, 107, 155, 66, 74, 245, 223, 224, 158, 158, 158, 221, 107, 108, 232, 185, 186, 222, 139, 141, 176, 22, 27, 196, 196, 196, 207, 34, 36, 17, 17, 17, 221, 84, 85, 191, 191, 191, 119, 119, 119, 249, 210, 210, 239, 145, 145, 243, 175, 175, 194, 107, 112, 233, 93, 93, 201, 81, 85, 242, 228, 230, 199, 147, 151, 221, 120, 122, 178, 25, 30, 239, 204, 205, 229, 150, 151, 233, 142, 143, 216, 170, 173, 161, 41, 49, 136, 136, 136, 216, 178, 181, 211, 117, 121, 173, 99, 105, 37, 37, 37, 187, 29, 33, 145, 145, 145, 84, 84, 84, 101, 101, 101, 212, 96, 99, 140, 140, 140, 223, 69, 70, 151, 27, 36, 215, 85, 87, 169, 57, 63, 89, 89, 89, 204, 114, 119, 187, 96, 101, 203, 26, 28, 172, 78, 84, 127, 15, 26, 190, 127, 132, 200, 83, 86, 200, 54, 57, 183, 122, 129, 192, 192, 192, 238, 223, 224, 255, 255, 255, 255, 254, 254, 254, 253, 253, 226, 49, 49, 228, 50, 50, 218, 46, 47, 216, 45, 46, 222, 47, 48, 220, 47, 47, 254, 250, 250, 212, 43, 45, 224, 48, 49, 214, 44, 46, 254, 248, 248, 208, 42, 44, 255, 252, 252, 251, 250, 250, 228, 52, 52, 204, 40, 43, 197, 37, 40, 200, 39, 42, 186, 32, 37, 194, 36, 40, 33, 33, 33, 191, 35, 38, 189, 34, 38, 180, 30, 35, 210, 42, 44, 30, 30, 30, 129, 10, 20, 173, 27, 33, 23, 23, 23, 207, 40, 43, 225, 31, 31, 228, 44, 44, 10, 10, 10, 202, 39, 42, 183, 31, 36, 170, 26, 32, 165, 24, 30, 134, 12, 22, 124, 7, 18, 236, 116, 116, 228, 48, 47, 19, 19, 19, 223, 50, 50, 176, 28, 34, 37, 37, 37, 138, 13, 23, 178, 29, 35, 204, 45, 47, 194, 40, 44, 227, 38, 38, 143, 14, 23, 150, 17, 25, 168, 25, 31, 156, 20, 28, 208, 47, 49, 229, 56, 56, 175, 33, 39, 212, 47, 49, 166, 31, 38, 189, 39, 43, 202, 28, 30, 189, 17, 21, 181, 12, 17, 196, 25, 29, 200, 45, 48, 199, 32, 35, 189, 24, 28, 132, 0, 6, 224, 55, 55, 213, 27, 29, 147, 22, 30, 49, 94, 55, 29, 0, 0, 0, 182, 116, 82, 78, 83, 251, 225, 254, 254, 248, 245, 246, 254, 254, 253, 250, 244, 254, 254, 248, 253, 254, 249, 245, 246, 254, 254, 248, 254, 254, 254, 254, 248, 248, 254, 253, 246, 246, 244, 254, 253, 245, 243, 237, 252, 246, 244, 244, 241, 240, 236, 233, 254, 254, 249, 247, 246, 245, 242, 238, 238, 254, 253, 250, 249, 245, 244, 240, 254, 254, 248, 247, 245, 243, 243, 243, 242, 240, 235, 254, 254, 254, 250, 249, 249, 248, 248, 247, 246, 242, 241, 252, 252, 248, 248, 246, 246, 244, 244, 244, 243, 243, 240, 240, 238, 237, 249, 247, 247, 246, 244, 243, 243, 242, 242, 242, 242, 240, 240, 239, 238, 232, 232, 230, 227, 250, 246, 245, 243, 241, 240, 240, 240, 239, 235, 235, 253, 251, 249, 248, 247, 246, 245, 244, 244, 243, 242, 241, 241, 241, 241, 240, 240, 240, 239, 238, 238, 234, 233, 246, 244, 243, 242, 237, 236, 236, 234, 231, 230, 223, 247, 243, 241, 240, 229, 225, 224, 249, 246, 242, 241, 233, 233, 222, 246, 228, 205, 116, 60, 49, 81, 0, 0, 16, 106, 73, 68, 65, 84, 120, 218, 236, 152, 107, 72, 83, 97, 24, 199, 79, 99, 45, 87, 224, 22, 203, 196, 133, 177, 21, 131, 16, 196, 76, 6, 102, 152, 87, 76, 42, 161, 164, 48, 161, 68, 76, 45, 162, 15, 154, 69, 217, 69, 165, 18, 9, 42, 75, 211, 50, 42, 250, 16, 93, 232, 94, 116, 222, 179, 153, 206, 53, 215, 230, 20, 83, 54, 84, 212, 37, 50, 209, 121, 75, 179, 214, 197, 174, 207, 251, 158, 169, 179, 102, 185, 210, 250, 80, 255, 47, 162, 135, 115, 254, 191, 247, 121, 159, 247, 121, 158, 87, 106, 6, 77, 209, 127, 83, 255, 1, 254, 3, 252, 7, 248, 15, 240, 207, 0, 32, 231, 127, 254, 99, 0, 218, 191, 11, 128, 84, 19, 133, 224, 207, 0, 168, 24, 90, 20, 233, 252, 209, 159, 0, 64, 26, 154, 146, 110, 136, 164, 145, 211, 24, 76, 63, 0, 44, 223, 125, 151, 79, 230, 4, 123, 48, 253, 0, 120, 249, 193, 11, 19, 16, 173, 117, 250, 120, 186, 1, 24, 154, 150, 109, 240, 111, 92, 205, 5, 16, 167, 154, 102, 0, 45, 77, 101, 6, 244, 244, 4, 203, 38, 244, 159, 70, 0, 146, 116, 155, 54, 242, 155, 218, 125, 164, 19, 251, 79, 31, 0, 98, 16, 205, 141, 246, 105, 212, 41, 252, 19, 40, 154, 113, 164, 114, 212, 180, 1, 32, 176, 140, 60, 181, 176, 125, 80, 201, 223, 136, 19, 128, 97, 24, 45, 136, 249, 214, 127, 154, 0, 16, 164, 252, 130, 132, 185, 61, 131, 58, 5, 127, 142, 140, 246, 164, 39, 210, 20, 2, 32, 134, 195, 209, 170, 158, 170, 176, 96, 157, 104, 103, 112, 163, 114, 150, 66, 217, 30, 112, 28, 63, 164, 104, 138, 75, 115, 100, 243, 35, 139, 139, 101, 104, 170, 0, 16, 195, 112, 84, 156, 167, 79, 53, 154, 121, 26, 45, 195, 161, 29, 21, 116, 194, 31, 47, 95, 169, 208, 37, 165, 236, 78, 59, 178, 101, 239, 209, 139, 247, 79, 203, 31, 156, 190, 184, 119, 119, 16, 188, 249, 219, 0, 104, 222, 188, 121, 42, 237, 120, 79, 88, 34, 119, 166, 40, 197, 215, 119, 93, 90, 73, 70, 240, 66, 88, 62, 72, 41, 73, 140, 47, 202, 13, 20, 8, 4, 111, 189, 228, 23, 143, 108, 34, 86, 232, 183, 35, 128, 236, 249, 204, 229, 209, 59, 82, 82, 10, 118, 175, 88, 81, 82, 88, 120, 239, 210, 173, 59, 55, 18, 207, 95, 139, 253, 18, 117, 121, 31, 89, 190, 82, 169, 91, 19, 223, 42, 8, 20, 228, 134, 159, 78, 150, 202, 184, 216, 71, 245, 148, 161, 127, 123, 11, 16, 45, 42, 185, 80, 82, 248, 240, 225, 165, 236, 236, 236, 3, 7, 14, 220, 221, 102, 108, 91, 251, 145, 213, 210, 222, 222, 162, 152, 193, 193, 79, 74, 236, 63, 168, 14, 244, 16, 196, 203, 47, 110, 205, 225, 17, 115, 79, 13, 174, 199, 83, 1, 144, 146, 189, 60, 110, 57, 209, 90, 144, 209, 104, 236, 236, 236, 236, 253, 66, 20, 181, 127, 214, 160, 197, 162, 192, 210, 241, 35, 18, 47, 110, 89, 231, 78, 190, 175, 113, 52, 255, 253, 45, 240, 189, 187, 188, 13, 100, 4, 61, 39, 234, 196, 8, 189, 189, 177, 151, 99, 148, 138, 50, 53, 184, 67, 252, 155, 54, 250, 138, 200, 183, 85, 26, 21, 222, 181, 169, 4, 160, 211, 226, 226, 218, 226, 218, 28, 32, 176, 127, 103, 148, 68, 167, 44, 179, 168, 73, 250, 233, 218, 131, 69, 184, 29, 145, 83, 9, 154, 74, 0, 32, 64, 133, 16, 130, 241, 0, 157, 120, 249, 101, 101, 106, 53, 1, 208, 41, 125, 118, 210, 90, 21, 155, 114, 83, 14, 0, 181, 157, 186, 180, 220, 56, 206, 255, 121, 148, 68, 161, 46, 47, 83, 91, 0, 0, 251, 251, 71, 147, 22, 224, 50, 0, 114, 34, 167, 49, 88, 146, 77, 8, 70, 178, 0, 150, 175, 46, 47, 135, 0, 128, 192, 95, 199, 223, 192, 163, 85, 180, 203, 0, 32, 39, 52, 204, 119, 66, 140, 22, 39, 162, 145, 4, 224, 227, 71, 227, 54, 88, 126, 121, 41, 248, 19, 2, 124, 0, 32, 1, 52, 244, 47, 0, 120, 6, 205, 230, 241, 240, 169, 69, 20, 232, 199, 111, 94, 136, 91, 219, 134, 79, 225, 129, 75, 55, 31, 236, 179, 60, 46, 45, 135, 8, 176, 254, 150, 166, 128, 157, 224, 239, 50, 0, 196, 122, 93, 226, 249, 27, 55, 110, 220, 202, 191, 149, 159, 127, 243, 102, 242, 22, 80, 73, 73, 218, 58, 144, 175, 111, 78, 80, 80, 144, 72, 36, 218, 129, 48, 28, 151, 139, 104, 170, 48, 110, 237, 129, 236, 123, 190, 51, 87, 6, 243, 75, 31, 151, 150, 130, 255, 200, 22, 204, 141, 70, 180, 74, 133, 92, 4, 32, 4, 23, 250, 150, 190, 240, 88, 138, 229, 193, 106, 251, 118, 65, 96, 96, 110, 110, 81, 209, 229, 240, 240, 240, 131, 242, 7, 242, 245, 235, 215, 175, 58, 124, 248, 230, 209, 132, 132, 115, 249, 23, 224, 160, 7, 173, 90, 252, 217, 27, 252, 9, 0, 155, 132, 202, 176, 59, 23, 220, 113, 245, 97, 92, 4, 192, 105, 187, 34, 170, 239, 149, 219, 43, 86, 47, 177, 188, 132, 93, 117, 194, 150, 234, 103, 207, 66, 67, 63, 124, 248, 16, 242, 238, 13, 104, 17, 209, 226, 171, 50, 90, 116, 86, 178, 216, 219, 251, 201, 24, 0, 72, 41, 137, 253, 184, 52, 113, 139, 12, 1, 130, 214, 197, 28, 128, 228, 90, 225, 182, 244, 149, 27, 200, 108, 238, 239, 111, 109, 53, 153, 76, 29, 0, 0, 242, 122, 13, 234, 238, 238, 126, 79, 100, 181, 90, 7, 6, 108, 233, 91, 87, 45, 246, 91, 243, 228, 201, 99, 135, 8, 88, 148, 49, 81, 207, 221, 220, 60, 60, 14, 38, 231, 80, 128, 160, 114, 237, 20, 48, 140, 157, 192, 12, 0, 173, 24, 160, 163, 163, 163, 174, 174, 174, 165, 165, 186, 26, 162, 80, 91, 91, 83, 83, 83, 85, 101, 48, 52, 55, 55, 235, 27, 6, 26, 242, 196, 222, 67, 21, 4, 96, 36, 7, 45, 138, 185, 69, 198, 190, 190, 23, 175, 94, 6, 10, 34, 206, 172, 227, 98, 4, 151, 142, 33, 7, 19, 120, 188, 34, 0, 253, 44, 64, 215, 40, 64, 45, 6, 168, 98, 1, 244, 250, 134, 202, 202, 138, 161, 138, 138, 10, 240, 119, 216, 2, 101, 196, 182, 94, 0, 48, 183, 190, 244, 250, 240, 38, 108, 213, 202, 29, 24, 193, 5, 0, 216, 5, 66, 224, 16, 129, 46, 236, 223, 50, 22, 0, 2, 160, 39, 0, 149, 245, 224, 207, 2, 148, 179, 0, 10, 201, 182, 231, 189, 189, 47, 220, 204, 173, 29, 194, 215, 221, 195, 182, 188, 99, 25, 34, 220, 143, 92, 40, 68, 90, 198, 78, 96, 79, 1, 66, 64, 0, 48, 129, 115, 0, 54, 0, 24, 32, 38, 182, 173, 179, 183, 15, 3, 116, 9, 159, 213, 188, 183, 214, 251, 249, 93, 77, 144, 81, 208, 23, 38, 95, 9, 25, 66, 240, 210, 100, 122, 201, 74, 232, 5, 122, 141, 213, 77, 100, 0, 53, 55, 59, 5, 80, 207, 77, 141, 123, 206, 2, 152, 186, 90, 158, 213, 24, 244, 67, 222, 165, 124, 126, 192, 174, 67, 92, 8, 3, 154, 36, 0, 33, 136, 218, 78, 36, 24, 209, 91, 44, 56, 129, 239, 64, 19, 71, 64, 17, 17, 103, 100, 1, 250, 77, 117, 213, 181, 85, 134, 134, 250, 39, 229, 22, 69, 83, 207, 220, 141, 82, 30, 4, 23, 77, 10, 128, 212, 131, 130, 221, 32, 24, 247, 142, 128, 246, 130, 146, 147, 147, 143, 130, 146, 174, 128, 222, 15, 235, 157, 0, 0, 1, 36, 192, 120, 128, 230, 202, 138, 199, 229, 106, 139, 78, 217, 222, 227, 127, 106, 25, 32, 32, 39, 0, 92, 196, 124, 175, 137, 10, 8, 226, 114, 41, 74, 26, 102, 179, 218, 183, 160, 194, 17, 64, 29, 147, 186, 173, 141, 5, 128, 28, 36, 0, 13, 0, 80, 6, 243, 9, 168, 169, 103, 78, 180, 200, 133, 171, 25, 135, 5, 193, 34, 63, 237, 66, 248, 214, 39, 53, 216, 172, 250, 134, 6, 54, 0, 99, 91, 96, 137, 127, 225, 182, 205, 8, 254, 118, 128, 238, 225, 97, 177, 216, 111, 223, 62, 190, 93, 141, 11, 125, 118, 69, 82, 223, 220, 11, 10, 60, 11, 82, 82, 82, 68, 238, 11, 176, 220, 71, 181, 224, 7, 227, 4, 98, 104, 105, 179, 109, 128, 0, 216, 203, 0, 27, 128, 48, 55, 115, 127, 20, 156, 194, 62, 114, 10, 91, 34, 178, 182, 74, 151, 101, 102, 102, 46, 27, 83, 102, 244, 74, 247, 241, 31, 166, 30, 165, 221, 187, 4, 195, 245, 181, 107, 215, 206, 159, 79, 76, 76, 60, 136, 37, 151, 167, 167, 159, 165, 104, 213, 143, 8, 244, 64, 48, 14, 160, 84, 45, 49, 187, 65, 237, 138, 101, 1, 76, 112, 10, 195, 214, 75, 121, 78, 222, 254, 46, 7, 230, 21, 164, 21, 230, 223, 57, 31, 75, 90, 160, 32, 48, 180, 58, 36, 100, 120, 248, 246, 185, 159, 16, 88, 197, 64, 48, 6, 80, 90, 22, 147, 234, 134, 43, 87, 106, 108, 39, 201, 193, 174, 150, 218, 170, 69, 139, 210, 79, 68, 34, 90, 235, 233, 169, 81, 105, 88, 169, 38, 200, 1, 138, 203, 43, 72, 219, 155, 127, 58, 49, 62, 55, 48, 244, 67, 173, 193, 58, 144, 119, 150, 11, 4, 104, 194, 255, 62, 172, 204, 19, 15, 56, 22, 194, 152, 8, 226, 223, 209, 149, 26, 59, 122, 8, 172, 3, 126, 159, 125, 72, 13, 112, 94, 135, 88, 128, 217, 156, 167, 64, 200, 254, 198, 219, 92, 188, 37, 41, 75, 30, 30, 178, 104, 145, 205, 6, 49, 208, 210, 200, 249, 85, 216, 83, 67, 101, 220, 246, 27, 114, 0, 8, 51, 247, 219, 91, 103, 234, 216, 41, 108, 24, 90, 195, 95, 232, 179, 1, 239, 132, 6, 91, 252, 160, 14, 48, 42, 205, 8, 5, 87, 20, 185, 242, 236, 153, 235, 251, 243, 146, 120, 227, 19, 6, 105, 73, 32, 237, 195, 54, 181, 85, 226, 55, 52, 2, 80, 46, 73, 5, 127, 82, 180, 171, 189, 162, 70, 78, 161, 30, 202, 128, 229, 83, 123, 163, 255, 169, 147, 164, 33, 160, 159, 14, 36, 28, 248, 60, 34, 127, 167, 22, 108, 222, 153, 177, 153, 0, 32, 196, 1, 186, 177, 203, 21, 76, 100, 238, 178, 67, 210, 147, 209, 233, 226, 17, 128, 114, 239, 120, 51, 246, 39, 61, 163, 214, 43, 202, 108, 234, 128, 66, 12, 0, 79, 74, 203, 212, 186, 65, 101, 15, 63, 56, 90, 6, 201, 160, 153, 76, 29, 128, 117, 218, 41, 224, 5, 208, 104, 9, 231, 82, 188, 160, 156, 226, 173, 103, 147, 14, 175, 79, 223, 47, 177, 222, 22, 215, 215, 215, 219, 203, 64, 76, 132, 25, 122, 22, 241, 135, 166, 93, 19, 111, 110, 37, 157, 128, 5, 80, 40, 8, 2, 52, 4, 10, 143, 105, 147, 43, 68, 48, 120, 143, 76, 149, 20, 151, 18, 109, 46, 222, 186, 55, 41, 235, 180, 60, 60, 60, 44, 36, 4, 186, 129, 109, 88, 172, 175, 108, 0, 0, 123, 33, 12, 107, 53, 129, 125, 157, 144, 244, 108, 232, 151, 241, 173, 117, 66, 12, 80, 207, 2, 0, 130, 14, 42, 161, 207, 134, 157, 60, 140, 48, 249, 155, 81, 80, 113, 218, 150, 228, 172, 251, 242, 240, 8, 97, 40, 59, 18, 134, 132, 64, 39, 50, 232, 173, 32, 210, 9, 8, 64, 169, 36, 213, 84, 55, 186, 124, 240, 111, 142, 40, 234, 170, 126, 86, 133, 1, 236, 133, 152, 69, 128, 134, 176, 18, 16, 84, 204, 164, 0, 16, 162, 55, 201, 61, 114, 5, 48, 21, 135, 134, 182, 144, 165, 213, 116, 119, 227, 97, 128, 52, 67, 82, 8, 89, 127, 239, 120, 19, 59, 52, 217, 231, 5, 67, 243, 254, 43, 123, 66, 187, 171, 12, 99, 157, 128, 141, 130, 174, 157, 15, 201, 0, 249, 200, 160, 73, 0, 176, 4, 2, 47, 50, 146, 146, 105, 196, 97, 28, 113, 4, 120, 28, 65, 252, 171, 89, 127, 242, 88, 156, 148, 28, 24, 98, 96, 123, 161, 162, 125, 84, 10, 128, 105, 106, 12, 56, 177, 9, 193, 199, 127, 10, 64, 10, 94, 206, 30, 32, 104, 17, 58, 25, 200, 42, 65, 245, 245, 126, 160, 48, 240, 23, 218, 67, 196, 62, 181, 138, 143, 229, 100, 189, 125, 175, 39, 0, 159, 2, 102, 205, 29, 39, 255, 125, 208, 147, 224, 235, 63, 5, 32, 131, 129, 47, 16, 8, 191, 153, 8, 155, 173, 184, 23, 138, 65, 146, 171, 171, 18, 164, 201, 130, 106, 97, 245, 104, 248, 73, 159, 174, 151, 72, 55, 135, 189, 179, 146, 67, 16, 112, 238, 80, 208, 166, 249, 142, 218, 52, 255, 248, 252, 73, 94, 207, 17, 38, 120, 235, 37, 28, 157, 201, 217, 12, 24, 182, 217, 108, 121, 251, 143, 157, 201, 56, 180, 0, 222, 230, 102, 189, 245, 114, 88, 62, 222, 154, 33, 191, 36, 110, 198, 155, 134, 10, 0, 176, 180, 67, 25, 114, 119, 178, 191, 147, 2, 160, 145, 138, 16, 124, 37, 215, 108, 66, 162, 138, 194, 48, 124, 208, 169, 193, 188, 14, 168, 145, 162, 205, 24, 106, 150, 63, 76, 136, 98, 17, 52, 149, 25, 53, 9, 149, 164, 17, 41, 73, 181, 236, 7, 202, 141, 185, 136, 114, 165, 166, 82, 32, 228, 54, 132, 112, 219, 230, 156, 171, 134, 83, 212, 232, 74, 161, 64, 102, 102, 151, 138, 144, 110, 148, 161, 12, 21, 165, 247, 124, 115, 244, 202, 205, 159, 153, 46, 67, 139, 222, 129, 81, 231, 220, 123, 223, 231, 251, 238, 249, 206, 185, 231, 56, 0, 128, 195, 44, 250, 224, 50, 138, 112, 249, 208, 163, 11, 189, 158, 6, 27, 139, 12, 21, 220, 241, 238, 215, 172, 17, 190, 124, 74, 113, 30, 107, 119, 176, 154, 220, 48, 141, 67, 131, 115, 174, 178, 46, 26, 3, 50, 124, 126, 191, 143, 228, 143, 42, 3, 6, 193, 15, 60, 148, 206, 142, 159, 94, 89, 92, 57, 219, 210, 223, 211, 212, 153, 206, 4, 109, 254, 80, 77, 203, 190, 186, 184, 100, 132, 143, 142, 233, 124, 95, 125, 159, 31, 104, 201, 114, 14, 201, 34, 88, 181, 79, 6, 48, 6, 48, 154, 147, 98, 223, 33, 33, 130, 241, 51, 139, 139, 43, 231, 30, 61, 125, 237, 105, 160, 61, 55, 161, 166, 4, 149, 205, 171, 149, 185, 75, 27, 225, 203, 145, 105, 184, 185, 139, 241, 187, 89, 67, 168, 66, 89, 130, 11, 64, 40, 173, 195, 195, 72, 100, 52, 22, 49, 1, 16, 193, 137, 202, 87, 61, 77, 87, 211, 109, 212, 51, 97, 46, 76, 61, 197, 83, 185, 252, 93, 86, 198, 23, 229, 63, 156, 244, 50, 155, 179, 59, 107, 211, 0, 24, 148, 12, 163, 246, 193, 128, 156, 16, 112, 122, 134, 30, 83, 6, 136, 224, 217, 93, 10, 28, 1, 40, 115, 243, 1, 142, 254, 220, 121, 233, 79, 3, 19, 252, 167, 63, 22, 117, 98, 36, 109, 119, 173, 2, 64, 150, 191, 154, 16, 146, 187, 170, 112, 157, 12, 127, 76, 0, 176, 141, 216, 32, 235, 219, 236, 206, 59, 106, 126, 126, 54, 210, 143, 21, 194, 244, 116, 210, 69, 52, 117, 54, 7, 71, 7, 200, 31, 28, 64, 24, 197, 156, 84, 123, 223, 70, 235, 246, 24, 0, 224, 237, 135, 185, 216, 182, 84, 51, 106, 114, 85, 239, 131, 191, 90, 37, 7, 235, 108, 92, 176, 91, 174, 5, 114, 87, 227, 49, 16, 228, 34, 197, 35, 231, 36, 159, 1, 96, 77, 228, 63, 63, 175, 194, 31, 146, 246, 180, 89, 89, 86, 133, 204, 101, 215, 5, 236, 240, 222, 16, 77, 8, 115, 165, 167, 186, 247, 32, 42, 159, 2, 176, 238, 159, 55, 79, 19, 51, 236, 35, 225, 211, 86, 105, 41, 54, 138, 4, 175, 42, 154, 179, 195, 85, 105, 64, 253, 72, 74, 74, 190, 117, 152, 234, 199, 50, 128, 224, 217, 23, 164, 191, 41, 124, 244, 252, 96, 29, 3, 29, 235, 118, 5, 39, 131, 127, 106, 46, 144, 90, 219, 201, 184, 176, 10, 160, 147, 191, 42, 62, 35, 124, 249, 154, 44, 187, 33, 151, 185, 159, 30, 23, 157, 74, 222, 82, 69, 111, 123, 15, 91, 204, 128, 240, 147, 127, 228, 169, 128, 226, 143, 132, 79, 0, 131, 165, 221, 224, 67, 146, 247, 238, 219, 90, 54, 223, 73, 7, 1, 88, 244, 15, 27, 189, 143, 194, 7, 0, 4, 2, 170, 3, 188, 118, 144, 197, 91, 224, 35, 127, 115, 239, 83, 37, 135, 123, 128, 127, 217, 233, 240, 0, 4, 137, 171, 119, 37, 106, 177, 146, 1, 129, 241, 175, 53, 47, 28, 254, 16, 89, 155, 170, 222, 39, 147, 15, 17, 72, 234, 19, 48, 238, 40, 75, 0, 228, 239, 12, 111, 238, 125, 235, 195, 46, 49, 32, 5, 181, 116, 237, 56, 1, 224, 254, 183, 170, 77, 82, 216, 147, 191, 52, 133, 12, 128, 228, 116, 28, 22, 31, 0, 21, 191, 211, 136, 31, 0, 102, 77, 166, 122, 184, 47, 62, 0, 66, 240, 189, 61, 89, 213, 213, 206, 106, 104, 21, 178, 111, 169, 209, 199, 76, 196, 5, 0, 254, 13, 253, 121, 107, 82, 46, 82, 96, 107, 185, 202, 210, 185, 47, 46, 0, 88, 26, 183, 95, 90, 215, 183, 237, 85, 123, 32, 62, 0, 144, 30, 53, 107, 188, 170, 224, 95, 3, 8, 93, 236, 46, 93, 236, 226, 255, 31, 125, 157, 47, 118, 0, 161, 67, 72, 32, 189, 235, 82, 220, 144, 78, 141, 230, 131, 77, 237, 166, 203, 141, 140, 140, 232, 127, 155, 1, 17, 221, 199, 98, 251, 63, 213, 87, 60, 18, 244, 24, 0, 24, 196, 133, 216, 120, 23, 194, 184, 50, 163, 70, 211, 7, 155, 28, 229, 241, 155, 9, 224, 203, 246, 28, 61, 194, 240, 91, 148, 0, 130, 231, 123, 221, 110, 239, 77, 222, 225, 118, 151, 228, 240, 138, 62, 183, 251, 161, 106, 2, 72, 35, 154, 220, 111, 174, 243, 17, 174, 148, 95, 114, 207, 139, 131, 117, 101, 153, 80, 209, 231, 117, 87, 192, 205, 240, 47, 190, 87, 112, 185, 224, 197, 3, 236, 251, 69, 7, 160, 243, 198, 122, 45, 84, 95, 44, 206, 107, 41, 245, 183, 217, 113, 45, 116, 165, 68, 36, 40, 0, 81, 162, 133, 82, 180, 107, 55, 249, 117, 5, 203, 111, 183, 105, 41, 109, 29, 17, 32, 161, 243, 163, 5, 218, 132, 230, 101, 60, 97, 253, 98, 236, 121, 189, 150, 50, 53, 17, 42, 207, 225, 251, 163, 205, 64, 78, 90, 226, 88, 90, 78, 126, 121, 98, 102, 121, 99, 254, 181, 196, 153, 52, 121, 174, 74, 78, 225, 68, 230, 204, 88, 90, 49, 63, 178, 14, 208, 145, 56, 51, 86, 168, 14, 16, 56, 183, 112, 42, 115, 172, 66, 168, 104, 1, 94, 124, 48, 148, 57, 51, 49, 245, 245, 50, 178, 22, 21, 0, 162, 248, 77, 125, 249, 242, 168, 15, 131, 113, 124, 161, 12, 113, 89, 205, 114, 98, 98, 9, 134, 240, 39, 16, 212, 178, 153, 217, 137, 51, 32, 72, 78, 128, 32, 72, 32, 128, 195, 99, 200, 229, 120, 9, 8, 2, 23, 12, 250, 210, 238, 21, 224, 106, 154, 84, 204, 54, 217, 251, 248, 61, 219, 122, 27, 151, 51, 76, 254, 38, 104, 186, 246, 233, 243, 201, 247, 249, 67, 87, 63, 73, 228, 140, 247, 67, 134, 78, 211, 79, 44, 80, 160, 145, 80, 45, 173, 62, 16, 227, 194, 218, 231, 0, 116, 55, 140, 69, 179, 157, 3, 116, 71, 146, 217, 123, 18, 230, 2, 244, 34, 198, 184, 231, 79, 252, 26, 169, 60, 27, 130, 198, 86, 34, 115, 118, 53, 44, 225, 204, 142, 17, 183, 215, 138, 61, 164, 218, 38, 98, 156, 33, 107, 149, 75, 242, 242, 102, 88, 114, 83, 37, 119, 197, 179, 250, 224, 220, 156, 22, 17, 104, 129, 5, 242, 107, 90, 87, 169, 242, 84, 8, 222, 7, 17, 218, 126, 251, 0, 96, 118, 131, 136, 155, 245, 60, 194, 83, 71, 178, 237, 9, 217, 59, 90, 161, 106, 111, 96, 196, 162, 7, 49, 87, 37, 49, 7, 65, 6, 109, 48, 80, 0, 247, 4, 160, 211, 78, 173, 73, 9, 0, 62, 112, 109, 113, 18, 230, 206, 148, 124, 169, 229, 193, 217, 97, 100, 245, 77, 105, 207, 193, 161, 74, 10, 15, 51, 190, 166, 176, 86, 8, 18, 84, 115, 128, 144, 172, 49, 138, 133, 175, 131, 1, 125, 30, 192, 7, 128, 94, 100, 94, 132, 217, 143, 133, 189, 2, 99, 165, 39, 44, 152, 46, 68, 25, 0, 212, 113, 227, 145, 228, 163, 21, 56, 204, 5, 177, 148, 32, 202, 166, 125, 49, 24, 147, 23, 149, 1, 207, 1, 128, 31, 102, 118, 112, 208, 195, 167, 45, 79, 244, 11, 243, 140, 150, 124, 51, 155, 160, 201, 27, 156, 167, 138, 224, 131, 67, 190, 100, 57, 73, 19, 65, 162, 24, 237, 30, 194, 93, 73, 94, 49, 14, 80, 180, 4, 192, 37, 98, 246, 132, 205, 231, 134, 109, 115, 209, 215, 8, 85, 41, 216, 195, 136, 185, 13, 112, 217, 207, 68, 166, 132, 174, 135, 76, 12, 26, 170, 8, 82, 65, 152, 13, 130, 132, 121, 75, 190, 67, 101, 226, 52, 13, 238, 79, 3, 44, 110, 80, 58, 144, 128, 115, 35, 102, 220, 254, 206, 107, 176, 1, 39, 217, 95, 95, 136, 139, 37, 249, 1, 56, 66, 14, 66, 204, 21, 0, 253, 156, 32, 238, 76, 139, 127, 3, 154, 120, 112, 49, 66, 206, 12, 246, 208, 39, 1, 180, 101, 34, 154, 191, 184, 2, 0, 26, 180, 242, 8, 184, 72, 48, 46, 49, 172, 5, 53, 5, 240, 186, 137, 98, 113, 208, 96, 86, 8, 210, 153, 181, 234, 144, 114, 89, 99, 60, 175, 180, 218, 90, 42, 128, 39, 21, 160, 164, 103, 48, 132, 174, 218, 97, 8, 66, 244, 126, 34, 64, 94, 54, 17, 231, 82, 34, 206, 147, 206, 211, 74, 61, 182, 7, 80, 101, 103, 104, 84, 10, 253, 104, 128, 102, 142, 227, 67, 222, 164, 204, 117, 115, 24, 220, 70, 192, 221, 209, 201, 189, 4, 0, 182, 184, 179, 39, 7, 108, 197, 163, 46, 4, 63, 19, 96, 106, 66, 27, 222, 28, 3, 22, 115, 255, 93, 181, 66, 232, 218, 177, 229, 230, 69, 240, 186, 132, 190, 27, 51, 233, 87, 73, 37, 107, 140, 142, 16, 152, 199, 92, 30, 75, 84, 1, 165, 7, 67, 70, 157, 5, 89, 194, 224, 169, 250, 9, 41, 189, 26, 24, 155, 11, 178, 55, 112, 100, 214, 19, 0, 0, 219, 15, 163, 200, 238, 22, 69, 208, 49, 4, 198, 50, 90, 106, 10, 192, 29, 226, 152, 35, 140, 47, 122, 41, 128, 221, 182, 217, 60, 83, 58, 223, 54, 189, 53, 248, 206, 34, 160, 191, 193, 244, 76, 72, 215, 107, 122, 183, 105, 18, 81, 10, 19, 120, 247, 213, 200, 195, 91, 191, 117, 154, 240, 120, 46, 81, 31, 231, 245, 131, 105, 179, 145, 55, 7, 255, 101, 110, 68, 53, 93, 215, 171, 217, 160, 50, 0, 126, 43, 122, 58, 13, 95, 146, 177, 242, 176, 115, 145, 219, 165, 123, 210, 109, 69, 66, 55, 198, 227, 113, 27, 138, 166, 252, 149, 44, 252, 53, 16, 250, 119, 181, 40, 182, 63, 123, 232, 239, 67, 232, 157, 148, 2, 80, 183, 72, 53, 168, 135, 86, 138, 183, 247, 199, 157, 149, 7, 191, 201, 218, 47, 171, 48, 155, 255, 103, 215, 242, 127, 195, 1, 70, 29, 48, 234, 128, 81, 7, 140, 58, 96, 212, 1, 163, 14, 24, 117, 0, 213, 1, 0, 87, 162, 212, 25, 139, 217, 220, 95, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130} diff --git a/exp/tasks/png2bytes/macos_template_icon.png b/exp/tasks/png2bytes/macos_template_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f30e111d4db7ba2df058761edbcee5ed289b65c0 GIT binary patch literal 760 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!+5>z-T!HleK>)HQ{ucx~MYkl# zFPPyWw*Vizl#sup_}!G~4PH0P;*~@$pKQ%=otkI5clpBFFdyAxv-&$MHFusq;Of)* zkb!~mv!{z=NW|f{*K+fl3eda#;$n}V@=@c z-Q~R7uH@F}?F!*Jca;15S@xb4xBJ9e8hAzH;}RBDT>H3$@rbjHU8TOVzX_{HDD#gc zk6Yzmm`x6(bShryA2Nf&#k$C?#H?*jDIxd z?mEEOa-hj=iJrj(roxt;dijmVt4^MJSL46uzi+7f+Qv8MwtqcxU}}JrZvV+MZx>|< hdnTLMeD?Us`un`(fm>P9KY{6n!PC{xWt~$(69CzGm6rej literal 0 HcmV?d00001 diff --git a/exp/tasks/png2bytes/png2bytes.go b/exp/tasks/png2bytes/png2bytes.go new file mode 100644 index 000000000..b51a472b6 --- /dev/null +++ b/exp/tasks/png2bytes/png2bytes.go @@ -0,0 +1,38 @@ +package main + +import ( + "bytes" + "os" + "strconv" +) + +func main() { + + if len(os.Args) != 2 { + println("Please provide a filename") + os.Exit(1) + } + + data, err := os.ReadFile(os.Args[1]) + if err != nil { + println("Error reading file:", err.Error()) + os.Exit(1) + } + + var buffer bytes.Buffer + buffer.WriteString("var image = []byte{") + // Iterate over the bytes and print them out in decimal + for _, b := range data { + // convert byte to decimal + buffer.WriteString(strconv.Itoa(int(b)) + ", ") + } + buffer.WriteString("}\n") + + // write to file + err = os.WriteFile(os.Args[1]+".go", buffer.Bytes(), 0644) + if err != nil { + println("Error writing file:", err.Error()) + os.Exit(1) + } + +} From b1e8f2f88716e2210be92ba459e215a9fe9fdf4a Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 18 Dec 2022 23:06:31 +1100 Subject: [PATCH 41/85] Start of file dialogs --- exp/examples/dialogs/main.go | 57 ++++++++++++++ exp/examples/kitchensink/icon.png | Bin 1622 -> 0 bytes exp/examples/kitchensink/macos_icon.png | Bin 1212 -> 0 bytes exp/examples/kitchensink/main.go | 14 +--- exp/pkg/application/application.go | 26 ++++--- exp/pkg/application/dialogs.go | 96 ++++++++++++++++++++---- exp/pkg/application/dialogs_darwin.go | 94 ++++++++++++++++++++++- 7 files changed, 252 insertions(+), 35 deletions(-) delete mode 100644 exp/examples/kitchensink/icon.png delete mode 100644 exp/examples/kitchensink/macos_icon.png diff --git a/exp/examples/dialogs/main.go b/exp/examples/dialogs/main.go index f976f014f..1f1a8361b 100644 --- a/exp/examples/dialogs/main.go +++ b/exp/examples/dialogs/main.go @@ -135,6 +135,63 @@ func main() { dialog.Show() }) + openMenu := menu.AddSubmenu("Open") + openMenu.Add("Open File").OnClick(func(ctx *application.Context) { + result, _ := app.NewOpenFileDialog(). + CanChooseFiles(true). + Show() + if result != "" { + app.NewInfoDialog().SetMessage(result).Show() + } else { + app.NewInfoDialog().SetMessage("No file selected").Show() + } + }) + openMenu.Add("Open File (Show Hidden Files)").OnClick(func(ctx *application.Context) { + result, _ := app.NewOpenFileDialog(). + CanChooseFiles(true). + CanCreateDirectories(true). + ShowHiddenFiles(true). + Show() + if result != "" { + app.NewInfoDialog().SetMessage(result).Show() + } else { + app.NewInfoDialog().SetMessage("No file selected").Show() + } + }) + //openMenu.Add("Open Multiple Files (Show Hidden Files)").OnClick(func(ctx *application.Context) { + // result, _ := app.NewOpenMultipleFilesDialog(). + // CanChooseFiles(true). + // CanCreateDirectories(true). + // ShowHiddenFiles(true). + // Show() + // if len(result) > 0 { + // app.NewInfoDialog().SetMessage(strings.Join(result, ",")).Show() + // } else { + // app.NewInfoDialog().SetMessage("No file selected").Show() + // } + //}) + openMenu.Add("Open Directory").OnClick(func(ctx *application.Context) { + result, _ := app.NewOpenFileDialog(). + CanChooseDirectories(true). + Show() + if result != "" { + app.NewInfoDialog().SetMessage(result).Show() + } else { + app.NewInfoDialog().SetMessage("No directory selected").Show() + } + }) + openMenu.Add("Open Directory (Create Directories)").OnClick(func(ctx *application.Context) { + result, _ := app.NewOpenFileDialog(). + CanChooseDirectories(true). + CanCreateDirectories(true). + Show() + if result != "" { + app.NewInfoDialog().SetMessage(result).Show() + } else { + app.NewInfoDialog().SetMessage("No directory selected").Show() + } + }) + app.SetMenu(menu) app.NewWindow() diff --git a/exp/examples/kitchensink/icon.png b/exp/examples/kitchensink/icon.png deleted file mode 100644 index fc492c9167cce9c272f98bf99207d0efff1d1c1a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1622 zcmV-c2C4apP)?9E5by_tm=H)BK!2&G8Wn%g z1REfMKm>jvR4h%YDEwl01TgZle?-$?nBFt(Ztk8lvpYj`ldheUe8TR%=j?p%mzjHK z?ykvXgb_v$>U*@FR5X( zImyGEK7E?h0m2M;^5luMy}j*{j*bpeS6Nv}@_1nR#x?iv-zRyPuC6Xp2M9CZ`+N6@ z2uyQxGpXzE?#axiS!mW{$10bvHTwY3o;n2L%Dr<#I-0+NHt&vQ25`t|E12Xp)O zZKBVPFavJgxrl#^2vxT3J~kIXpj2PO_&R<Ak5LDN9Ejvgap#3 zMpo9}2EZNT=H@2p=fSIt62c5Pd-g05go%oZl5<;ITS=c9Sy@?fjXQ(a*ViSR%|>)# zgc*>Uno2}rEEbEL`)cYH=~Ls}xpQ*O-Me>5AI}T6JYr2s2s0olDT#>UfeFgj*H69- za37#HCuC-3%6D}$Gc%-*r?9Y)Xi`F$0mqLYC!%=P*4E_7k9`*D1JqW9GiT07M~)mJ z?L6?=X0w@SQbL#khYuen!gv-I7UaC);bGGE?%g}7w6v7818~1^<;oS(&hzNeBcewQ zVFpA-MiOB>v$M1EB(<@zLHgi9>hk5wq#ek}$dH~seM;JS>=UIHgc-1J-##LYXKHFn zD!Futv;(J3rK_F+a0x6fE|PXTaAv`6HP)ksFazKkgozFdv@<$7Dm{DljI=K;ElGZU zeo|Rk8R-LV-n>cLcwlwFT3jK_0QfJsdbS4xV6wvP4(y?hhlYko8xK4mU@fi? zW&kWztE;O-pdB@H>^nYc6P;Qe@b>Ln$;ZcsXmN!w1AzDM-xHCp`0(L_6ciLB*IvDP zmGrvT0ICg zz!NYG*o^^fg8Bwtehvig=68aVlapVv>+er^>*=t$WQL8&Y|;~~U~fc3#IWg~pPPCp zvi9WU$x zvFrgX?%%(EA}uYgijBbnmoy%m=73^`A6!EWDJj4;9oBmQUc7aDot UG_K_hc>n+a07*qoM6N<$g0pSuE&u=k diff --git a/exp/examples/kitchensink/macos_icon.png b/exp/examples/kitchensink/macos_icon.png deleted file mode 100644 index 659d860e141b3bbf9139c9290f0fe57a78fbe3e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1212 zcmV;t1Vj6YP)#O?|gIZHH`tSTp#>6n{nBD>~F8L_Fi+YDN}m&>eZ`P zuU0EUm5EN^OOb3Qf0O>72n%PS(CCznS;45 zDZPie7#}IA4*7)`@1pd5T&m2#c%xF&G>msq>0e?t#HC1xdG3RHo99PThg|RbYDu60FOngUozP>yDE}aJo_nEZ z6{$hKk<2eX2{hmk83fr3Jr9x^WCQeUBQ?l#zQ;=f4cJcxK^}#kH%JYF1{@_d$ZFr? zC4mO)CW9cu!&x8CRDLEk$UUy-Lgg1y-}dC$0VMP1J%fd)KG212e*wYIkK1IaV)bg%I_$$LKe zXCf{MG++Z62w9P8uO+!0ccdQs#dwzFJrllVm?Y4ETggDk;Cb}#L6XZ+8!*b?Kb1uj zr#69-ht=20g(10t+V4jny?qibsUU{6vjrGct zB<^_~=gCO|4Om77^L#7Ss_Yq(vkR%mNZhztd7H#NgA-*NNuU9?XMlrw?8LW`#Elyz ze+1aSz$p^1IjPLVd2*6K18fIooD5j=sqzkqpH?nVHj$jMm&80raF!-XpaFJq({ycb z2H438tu;hvvF8DP@7pU99+ z{4Qy$O8-7Z@}oF}GmMf18(^OZ4%x(eu6HxZk796fRU!#C-~<`6iA}C|3&}U}l|tA3 znk2ynd_e}yaaLL4dY>jWP3-Zn-BuE8z%eptj$_cfmDJ=ISC;$!wvu22J|x5Dz$NlF ztGzX!`Q8#qumSIqVRNj6-Vy`0`rZ;rumNqBxsBtbx6PueVb>DFb4RHp*nl>BcE&-{ z`wXdLypO#ll3)W~CId6BBfV`6cm#V(B*6wePXyqrK9jUF;4SPcl>{5Giwuq2gncHB? +extern void openFileDialogCallback(uint id, char* path); +extern void openFileDialogCallbackEnd(uint id); + static void showAboutBox(char* title, char *message, void *icon, int length) { // run on main thread @@ -99,9 +102,46 @@ static void alertAddButton(void *dialog, char *label, bool isDefault, bool isCan } } +static void showOpenFileDialog(unsigned int dialogID, bool canChooseFiles, bool canChooseDirectories, bool canCreateDirectories, bool showHiddenFiles, bool allowsMultipleSelection) { + + // run on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + NSOpenPanel *panel = [NSOpenPanel openPanel]; + + [panel setCanChooseFiles:canChooseFiles]; + [panel setCanChooseDirectories:canChooseDirectories]; + [panel setCanCreateDirectories:canCreateDirectories]; + [panel setShowsHiddenFiles:showHiddenFiles]; + [panel setAllowsMultipleSelection:allowsMultipleSelection]; + + + // Show panel + [panel beginWithCompletionHandler:^(NSInteger result) { + const char *path = NULL; + if (result == NSModalResponseOK) { + if (allowsMultipleSelection) { + NSArray *urls = [panel URLs]; + for (NSURL *url in urls) { + path = [[url path] UTF8String]; + openFileDialogCallback(dialogID, (char *)path); + } + + } else { + NSURL *url = [panel URL]; + path = [[url path] UTF8String]; + openFileDialogCallback(dialogID, (char *)path); + } + } + openFileDialogCallbackEnd(dialogID); + }]; + }); +} + */ import "C" -import "unsafe" +import ( + "unsafe" +) const NSAlertStyleWarning = C.int(0) const NSAlertStyleInformational = C.int(1) @@ -123,7 +163,7 @@ func (m *macosApp) showAboutDialog(title string, message string, icon []byte) { } type macosDialog struct { - dialog *Dialog + dialog *MessageDialog nsDialog unsafe.Pointer } @@ -188,8 +228,56 @@ func (m *macosDialog) show() { } -func newDialogImpl(d *Dialog) *macosDialog { +func newDialogImpl(d *MessageDialog) *macosDialog { return &macosDialog{ dialog: d, } } + +type macosOpenFileDialog struct { + dialog *OpenFileDialog +} + +func newOpenFileDialogImpl(d *OpenFileDialog) *macosOpenFileDialog { + return &macosOpenFileDialog{ + dialog: d, + } +} + +func (m *macosOpenFileDialog) show() ([]string, error) { + openFileResponses[dialogID] = make(chan string) + C.showOpenFileDialog(C.uint(m.dialog.id), + C.bool(m.dialog.canChooseFiles), + C.bool(m.dialog.canChooseDirectories), + C.bool(m.dialog.canCreateDirectories), + C.bool(m.dialog.showHiddenFiles), + C.bool(m.dialog.allowsMultipleSelection)) + var result []string + for filename := range openFileResponses[m.dialog.id] { + result = append(result, filename) + } + return result, nil +} + +//export openFileDialogCallback +func openFileDialogCallback(id C.uint, path *C.char) { + // Covert the path to a string + filePath := C.GoString(path) + // put response on channel + channel, ok := openFileResponses[uint(id)] + if ok { + channel <- filePath + } else { + panic("No channel found for open file dialog") + } +} + +//export openFileDialogCallbackEnd +func openFileDialogCallbackEnd(id C.uint) { + channel, ok := openFileResponses[uint(id)] + if ok { + close(channel) + } else { + panic("No channel found for open file dialog") + } +} From ea1f0862899d6dfef6e54800fffcd41b12eee22e Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Mon, 19 Dec 2022 08:26:59 +1100 Subject: [PATCH 42/85] OpenDialog attach to window & multiple files selection --- exp/examples/dialogs/main.go | 47 ++++++++++------ exp/pkg/application/dialogs.go | 26 ++++++++- exp/pkg/application/dialogs_darwin.go | 59 ++++++++++++-------- exp/tasks/png2bytes/macos_template_icon.png | Bin 760 -> 0 bytes 4 files changed, 91 insertions(+), 41 deletions(-) delete mode 100644 exp/tasks/png2bytes/macos_template_icon.png diff --git a/exp/examples/dialogs/main.go b/exp/examples/dialogs/main.go index 1f1a8361b..d6c40a3a1 100644 --- a/exp/examples/dialogs/main.go +++ b/exp/examples/dialogs/main.go @@ -3,6 +3,7 @@ package main import ( _ "embed" "log" + "strings" "github.com/wailsapp/wails/exp/pkg/application" ) @@ -139,7 +140,7 @@ func main() { openMenu.Add("Open File").OnClick(func(ctx *application.Context) { result, _ := app.NewOpenFileDialog(). CanChooseFiles(true). - Show() + PromptForSingleFile() if result != "" { app.NewInfoDialog().SetMessage(result).Show() } else { @@ -151,29 +152,42 @@ func main() { CanChooseFiles(true). CanCreateDirectories(true). ShowHiddenFiles(true). - Show() + PromptForSingleFile() if result != "" { app.NewInfoDialog().SetMessage(result).Show() } else { app.NewInfoDialog().SetMessage("No file selected").Show() } }) - //openMenu.Add("Open Multiple Files (Show Hidden Files)").OnClick(func(ctx *application.Context) { - // result, _ := app.NewOpenMultipleFilesDialog(). - // CanChooseFiles(true). - // CanCreateDirectories(true). - // ShowHiddenFiles(true). - // Show() - // if len(result) > 0 { - // app.NewInfoDialog().SetMessage(strings.Join(result, ",")).Show() - // } else { - // app.NewInfoDialog().SetMessage("No file selected").Show() - // } - //}) + openMenu.Add("Open File (Attach to window)").OnClick(func(ctx *application.Context) { + result, _ := app.NewOpenFileDialog(). + CanChooseFiles(true). + CanCreateDirectories(true). + ShowHiddenFiles(true). + AttachToWindow(app.GetCurrentWindow()). + PromptForSingleFile() + if result != "" { + app.NewInfoDialog().SetMessage(result).Show() + } else { + app.NewInfoDialog().SetMessage("No file selected").Show() + } + }) + openMenu.Add("Open Multiple Files (Show Hidden Files)").OnClick(func(ctx *application.Context) { + result, _ := app.NewOpenFileDialog(). + CanChooseFiles(true). + CanCreateDirectories(true). + ShowHiddenFiles(true). + PromptForMultipleFiles() + if len(result) > 0 { + app.NewInfoDialog().SetMessage(strings.Join(result, ",")).Show() + } else { + app.NewInfoDialog().SetMessage("No file selected").Show() + } + }) openMenu.Add("Open Directory").OnClick(func(ctx *application.Context) { result, _ := app.NewOpenFileDialog(). CanChooseDirectories(true). - Show() + PromptForSingleFile() if result != "" { app.NewInfoDialog().SetMessage(result).Show() } else { @@ -184,7 +198,7 @@ func main() { result, _ := app.NewOpenFileDialog(). CanChooseDirectories(true). CanCreateDirectories(true). - Show() + PromptForSingleFile() if result != "" { app.NewInfoDialog().SetMessage(result).Show() } else { @@ -194,6 +208,7 @@ func main() { app.SetMenu(menu) + app.NewWindow() app.NewWindow() err := app.Run() diff --git a/exp/pkg/application/dialogs.go b/exp/pkg/application/dialogs.go index 680cf7898..6309f2f6c 100644 --- a/exp/pkg/application/dialogs.go +++ b/exp/pkg/application/dialogs.go @@ -124,6 +124,7 @@ type OpenFileDialog struct { canCreateDirectories bool showHiddenFiles bool allowsMultipleSelection bool + window *Window impl openFileDialogImpl } @@ -148,12 +149,31 @@ func (d *OpenFileDialog) ShowHiddenFiles(showHiddenFiles bool) *OpenFileDialog { return d } -func (d *OpenFileDialog) Show() (string, error) { +func (d *OpenFileDialog) AttachToWindow(window *Window) *OpenFileDialog { + d.window = window + return d +} + +func (d *OpenFileDialog) PromptForSingleFile() (string, error) { + d.allowsMultipleSelection = false if d.impl == nil { d.impl = newOpenFileDialogImpl(d) } - result, err := d.impl.show() - return result[0], err + selection, err := d.impl.show() + var result string + if len(selection) > 0 { + result = selection[0] + } + + return result, err +} + +func (d *OpenFileDialog) PromptForMultipleFiles() ([]string, error) { + d.allowsMultipleSelection = true + if d.impl == nil { + d.impl = newOpenFileDialogImpl(d) + } + return d.impl.show() } func newOpenFileDialog() *OpenFileDialog { diff --git a/exp/pkg/application/dialogs_darwin.go b/exp/pkg/application/dialogs_darwin.go index 0c619231a..67eb8406c 100644 --- a/exp/pkg/application/dialogs_darwin.go +++ b/exp/pkg/application/dialogs_darwin.go @@ -102,7 +102,27 @@ static void alertAddButton(void *dialog, char *label, bool isDefault, bool isCan } } -static void showOpenFileDialog(unsigned int dialogID, bool canChooseFiles, bool canChooseDirectories, bool canCreateDirectories, bool showHiddenFiles, bool allowsMultipleSelection) { +static void processOpenFileDialogResults(NSOpenPanel *panel, NSInteger result, bool allowsMultipleSelection, uint dialogID) { + const char *path = NULL; + if (result == NSModalResponseOK) { + if (allowsMultipleSelection) { + NSArray *urls = [panel URLs]; + for (NSURL *url in urls) { + path = [[url path] UTF8String]; + openFileDialogCallback(dialogID, (char *)path); + } + + } else { + NSURL *url = [panel URL]; + path = [[url path] UTF8String]; + openFileDialogCallback(dialogID, (char *)path); + } + } + openFileDialogCallbackEnd(dialogID); +} + + +static void showOpenFileDialog(unsigned int dialogID, bool canChooseFiles, bool canChooseDirectories, bool canCreateDirectories, bool showHiddenFiles, bool allowsMultipleSelection, void *window) { // run on main thread dispatch_async(dispatch_get_main_queue(), ^{ @@ -114,26 +134,15 @@ static void showOpenFileDialog(unsigned int dialogID, bool canChooseFiles, bool [panel setShowsHiddenFiles:showHiddenFiles]; [panel setAllowsMultipleSelection:allowsMultipleSelection]; - - // Show panel - [panel beginWithCompletionHandler:^(NSInteger result) { - const char *path = NULL; - if (result == NSModalResponseOK) { - if (allowsMultipleSelection) { - NSArray *urls = [panel URLs]; - for (NSURL *url in urls) { - path = [[url path] UTF8String]; - openFileDialogCallback(dialogID, (char *)path); - } - - } else { - NSURL *url = [panel URL]; - path = [[url path] UTF8String]; - openFileDialogCallback(dialogID, (char *)path); - } - } - openFileDialogCallbackEnd(dialogID); - }]; + if (window != NULL) { + [panel beginSheetModalForWindow:(__bridge NSWindow *)window completionHandler:^(NSInteger result) { + processOpenFileDialogResults(panel, result, allowsMultipleSelection, dialogID); + }]; + } else { + [panel beginWithCompletionHandler:^(NSInteger result) { + processOpenFileDialogResults(panel, result, allowsMultipleSelection, dialogID); + }]; + } }); } @@ -246,12 +255,18 @@ func newOpenFileDialogImpl(d *OpenFileDialog) *macosOpenFileDialog { func (m *macosOpenFileDialog) show() ([]string, error) { openFileResponses[dialogID] = make(chan string) + nsWindow := unsafe.Pointer(nil) + if m.dialog.window != nil { + // get NSWindow from window + nsWindow = m.dialog.window.impl.(*macosWindow).nsWindow + } C.showOpenFileDialog(C.uint(m.dialog.id), C.bool(m.dialog.canChooseFiles), C.bool(m.dialog.canChooseDirectories), C.bool(m.dialog.canCreateDirectories), C.bool(m.dialog.showHiddenFiles), - C.bool(m.dialog.allowsMultipleSelection)) + C.bool(m.dialog.allowsMultipleSelection), + nsWindow) var result []string for filename := range openFileResponses[m.dialog.id] { result = append(result, filename) diff --git a/exp/tasks/png2bytes/macos_template_icon.png b/exp/tasks/png2bytes/macos_template_icon.png deleted file mode 100644 index f30e111d4db7ba2df058761edbcee5ed289b65c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 760 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!+5>z-T!HleK>)HQ{ucx~MYkl# zFPPyWw*Vizl#sup_}!G~4PH0P;*~@$pKQ%=otkI5clpBFFdyAxv-&$MHFusq;Of)* zkb!~mv!{z=NW|f{*K+fl3eda#;$n}V@=@c z-Q~R7uH@F}?F!*Jca;15S@xb4xBJ9e8hAzH;}RBDT>H3$@rbjHU8TOVzX_{HDD#gc zk6Yzmm`x6(bShryA2Nf&#k$C?#H?*jDIxd z?mEEOa-hj=iJrj(roxt;dijmVt4^MJSL46uzi+7f+Qv8MwtqcxU}}JrZvV+MZx>|< hdnTLMeD?Us`un`(fm>P9KY{6n!PC{xWt~$(69CzGm6rej From e7abe1c606f4ee21d533ea85cef9c85ddee84d6c Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Mon, 19 Dec 2022 21:17:50 +1100 Subject: [PATCH 43/85] Add Webview navigation events Add HTML/JS/CSS in config Add RenderHTML() Tidy up window delegate --- exp/examples/plain/main.go | 32 +++ exp/go.mod | 7 +- exp/go.sum | 9 - exp/pkg/application/app_delegate.h | 2 - exp/pkg/application/app_delegate.m | 27 +-- exp/pkg/application/application_darwin.go | 7 +- exp/pkg/application/keys.go | 68 +++++- exp/pkg/application/window.go | 17 +- exp/pkg/application/window_darwin.go | 103 +++++++--- exp/pkg/application/window_delegate.h | 2 +- exp/pkg/application/window_delegate.m | 41 ++-- exp/pkg/events/events.go | 240 +++++++++++----------- exp/pkg/events/events.h | 4 + exp/pkg/events/events.txt | 7 +- exp/pkg/options/window.go | 3 + exp/tasks/events/generate.go | 168 ++++++++------- 16 files changed, 447 insertions(+), 290 deletions(-) create mode 100644 exp/examples/plain/main.go diff --git a/exp/examples/plain/main.go b/exp/examples/plain/main.go new file mode 100644 index 000000000..64096a4b5 --- /dev/null +++ b/exp/examples/plain/main.go @@ -0,0 +1,32 @@ +package main + +import ( + _ "embed" + "log" + + "github.com/wailsapp/wails/exp/pkg/options" + + "github.com/wailsapp/wails/exp/pkg/application" +) + +func main() { + app := application.New() + + // Create window + app.NewWindowWithOptions(&options.Window{ + Title: "Plain Bundle", + EnableDevTools: true, + HTML: `Plain Bundle

Plain Bundle

This is a plain bundle. It has no frontend code.

`, + CSS: `body { background-color: rgba(255, 255, 255, 0); } .main { color: white; margin: 20%; }`, + Mac: &options.MacWindow{ + Backdrop: options.MacBackdropTranslucent, + TitleBar: options.TitleBarHiddenInset, + }, + }) + + err := app.Run() + + if err != nil { + log.Fatal(err) + } +} diff --git a/exp/go.mod b/exp/go.mod index 19cc91829..1969eb348 100644 --- a/exp/go.mod +++ b/exp/go.mod @@ -2,9 +2,4 @@ module github.com/wailsapp/wails/exp go 1.19 -require ( - github.com/leaanthony/clir v1.3.0 - github.com/samber/lo v1.36.0 -) - -require golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect +require github.com/leaanthony/clir v1.3.0 diff --git a/exp/go.sum b/exp/go.sum index eb2ed5fb8..ec90627a4 100644 --- a/exp/go.sum +++ b/exp/go.sum @@ -1,11 +1,2 @@ -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/leaanthony/clir v1.3.0 h1:L9nPDWrmc/qU9UWZZvRaFajWYuO0np9V5p+5gxyYno0= github.com/leaanthony/clir v1.3.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/samber/lo v1.36.0 h1:4LaOxH1mHnbDGhTVE0i1z8v/lWaQW8AIfOD3HU4mSaw= -github.com/samber/lo v1.36.0/go.mod h1:HLeWcJRRyLKp3+/XBJvOrerCQn9mhdKMHyd7IRlgeQ8= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M= -golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM= -golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/exp/pkg/application/app_delegate.h b/exp/pkg/application/app_delegate.h index db8021543..1d288bd6b 100644 --- a/exp/pkg/application/app_delegate.h +++ b/exp/pkg/application/app_delegate.h @@ -6,8 +6,6 @@ #import @interface AppDelegate : NSObject -@property NSApplicationActivationPolicy activationPolicy; -- (void)setApplicationActivationPolicy:(NSApplicationActivationPolicy)policy; @end #endif diff --git a/exp/pkg/application/app_delegate.m b/exp/pkg/application/app_delegate.m index 120efe38e..c3a7bdcde 100644 --- a/exp/pkg/application/app_delegate.m +++ b/exp/pkg/application/app_delegate.m @@ -1,31 +1,12 @@ //go:build darwin - #import "app_delegate.h" #import "../events/events.h" - @implementation AppDelegate - - (void)dealloc { [super dealloc]; } -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification -{ - [NSApp setActivationPolicy:self.activationPolicy]; - [NSApp activateIgnoringOtherApps:YES]; - - //callOnApplicationDidFinishLaunchingHandler(); - processApplicationEvent(EventApplicationDidFinishLaunching); - -} - - -- (void)setApplicationActivationPolicy:(NSApplicationActivationPolicy)policy -{ - self.activationPolicy = policy; -} - // GENERATED EVENTS START - (void)applicationDidBecomeActive:(NSNotification *)notification { processApplicationEvent(EventApplicationDidBecomeActive); @@ -59,6 +40,10 @@ processApplicationEvent(EventApplicationDidChangeStatusBarOrientation); } +- (void)applicationDidFinishLaunching:(NSNotification *)notification { + processApplicationEvent(EventApplicationDidFinishLaunching); +} + - (void)applicationDidHide:(NSNotification *)notification { processApplicationEvent(EventApplicationDidHide); } @@ -104,8 +89,4 @@ } // GENERATED EVENTS END - @end - - - diff --git a/exp/pkg/application/application_darwin.go b/exp/pkg/application/application_darwin.go index 355b37690..4699383fe 100644 --- a/exp/pkg/application/application_darwin.go +++ b/exp/pkg/application/application_darwin.go @@ -23,7 +23,11 @@ static void init(void) { } static void setActivationPolicy(int policy) { - [appDelegate setApplicationActivationPolicy:policy]; + [NSApp setActivationPolicy:policy]; +} + +static void activateIgnoringOtherApps() { + [NSApp activateIgnoringOtherApps:YES]; } static void run(void) { @@ -123,6 +127,7 @@ func newPlatformApp(appOptions *options.Application) *macosApp { } C.init() C.setActivationPolicy(C.int(appOptions.Mac.ActivationPolicy)) + C.activateIgnoringOtherApps() return &macosApp{ options: appOptions, } diff --git a/exp/pkg/application/keys.go b/exp/pkg/application/keys.go index 4670e1833..d7d1beaf7 100644 --- a/exp/pkg/application/keys.go +++ b/exp/pkg/application/keys.go @@ -4,8 +4,6 @@ import ( "fmt" "strconv" "strings" - - "github.com/samber/lo" ) // modifier is actually a string @@ -42,7 +40,59 @@ type accelerator struct { Modifiers []modifier } -var namedKeys = []string{"backspace", "tab", "return", "enter", "escape", "left", "right", "up", "down", "space", "delete", "home", "end", "page up", "page down", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "f32", "f33", "f34", "f35", "numlock"} +var namedKeys = map[string]struct{}{ + "backspace": {}, + "tab": {}, + "return": {}, + "enter": {}, + "escape": {}, + "left": {}, + "right": {}, + "up": {}, + "down": {}, + "space": {}, + "delete": {}, + "home": {}, + "end": {}, + "page up": {}, + "page down": {}, + "f1": {}, + "f2": {}, + "f3": {}, + "f4": {}, + "f5": {}, + "f6": {}, + "f7": {}, + "f8": {}, + "f9": {}, + "f10": {}, + "f11": {}, + "f12": {}, + "f13": {}, + "f14": {}, + "f15": {}, + "f16": {}, + "f17": {}, + "f18": {}, + "f19": {}, + "f20": {}, + "f21": {}, + "f22": {}, + "f23": {}, + "f24": {}, + "f25": {}, + "f26": {}, + "f27": {}, + "f28": {}, + "f29": {}, + "f30": {}, + "f31": {}, + "f32": {}, + "f33": {}, + "f34": {}, + "f35": {}, + "numlock": {}, +} func parseKey(key string) (string, bool) { @@ -55,7 +105,8 @@ func parseKey(key string) (string, bool) { } // Handle named keys - if lo.Contains(namedKeys, key) { + _, namedKey := namedKeys[key] + if namedKey { return key, true } @@ -89,6 +140,8 @@ func parseAccelerator(shortcut string) (*accelerator, error) { return nil, fmt.Errorf("no components given to validateComponents") } + modifiers := map[modifier]struct{}{} + // Check components for index, component := range components { @@ -109,10 +162,11 @@ func parseAccelerator(shortcut string) (*accelerator, error) { return nil, fmt.Errorf("'%s' is not a valid modifier", component) } // Save this data + modifiers[thisModifier] = struct{}{} + } + // return the keys as a slice + for thisModifier := range modifiers { result.Modifiers = append(result.Modifiers, thisModifier) } - - result.Modifiers = lo.Uniq(result.Modifiers) - return &result, nil } diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index 250767f58..2e90085e5 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -43,6 +43,7 @@ type windowImpl interface { close() zoom() minimize() + renderHTML(html string) } type Window struct { @@ -66,6 +67,12 @@ func getWindowID() uint { } func NewWindow(options *options.Window) *Window { + if options.Width == 0 { + options.Width = 800 + } + if options.Height == 0 { + options.Height = 600 + } return &Window{ id: getWindowID(), options: options, @@ -94,7 +101,7 @@ func (w *Window) SetSize(width, height int) { func (w *Window) Run() { w.implLock.Lock() - w.impl = newWindowImpl(w.id, w.options) + w.impl = newWindowImpl(w) w.implLock.Unlock() w.impl.run() } @@ -173,7 +180,6 @@ func (w *Window) ExecJS(js string) { w.impl.execJS(js) } -// Set Maximized func (w *Window) SetMaximized() { w.options.StartState = options.WindowStateMaximised if w.impl == nil { @@ -375,3 +381,10 @@ func (w *Window) Zoom() { } w.impl.zoom() } + +func (w *Window) RenderHTML(html string) { + if w.impl == nil { + return + } + w.impl.renderHTML(html) +} diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index 595f813f7..db0e187a4 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -45,6 +45,9 @@ void* windowNew(unsigned int id, int width, int height) { WKWebView* webView = [[WKWebView alloc] initWithFrame:frame configuration:config]; [view addSubview:webView]; + // support webview events + [webView setNavigationDelegate:delegate]; + // Ensure webview resizes with the window [webView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; @@ -229,14 +232,18 @@ void windowZoomOut(void* nsWindow) { } // Execute JS in NSWindow -void windowExecJS(void* nsWindow, char* js) { +void windowExecJS(void* nsWindow, const char* js) { +printf("windowExecJS\n"); // Execute JS on main thread dispatch_async(dispatch_get_main_queue(), ^{ +printf("windowExecJS 2\n"); + // Get window delegate WindowDelegate* delegate = (WindowDelegate*)[(NSWindow*)nsWindow delegate]; // Execute JS in webview + printf("windowExecJS: %s\n", js); [delegate.webView evaluateJavaScript:[NSString stringWithUTF8String:js] completionHandler:nil]; - free(js); + free((void*)js); }); } @@ -546,23 +553,47 @@ static void windowMaximize(void *window) { [(NSWindow*)window zoom:nil]; }); } + +// webviewRenderHTML renders the given HTML +static void windowRenderHTML(void *window, const char *html) { + dispatch_async(dispatch_get_main_queue(), ^{ + // get main window + NSWindow* nsWindow = (NSWindow*)window; + // get window delegate + WindowDelegate* windowDelegate = (WindowDelegate*)[nsWindow delegate]; + // render html + [(WKWebView*)windowDelegate.webView loadHTMLString:[NSString stringWithUTF8String:html] baseURL:nil]; + }); +} + +static void windowInjectCSS(void *window, const char *css) { + dispatch_async(dispatch_get_main_queue(), ^{ + // get main window + NSWindow* nsWindow = (NSWindow*)window; + // get window delegate + WindowDelegate* windowDelegate = (WindowDelegate*)[nsWindow delegate]; + // inject css + [(WKWebView*)windowDelegate.webView evaluateJavaScript:[NSString stringWithFormat:@"(function() { var style = document.createElement('style'); style.appendChild(document.createTextNode('%@')); document.head.appendChild(style); })();", [NSString stringWithUTF8String:css]] completionHandler:nil]; + free((void*)css); + }); +} + */ import "C" import ( "sync" "unsafe" + "github.com/wailsapp/wails/exp/pkg/events" + "github.com/wailsapp/wails/exp/pkg/options" ) var showDevTools = func(window unsafe.Pointer) {} type macosWindow struct { - id uint nsWindow unsafe.Pointer - options *options.Window - - // devtools + parent *Window } func (w *macosWindow) zoom() { @@ -603,12 +634,12 @@ func (w *macosWindow) toggleFullscreen() { func (w *macosWindow) reload() { //TODO: Implement - println("reload called on Window", w.id) + println("reload called on Window", w.parent.id) } func (w *macosWindow) forceReload() { //TODO: Implement - println("forceReload called on Window", w.id) + println("forceReload called on Window", w.parent.id) } func (w *macosWindow) center() { @@ -667,6 +698,7 @@ func (w *macosWindow) restoreWindow() { } func (w *macosWindow) execJS(js string) { + println("execJS called on Window", w.parent.id) C.windowExecJS(w.nsWindow, C.CString(js)) } @@ -678,10 +710,9 @@ func (w *macosWindow) setAlwaysOnTop(alwaysOnTop bool) { C.windowSetAlwaysOnTop(w.nsWindow, C.bool(alwaysOnTop)) } -func newWindowImpl(id uint, options *options.Window) *macosWindow { +func newWindowImpl(parent *Window) *macosWindow { result := &macosWindow{ - id: id, - options: options, + parent: parent, } return result } @@ -746,22 +777,22 @@ func (w *macosWindow) height() int { func (w *macosWindow) run() { DispatchOnMainThread(func() { - w.nsWindow = C.windowNew(C.uint(w.id), C.int(w.options.Width), C.int(w.options.Height)) - w.setTitle(w.options.Title) - w.setAlwaysOnTop(w.options.AlwaysOnTop) - w.setResizable(!w.options.DisableResize) - if w.options.MinWidth != 0 || w.options.MinHeight != 0 { - w.setMinSize(w.options.MinWidth, w.options.MinHeight) + w.nsWindow = C.windowNew(C.uint(w.parent.id), C.int(w.parent.options.Width), C.int(w.parent.options.Height)) + w.setTitle(w.parent.options.Title) + w.setAlwaysOnTop(w.parent.options.AlwaysOnTop) + w.setResizable(!w.parent.options.DisableResize) + if w.parent.options.MinWidth != 0 || w.parent.options.MinHeight != 0 { + w.setMinSize(w.parent.options.MinWidth, w.parent.options.MinHeight) } - if w.options.MaxWidth != 0 || w.options.MaxHeight != 0 { - w.setMaxSize(w.options.MaxWidth, w.options.MaxHeight) + if w.parent.options.MaxWidth != 0 || w.parent.options.MaxHeight != 0 { + w.setMaxSize(w.parent.options.MaxWidth, w.parent.options.MaxHeight) } - if w.options.EnableDevTools { + if w.parent.options.EnableDevTools { w.enableDevTools() } - w.setBackgroundColor(w.options.BackgroundColour) - if w.options.Mac != nil { - macOptions := w.options.Mac + w.setBackgroundColor(w.parent.options.BackgroundColour) + if w.parent.options.Mac != nil { + macOptions := w.parent.options.Mac switch macOptions.Backdrop { case options.MacBackdropTransparent: C.windowSetTransparent(w.nsWindow) @@ -785,7 +816,7 @@ func (w *macosWindow) run() { C.windowSetAppearanceTypeByName(w.nsWindow, C.CString(string(macOptions.Appearance))) } - switch w.options.StartState { + switch w.parent.options.StartState { case options.WindowStateMaximised: w.setMaximised() case options.WindowStateMinimised: @@ -798,9 +829,22 @@ func (w *macosWindow) run() { } C.windowCenter(w.nsWindow) - if w.options.URL != "" { - w.navigateToURL(w.options.URL) + if w.parent.options.URL != "" { + w.navigateToURL(w.parent.options.URL) } + // Ee need to wait for the HTML to load before we can execute the javascript + w.parent.On(events.Mac.WebViewDidFinishNavigation, func() { + if w.parent.options.JS != "" { + w.execJS(w.parent.options.JS) + } + if w.parent.options.CSS != "" { + C.windowInjectCSS(w.nsWindow, C.CString(w.parent.options.CSS)) + } + }) + if w.parent.options.HTML != "" { + w.renderHTML(w.parent.options.HTML) + } + C.windowShow(w.nsWindow) }) } @@ -827,3 +871,10 @@ func (w *macosWindow) position() (int, int) { func (w *macosWindow) destroy() { C.windowDestroy(w.nsWindow) } + +func (w *macosWindow) renderHTML(html string) { + // Convert HTML to C string + cHTML := C.CString(html) + // Render HTML + C.windowRenderHTML(w.nsWindow, cHTML) +} diff --git a/exp/pkg/application/window_delegate.h b/exp/pkg/application/window_delegate.h index c0446abee..3927efc6f 100644 --- a/exp/pkg/application/window_delegate.h +++ b/exp/pkg/application/window_delegate.h @@ -6,7 +6,7 @@ #import #import -@interface WindowDelegate : NSObject +@interface WindowDelegate : NSObject @property bool hideOnClose; @property (retain) WKWebView* webView; diff --git a/exp/pkg/application/window_delegate.m b/exp/pkg/application/window_delegate.m index 5a5488c4d..8f21e7086 100644 --- a/exp/pkg/application/window_delegate.m +++ b/exp/pkg/application/window_delegate.m @@ -5,14 +5,11 @@ // // Created by Lea Anthony on 10/10/21. // - #import #import #import "window_delegate.h" #import "../events/events.h" - extern void processMessage(unsigned int, const char*); - @implementation WindowDelegate - (BOOL)windowShouldClose:(NSWindow *)sender { if( self.hideOnClose ) { @@ -21,11 +18,9 @@ extern void processMessage(unsigned int, const char*); } return true; } - // Handle script messages from the external bridge - (void)userContentController:(nonnull WKUserContentController *)userContentController didReceiveScriptMessage:(nonnull WKScriptMessage *)message { NSString *m = message.body; - /* // TODO: Check for drag if ( [m isEqualToString:@"drag"] ) { @@ -38,12 +33,14 @@ extern void processMessage(unsigned int, const char*); return; } */ - const char *_m = [m UTF8String]; - processMessage(self.windowId, _m); } +- (void) mouseDown:(NSEvent*)someEvent { + NSLog(@"MOUSE DOWN!!!"); +} + // GENERATED EVENTS START - (void)windowDidBecomeKey:(NSNotification *)notification { processWindowEvent(self.windowId, EventWindowDidBecomeKey); @@ -337,19 +334,21 @@ extern void processMessage(unsigned int, const char*); processWindowEvent(self.windowId, EventWindowWillUseStandardFrame); } +- (void)webView:(WKWebView *)webview didStartProvisionalNavigation:(WKNavigation *)navigation { + processWindowEvent(self.windowId, EventWebViewDidStartProvisionalNavigation); +} + +- (void)webView:(WKWebView *)webview didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation { + processWindowEvent(self.windowId, EventWebViewDidReceiveServerRedirectForProvisionalNavigation); +} + +- (void)webView:(WKWebView *)webview didFinishNavigation:(WKNavigation *)navigation { + processWindowEvent(self.windowId, EventWebViewDidFinishNavigation); +} + +- (void)webView:(WKWebView *)webview didCommitNavigation:(WKNavigation *)navigation { + processWindowEvent(self.windowId, EventWebViewDidCommitNavigation); +} + // GENERATED EVENTS END - @end - - - - - - - - - - - - - diff --git a/exp/pkg/events/events.go b/exp/pkg/events/events.go index eaca310f8..f003e7c49 100644 --- a/exp/pkg/events/events.go +++ b/exp/pkg/events/events.go @@ -6,122 +6,126 @@ type WindowEventType uint var Mac = newMacEvents() type macEvents struct { - ApplicationDidBecomeActive ApplicationEventType - ApplicationDidChangeBackingProperties ApplicationEventType - ApplicationDidChangeEffectiveAppearance ApplicationEventType - ApplicationDidChangeIcon ApplicationEventType - ApplicationDidChangeOcclusionState ApplicationEventType - ApplicationDidChangeScreenParameters ApplicationEventType - ApplicationDidChangeStatusBarFrame ApplicationEventType - ApplicationDidChangeStatusBarOrientation ApplicationEventType - ApplicationDidFinishLaunching ApplicationEventType - ApplicationDidHide ApplicationEventType - ApplicationDidResignActive ApplicationEventType - ApplicationDidUnhide ApplicationEventType - ApplicationDidUpdate ApplicationEventType - ApplicationWillBecomeActive ApplicationEventType - ApplicationWillFinishLaunching ApplicationEventType - ApplicationWillHide ApplicationEventType - ApplicationWillResignActive ApplicationEventType - ApplicationWillTerminate ApplicationEventType - ApplicationWillUnhide ApplicationEventType - ApplicationWillUpdate ApplicationEventType - WindowDidBecomeKey WindowEventType - WindowDidBecomeMain WindowEventType - WindowDidBeginSheet WindowEventType - WindowDidChangeAlpha WindowEventType - WindowDidChangeBackingLocation WindowEventType - WindowDidChangeBackingProperties WindowEventType - WindowDidChangeCollectionBehavior WindowEventType - WindowDidChangeEffectiveAppearance WindowEventType - WindowDidChangeOcclusionState WindowEventType - WindowDidChangeOrderingMode WindowEventType - WindowDidChangeScreen WindowEventType - WindowDidChangeScreenParameters WindowEventType - WindowDidChangeScreenProfile WindowEventType - WindowDidChangeScreenSpace WindowEventType - WindowDidChangeScreenSpaceProperties WindowEventType - WindowDidChangeSharingType WindowEventType - WindowDidChangeSpace WindowEventType - WindowDidChangeSpaceOrderingMode WindowEventType - WindowDidChangeTitle WindowEventType - WindowDidChangeToolbar WindowEventType - WindowDidChangeVisibility WindowEventType - WindowDidClose WindowEventType - WindowDidDeminiaturize WindowEventType - WindowDidEndSheet WindowEventType - WindowDidEnterFullScreen WindowEventType - WindowDidEnterVersionBrowser WindowEventType - WindowDidExitFullScreen WindowEventType - WindowDidExitVersionBrowser WindowEventType - WindowDidExpose WindowEventType - WindowDidFocus WindowEventType - WindowDidMiniaturize WindowEventType - WindowDidMove WindowEventType - WindowDidOrderOffScreen WindowEventType - WindowDidOrderOnScreen WindowEventType - WindowDidResignKey WindowEventType - WindowDidResignMain WindowEventType - WindowDidResize WindowEventType - WindowDidUnfocus WindowEventType - WindowDidUpdate WindowEventType - WindowDidUpdateAlpha WindowEventType - WindowDidUpdateCollectionBehavior WindowEventType - WindowDidUpdateCollectionProperties WindowEventType - WindowDidUpdateShadow WindowEventType - WindowDidUpdateTitle WindowEventType - WindowDidUpdateToolbar WindowEventType - WindowDidUpdateVisibility WindowEventType - WindowWillBecomeKey WindowEventType - WindowWillBecomeMain WindowEventType - WindowWillBeginSheet WindowEventType - WindowWillChangeOrderingMode WindowEventType - WindowWillClose WindowEventType - WindowWillDeminiaturize WindowEventType - WindowWillEnterFullScreen WindowEventType - WindowWillEnterVersionBrowser WindowEventType - WindowWillExitFullScreen WindowEventType - WindowWillExitVersionBrowser WindowEventType - WindowWillFocus WindowEventType - WindowWillMiniaturize WindowEventType - WindowWillMove WindowEventType - WindowWillOrderOffScreen WindowEventType - WindowWillOrderOnScreen WindowEventType - WindowWillResignMain WindowEventType - WindowWillResize WindowEventType - WindowWillUnfocus WindowEventType - WindowWillUpdate WindowEventType - WindowWillUpdateAlpha WindowEventType - WindowWillUpdateCollectionBehavior WindowEventType - WindowWillUpdateCollectionProperties WindowEventType - WindowWillUpdateShadow WindowEventType - WindowWillUpdateTitle WindowEventType - WindowWillUpdateToolbar WindowEventType - WindowWillUpdateVisibility WindowEventType - WindowWillUseStandardFrame WindowEventType - MenuWillOpen ApplicationEventType - MenuDidOpen ApplicationEventType - MenuDidClose ApplicationEventType - MenuWillSendAction ApplicationEventType - MenuDidSendAction ApplicationEventType - MenuWillHighlightItem ApplicationEventType - MenuDidHighlightItem ApplicationEventType - MenuWillDisplayItem ApplicationEventType - MenuDidDisplayItem ApplicationEventType - MenuWillAddItem ApplicationEventType - MenuDidAddItem ApplicationEventType - MenuWillRemoveItem ApplicationEventType - MenuDidRemoveItem ApplicationEventType - MenuWillBeginTracking ApplicationEventType - MenuDidBeginTracking ApplicationEventType - MenuWillEndTracking ApplicationEventType - MenuDidEndTracking ApplicationEventType - MenuWillUpdate ApplicationEventType - MenuDidUpdate ApplicationEventType - MenuWillPopUp ApplicationEventType - MenuDidPopUp ApplicationEventType - MenuWillSendActionToItem ApplicationEventType - MenuDidSendActionToItem ApplicationEventType + ApplicationDidBecomeActive ApplicationEventType + ApplicationDidChangeBackingProperties ApplicationEventType + ApplicationDidChangeEffectiveAppearance ApplicationEventType + ApplicationDidChangeIcon ApplicationEventType + ApplicationDidChangeOcclusionState ApplicationEventType + ApplicationDidChangeScreenParameters ApplicationEventType + ApplicationDidChangeStatusBarFrame ApplicationEventType + ApplicationDidChangeStatusBarOrientation ApplicationEventType + ApplicationDidFinishLaunching ApplicationEventType + ApplicationDidHide ApplicationEventType + ApplicationDidResignActive ApplicationEventType + ApplicationDidUnhide ApplicationEventType + ApplicationDidUpdate ApplicationEventType + ApplicationWillBecomeActive ApplicationEventType + ApplicationWillFinishLaunching ApplicationEventType + ApplicationWillHide ApplicationEventType + ApplicationWillResignActive ApplicationEventType + ApplicationWillTerminate ApplicationEventType + ApplicationWillUnhide ApplicationEventType + ApplicationWillUpdate ApplicationEventType + WindowDidBecomeKey WindowEventType + WindowDidBecomeMain WindowEventType + WindowDidBeginSheet WindowEventType + WindowDidChangeAlpha WindowEventType + WindowDidChangeBackingLocation WindowEventType + WindowDidChangeBackingProperties WindowEventType + WindowDidChangeCollectionBehavior WindowEventType + WindowDidChangeEffectiveAppearance WindowEventType + WindowDidChangeOcclusionState WindowEventType + WindowDidChangeOrderingMode WindowEventType + WindowDidChangeScreen WindowEventType + WindowDidChangeScreenParameters WindowEventType + WindowDidChangeScreenProfile WindowEventType + WindowDidChangeScreenSpace WindowEventType + WindowDidChangeScreenSpaceProperties WindowEventType + WindowDidChangeSharingType WindowEventType + WindowDidChangeSpace WindowEventType + WindowDidChangeSpaceOrderingMode WindowEventType + WindowDidChangeTitle WindowEventType + WindowDidChangeToolbar WindowEventType + WindowDidChangeVisibility WindowEventType + WindowDidClose WindowEventType + WindowDidDeminiaturize WindowEventType + WindowDidEndSheet WindowEventType + WindowDidEnterFullScreen WindowEventType + WindowDidEnterVersionBrowser WindowEventType + WindowDidExitFullScreen WindowEventType + WindowDidExitVersionBrowser WindowEventType + WindowDidExpose WindowEventType + WindowDidFocus WindowEventType + WindowDidMiniaturize WindowEventType + WindowDidMove WindowEventType + WindowDidOrderOffScreen WindowEventType + WindowDidOrderOnScreen WindowEventType + WindowDidResignKey WindowEventType + WindowDidResignMain WindowEventType + WindowDidResize WindowEventType + WindowDidUnfocus WindowEventType + WindowDidUpdate WindowEventType + WindowDidUpdateAlpha WindowEventType + WindowDidUpdateCollectionBehavior WindowEventType + WindowDidUpdateCollectionProperties WindowEventType + WindowDidUpdateShadow WindowEventType + WindowDidUpdateTitle WindowEventType + WindowDidUpdateToolbar WindowEventType + WindowDidUpdateVisibility WindowEventType + WindowWillBecomeKey WindowEventType + WindowWillBecomeMain WindowEventType + WindowWillBeginSheet WindowEventType + WindowWillChangeOrderingMode WindowEventType + WindowWillClose WindowEventType + WindowWillDeminiaturize WindowEventType + WindowWillEnterFullScreen WindowEventType + WindowWillEnterVersionBrowser WindowEventType + WindowWillExitFullScreen WindowEventType + WindowWillExitVersionBrowser WindowEventType + WindowWillFocus WindowEventType + WindowWillMiniaturize WindowEventType + WindowWillMove WindowEventType + WindowWillOrderOffScreen WindowEventType + WindowWillOrderOnScreen WindowEventType + WindowWillResignMain WindowEventType + WindowWillResize WindowEventType + WindowWillUnfocus WindowEventType + WindowWillUpdate WindowEventType + WindowWillUpdateAlpha WindowEventType + WindowWillUpdateCollectionBehavior WindowEventType + WindowWillUpdateCollectionProperties WindowEventType + WindowWillUpdateShadow WindowEventType + WindowWillUpdateTitle WindowEventType + WindowWillUpdateToolbar WindowEventType + WindowWillUpdateVisibility WindowEventType + WindowWillUseStandardFrame WindowEventType + MenuWillOpen ApplicationEventType + MenuDidOpen ApplicationEventType + MenuDidClose ApplicationEventType + MenuWillSendAction ApplicationEventType + MenuDidSendAction ApplicationEventType + MenuWillHighlightItem ApplicationEventType + MenuDidHighlightItem ApplicationEventType + MenuWillDisplayItem ApplicationEventType + MenuDidDisplayItem ApplicationEventType + MenuWillAddItem ApplicationEventType + MenuDidAddItem ApplicationEventType + MenuWillRemoveItem ApplicationEventType + MenuDidRemoveItem ApplicationEventType + MenuWillBeginTracking ApplicationEventType + MenuDidBeginTracking ApplicationEventType + MenuWillEndTracking ApplicationEventType + MenuDidEndTracking ApplicationEventType + MenuWillUpdate ApplicationEventType + MenuDidUpdate ApplicationEventType + MenuWillPopUp ApplicationEventType + MenuDidPopUp ApplicationEventType + MenuWillSendActionToItem ApplicationEventType + MenuDidSendActionToItem ApplicationEventType + WebViewDidStartProvisionalNavigation WindowEventType + WebViewDidReceiveServerRedirectForProvisionalNavigation WindowEventType + WebViewDidFinishNavigation WindowEventType + WebViewDidCommitNavigation WindowEventType } func newMacEvents() macEvents { @@ -242,5 +246,9 @@ func newMacEvents() macEvents { MenuDidPopUp: 113, MenuWillSendActionToItem: 114, MenuDidSendActionToItem: 115, + WebViewDidStartProvisionalNavigation: 116, + WebViewDidReceiveServerRedirectForProvisionalNavigation: 117, + WebViewDidFinishNavigation: 118, + WebViewDidCommitNavigation: 119, } } diff --git a/exp/pkg/events/events.h b/exp/pkg/events/events.h index 85e700a95..02de910be 100644 --- a/exp/pkg/events/events.h +++ b/exp/pkg/events/events.h @@ -122,6 +122,10 @@ extern void processWindowEvent(unsigned int, unsigned int); #define EventMenuDidPopUp 113 #define EventMenuWillSendActionToItem 114 #define EventMenuDidSendActionToItem 115 +#define EventWebViewDidStartProvisionalNavigation 116 +#define EventWebViewDidReceiveServerRedirectForProvisionalNavigation 117 +#define EventWebViewDidFinishNavigation 118 +#define EventWebViewDidCommitNavigation 119 #endif \ No newline at end of file diff --git a/exp/pkg/events/events.txt b/exp/pkg/events/events.txt index 4eacfe99b..858bb2ad5 100644 --- a/exp/pkg/events/events.txt +++ b/exp/pkg/events/events.txt @@ -6,7 +6,7 @@ mac:ApplicationDidChangeOcclusionState mac:ApplicationDidChangeScreenParameters mac:ApplicationDidChangeStatusBarFrame mac:ApplicationDidChangeStatusBarOrientation -mac:ApplicationDidFinishLaunching! +mac:ApplicationDidFinishLaunching mac:ApplicationDidHide mac:ApplicationDidResignActive mac:ApplicationDidUnhide @@ -114,3 +114,8 @@ mac:MenuWillPopUp mac:MenuDidPopUp mac:MenuWillSendActionToItem mac:MenuDidSendActionToItem +mac:WebViewDidStartProvisionalNavigation +mac:WebViewDidReceiveServerRedirectForProvisionalNavigation +mac:WebViewDidFinishNavigation +mac:WebViewDidCommitNavigation + diff --git a/exp/pkg/options/window.go b/exp/pkg/options/window.go index f0f8c011f..fc931f95b 100644 --- a/exp/pkg/options/window.go +++ b/exp/pkg/options/window.go @@ -32,6 +32,9 @@ type Window struct { Mac *MacWindow BackgroundColour *RGBA Assets Assets + HTML string + JS string + CSS string } var WindowDefaults = &Window{ diff --git a/exp/tasks/events/generate.go b/exp/tasks/events/generate.go index 6fbd018d0..c3810ecd9 100644 --- a/exp/tasks/events/generate.go +++ b/exp/tasks/events/generate.go @@ -47,6 +47,7 @@ func main() { cHeaderEvents := bytes.NewBufferString("") windowDelegateEvents := bytes.NewBufferString("") applicationDelegateEvents := bytes.NewBufferString("") + webviewDelegateEvents := bytes.NewBufferString("") // Loop over each line in the file for id, line := range bytes.Split(eventNames, []byte{'\n'}) { @@ -78,6 +79,9 @@ func main() { if strings.HasPrefix(event, "Window") { eventType = "WindowEventType" } + if strings.HasPrefix(event, "WebView") { + eventType = "WindowEventType" + } macEventsDecl.WriteString("\t" + eventTitle + " " + eventType + "\n") macEventsValues.WriteString("\t\t" + event + ": " + strconv.Itoa(id) + ",\n") cHeaderEvents.WriteString("#define Event" + eventTitle + " " + strconv.Itoa(id) + "\n") @@ -90,6 +94,16 @@ func main() { processWindowEvent(self.windowId, Event` + eventTitle + `); } +`) + } + // Check if this is a webview event + if strings.HasPrefix(event, "WebView") { + webViewFunction := strings.TrimPrefix(event, "WebView") + webViewFunction = string(bytes.ToLower([]byte{webViewFunction[0]})) + webViewFunction[1:] + webviewDelegateEvents.WriteString(`- (void)webView:(WKWebView *)webview ` + webViewFunction + `:(WKNavigation *)navigation { + processWindowEvent(self.windowId, Event` + eventTitle + `); +} + `) } if strings.HasPrefix(event, "Application") { @@ -99,88 +113,92 @@ func main() { `) } + } - } + // Save the eventsGo template substituting the values and decls + templateToWrite := strings.ReplaceAll(eventsGo, "$$MACEVENTSDECL", macEventsDecl.String()) + templateToWrite = strings.ReplaceAll(templateToWrite, "$$MACEVENTSVALUES", macEventsValues.String()) + err = os.WriteFile("../../pkg/events/events.go", []byte(templateToWrite), 0644) + if err != nil { + panic(err) + } - // Save the eventsGo template substituting the values and decls - templateToWrite := strings.ReplaceAll(eventsGo, "$$MACEVENTSDECL", macEventsDecl.String()) - templateToWrite = strings.ReplaceAll(templateToWrite, "$$MACEVENTSVALUES", macEventsValues.String()) - err = os.WriteFile("../../pkg/events/events.go", []byte(templateToWrite), 0644) - if err != nil { - panic(err) - } + // Save the eventsH template substituting the values and decls + templateToWrite = strings.ReplaceAll(eventsH, "$$CHEADEREVENTS", cHeaderEvents.String()) + err = os.WriteFile("../../pkg/events/events.h", []byte(templateToWrite), 0644) + if err != nil { + panic(err) + } - // Save the eventsH template substituting the values and decls - templateToWrite = strings.ReplaceAll(eventsH, "$$CHEADEREVENTS", cHeaderEvents.String()) - err = os.WriteFile("../../pkg/events/events.h", []byte(templateToWrite), 0644) - if err != nil { - panic(err) - } + // Load the window_delegate.m file + windowDelegate, err := os.ReadFile("../../pkg/application/window_delegate.m") + if err != nil { + panic(err) + } + // iterate over the lines until we reach a line that says "// GENERATED EVENTS START" + // then we insert the events + // then we iterate until we reach a line that says "// GENERATED EVENTS END" + // then we write the file + var buffer bytes.Buffer + var inGeneratedEvents bool + for _, line := range bytes.Split(windowDelegate, []byte{'\n'}) { + if bytes.Contains(line, []byte("// GENERATED EVENTS START")) { + inGeneratedEvents = true + buffer.WriteString("// GENERATED EVENTS START\n") + buffer.WriteString(windowDelegateEvents.String()) + buffer.WriteString(webviewDelegateEvents.String()) + continue + } + if bytes.Contains(line, []byte("// GENERATED EVENTS END")) { + inGeneratedEvents = false + buffer.WriteString("// GENERATED EVENTS END\n") + continue + } + if !inGeneratedEvents { + if len(line) > 0 { + buffer.Write(line) + buffer.WriteString("\n") + } + } + } + err = os.WriteFile("../../pkg/application/window_delegate.m", buffer.Bytes(), 0755) + if err != nil { + panic(err) + } - // Load the window_delegate.m file - windowDelegate, err := os.ReadFile("../../pkg/application/window_delegate.m") - if err != nil { - panic(err) - } - // iterate over the lines until we reach a line that says "// GENERATED EVENTS START" - // then we insert the events - // then we iterate until we reach a line that says "// GENERATED EVENTS END" - // then we write the file - var buffer bytes.Buffer - var inGeneratedEvents bool - for _, line := range bytes.Split(windowDelegate, []byte{'\n'}) { - if bytes.Contains(line, []byte("// GENERATED EVENTS START")) { - inGeneratedEvents = true - buffer.WriteString("// GENERATED EVENTS START\n") - buffer.WriteString(windowDelegateEvents.String()) - continue + // Load the app_delegate.m file + appDelegate, err := os.ReadFile("../../pkg/application/app_delegate.m") + if err != nil { + panic(err) } - if bytes.Contains(line, []byte("// GENERATED EVENTS END")) { - inGeneratedEvents = false - buffer.WriteString("// GENERATED EVENTS END\n") - continue + // iterate over the lines until we reach a line that says "// GENERATED EVENTS START" + // then we insert the events + // then we iterate until we reach a line that says "// GENERATED EVENTS END" + // then we write the file + buffer.Reset() + for _, line := range bytes.Split(appDelegate, []byte{'\n'}) { + if bytes.Contains(line, []byte("// GENERATED EVENTS START")) { + inGeneratedEvents = true + buffer.WriteString("// GENERATED EVENTS START\n") + buffer.WriteString(applicationDelegateEvents.String()) + continue + } + if bytes.Contains(line, []byte("// GENERATED EVENTS END")) { + inGeneratedEvents = false + buffer.WriteString("// GENERATED EVENTS END\n") + continue + } + if !inGeneratedEvents { + if len(line) > 0 { + buffer.Write(line) + buffer.WriteString("\n") + } + } } - if !inGeneratedEvents { - buffer.Write(line) - buffer.WriteString("\n") + err = os.WriteFile("../../pkg/application/app_delegate.m", buffer.Bytes(), 0755) + if err != nil { + panic(err) } } - err = os.WriteFile("../../pkg/application/window_delegate.m", buffer.Bytes(), 0755) - if err != nil { - panic(err) - } - - // Load the app_delegate.m file - appDelegate, err := os.ReadFile("../../pkg/application/app_delegate.m") - if err != nil { - panic(err) - } - // iterate over the lines until we reach a line that says "// GENERATED EVENTS START" - // then we insert the events - // then we iterate until we reach a line that says "// GENERATED EVENTS END" - // then we write the file - buffer.Reset() - for _, line := range bytes.Split(appDelegate, []byte{'\n'}) { - if bytes.Contains(line, []byte("// GENERATED EVENTS START")) { - inGeneratedEvents = true - buffer.WriteString("// GENERATED EVENTS START\n") - buffer.WriteString(applicationDelegateEvents.String()) - continue - } - if bytes.Contains(line, []byte("// GENERATED EVENTS END")) { - inGeneratedEvents = false - buffer.WriteString("// GENERATED EVENTS END\n") - continue - } - if !inGeneratedEvents { - buffer.Write(line) - buffer.WriteString("\n") - } - } - err = os.WriteFile("../../pkg/application/app_delegate.m", buffer.Bytes(), 0755) - if err != nil { - panic(err) - } - } From 025e8d7645e231c59c7f3fb4f69dde6c8f5e63cd Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Tue, 20 Dec 2022 21:49:19 +1100 Subject: [PATCH 44/85] Add SaveFileDialog Add Toolbar Styles Add Invisible Titlebar option with drag support --- exp/examples/dialogs/main.go | 45 ++++++++++-- exp/examples/plain/main.go | 12 ++++ exp/examples/window/main.go | 2 +- exp/pkg/application/application.go | 6 +- exp/pkg/application/application_darwin.go | 40 +++++++++-- exp/pkg/application/dialogs.go | 50 +++++++++++++- exp/pkg/application/dialogs_darwin.go | 84 +++++++++++++++++++++++ exp/pkg/application/window_darwin.go | 71 ++++++++++++++++--- exp/pkg/application/window_delegate.h | 5 ++ exp/pkg/application/window_delegate.m | 20 +++++- exp/pkg/application/window_devtools.go | 5 -- exp/pkg/options/mac.go | 37 ++++++++-- 12 files changed, 339 insertions(+), 38 deletions(-) diff --git a/exp/examples/dialogs/main.go b/exp/examples/dialogs/main.go index d6c40a3a1..97b436575 100644 --- a/exp/examples/dialogs/main.go +++ b/exp/examples/dialogs/main.go @@ -140,7 +140,7 @@ func main() { openMenu.Add("Open File").OnClick(func(ctx *application.Context) { result, _ := app.NewOpenFileDialog(). CanChooseFiles(true). - PromptForSingleFile() + PromptForSingleSelection() if result != "" { app.NewInfoDialog().SetMessage(result).Show() } else { @@ -152,7 +152,7 @@ func main() { CanChooseFiles(true). CanCreateDirectories(true). ShowHiddenFiles(true). - PromptForSingleFile() + PromptForSingleSelection() if result != "" { app.NewInfoDialog().SetMessage(result).Show() } else { @@ -165,7 +165,7 @@ func main() { CanCreateDirectories(true). ShowHiddenFiles(true). AttachToWindow(app.GetCurrentWindow()). - PromptForSingleFile() + PromptForSingleSelection() if result != "" { app.NewInfoDialog().SetMessage(result).Show() } else { @@ -177,7 +177,7 @@ func main() { CanChooseFiles(true). CanCreateDirectories(true). ShowHiddenFiles(true). - PromptForMultipleFiles() + PromptForMultipleSelection() if len(result) > 0 { app.NewInfoDialog().SetMessage(strings.Join(result, ",")).Show() } else { @@ -187,7 +187,7 @@ func main() { openMenu.Add("Open Directory").OnClick(func(ctx *application.Context) { result, _ := app.NewOpenFileDialog(). CanChooseDirectories(true). - PromptForSingleFile() + PromptForSingleSelection() if result != "" { app.NewInfoDialog().SetMessage(result).Show() } else { @@ -198,7 +198,7 @@ func main() { result, _ := app.NewOpenFileDialog(). CanChooseDirectories(true). CanCreateDirectories(true). - PromptForSingleFile() + PromptForSingleSelection() if result != "" { app.NewInfoDialog().SetMessage(result).Show() } else { @@ -206,6 +206,39 @@ func main() { } }) + saveMenu := menu.AddSubmenu("Save") + saveMenu.Add("Select File (Defaults)").OnClick(func(ctx *application.Context) { + result, _ := app.NewSaveFileDialog(). + PromptForSingleSelection() + if result != "" { + app.NewInfoDialog().SetMessage(result).Show() + } + }) + saveMenu.Add("Select File (Attach To Window)").OnClick(func(ctx *application.Context) { + result, _ := app.NewSaveFileDialog(). + AttachToWindow(app.GetCurrentWindow()). + PromptForSingleSelection() + if result != "" { + app.NewInfoDialog().SetMessage(result).Show() + } + }) + saveMenu.Add("Select File (Show Hidden Files)").OnClick(func(ctx *application.Context) { + result, _ := app.NewSaveFileDialog(). + ShowHiddenFiles(true). + PromptForSingleSelection() + if result != "" { + app.NewInfoDialog().SetMessage(result).Show() + } + }) + saveMenu.Add("Select File (Cannot Create Directories)").OnClick(func(ctx *application.Context) { + result, _ := app.NewSaveFileDialog(). + CanCreateDirectories(false). + PromptForSingleSelection() + if result != "" { + app.NewInfoDialog().SetMessage(result).Show() + } + }) + app.SetMenu(menu) app.NewWindow() diff --git a/exp/examples/plain/main.go b/exp/examples/plain/main.go index 64096a4b5..61329f7dd 100644 --- a/exp/examples/plain/main.go +++ b/exp/examples/plain/main.go @@ -12,6 +12,18 @@ import ( func main() { app := application.New() + // Create window + app.NewWindowWithOptions(&options.Window{ + Title: "Plain Bundle", + EnableDevTools: true, + HTML: `Plain Bundle

Plain Bundle

This is a plain bundle. It has no frontend code.

`, + CSS: `body { background-color: rgba(255, 255, 255, 0); } .main { color: white; margin: 20%; }`, + Mac: &options.MacWindow{ + InvisibleTitleBarHeight: 50, + Backdrop: options.MacBackdropTranslucent, + TitleBar: options.TitleBarHiddenInset, + }, + }) // Create window app.NewWindowWithOptions(&options.Window{ Title: "Plain Bundle", diff --git a/exp/examples/window/main.go b/exp/examples/window/main.go index 3ddaf6ebc..cb0dea554 100644 --- a/exp/examples/window/main.go +++ b/exp/examples/window/main.go @@ -23,7 +23,7 @@ func main() { EnableDevTools: true, Mac: &options.MacWindow{ Backdrop: options.MacBackdropTranslucent, - TitleBar: options.TitleBarHiddenInset, + TitleBar: options.TitleBarHiddenInsetUnified, }, }) myWindow.On(events.Mac.WindowDidBecomeMain, func() { diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index 3408e9305..067372a0d 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -152,7 +152,7 @@ func (a *App) NewSystemTray() *SystemTray { } func (a *App) Run() error { - a.impl = newPlatformApp(a.options) + a.impl = newPlatformApp(a) a.running = true go func() { @@ -344,3 +344,7 @@ func (a *App) NewOpenDirectoryDialog() *MessageDialog { func (a *App) NewOpenFileDialog() *OpenFileDialog { return newOpenFileDialog() } + +func (a *App) NewSaveFileDialog() *SaveFileDialog { + return newSaveFileDialog() +} diff --git a/exp/pkg/application/application_darwin.go b/exp/pkg/application/application_darwin.go index 4699383fe..ff13bbad1 100644 --- a/exp/pkg/application/application_darwin.go +++ b/exp/pkg/application/application_darwin.go @@ -20,6 +20,28 @@ static void init(void) { [NSApplication sharedApplication]; appDelegate = [[AppDelegate alloc] init]; [NSApp setDelegate:appDelegate]; + + [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskLeftMouseDown handler:^NSEvent * _Nullable(NSEvent * _Nonnull event) { + NSWindow* eventWindow = [event window]; + if (![eventWindow respondsToSelector:@selector(handleLeftMouseDown)]) { + return event; + } + + WindowDelegate* windowDelegate = (WindowDelegate*)[eventWindow delegate]; + [windowDelegate handleLeftMouseDown:event]; + return event; + }]; + + [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskLeftMouseUp handler:^NSEvent * _Nullable(NSEvent * _Nonnull event) { + NSWindow* eventWindow = [event window]; + if (![eventWindow respondsToSelector:@selector(handleLeftMouseUp)]) { + return event; + } + + WindowDelegate* windowDelegate = (WindowDelegate*)[eventWindow delegate]; + [windowDelegate handleLeftMouseUp:eventWindow]; + return event; + }]; } static void setActivationPolicy(int policy) { @@ -79,12 +101,14 @@ import "C" import ( "unsafe" + "github.com/wailsapp/wails/exp/pkg/events" + "github.com/wailsapp/wails/exp/pkg/options" ) type macosApp struct { - options *options.Application applicationMenu unsafe.Pointer + parent *App } func (m *macosApp) setIcon(icon []byte) { @@ -107,12 +131,19 @@ func (m *macosApp) setApplicationMenu(menu *Menu) { menu = defaultApplicationMenu() } menu.Update() + // Convert impl to macosMenu object m.applicationMenu = (menu.impl).(*macosMenu).nsMenu C.setApplicationMenu(m.applicationMenu) } func (m *macosApp) run() error { + m.parent.On(events.Mac.ApplicationDidFinishLaunching, func() { + if m.parent.options != nil && m.parent.options.Mac != nil { + C.setActivationPolicy(C.int(m.parent.options.Mac.ActivationPolicy)) + } + C.activateIgnoringOtherApps() + }) C.run() return nil } @@ -121,15 +152,14 @@ func (m *macosApp) destroy() { C.destroyApp() } -func newPlatformApp(appOptions *options.Application) *macosApp { +func newPlatformApp(app *App) *macosApp { + appOptions := app.options if appOptions == nil { appOptions = options.ApplicationDefaults } C.init() - C.setActivationPolicy(C.int(appOptions.Mac.ActivationPolicy)) - C.activateIgnoringOtherApps() return &macosApp{ - options: appOptions, + parent: app, } } diff --git a/exp/pkg/application/dialogs.go b/exp/pkg/application/dialogs.go index 6309f2f6c..7ba5b7628 100644 --- a/exp/pkg/application/dialogs.go +++ b/exp/pkg/application/dialogs.go @@ -7,6 +7,7 @@ import ( type DialogType int +// TODO: Make this a map and clear it when the dialog is closed var dialogID uint var dialogIDLock sync.RWMutex @@ -18,6 +19,7 @@ func getDialogID() uint { } var openFileResponses = make(map[uint]chan string) +var saveFileResponses = make(map[uint]chan string) const ( InfoDialog DialogType = iota @@ -154,7 +156,7 @@ func (d *OpenFileDialog) AttachToWindow(window *Window) *OpenFileDialog { return d } -func (d *OpenFileDialog) PromptForSingleFile() (string, error) { +func (d *OpenFileDialog) PromptForSingleSelection() (string, error) { d.allowsMultipleSelection = false if d.impl == nil { d.impl = newOpenFileDialogImpl(d) @@ -168,7 +170,7 @@ func (d *OpenFileDialog) PromptForSingleFile() (string, error) { return result, err } -func (d *OpenFileDialog) PromptForMultipleFiles() ([]string, error) { +func (d *OpenFileDialog) PromptForMultipleSelection() ([]string, error) { d.allowsMultipleSelection = true if d.impl == nil { d.impl = newOpenFileDialogImpl(d) @@ -181,6 +183,48 @@ func newOpenFileDialog() *OpenFileDialog { id: getDialogID(), canChooseDirectories: false, canChooseFiles: true, - canCreateDirectories: false, + canCreateDirectories: true, } } + +func newSaveFileDialog() *SaveFileDialog { + return &SaveFileDialog{ + id: getDialogID(), + canCreateDirectories: true, + } +} + +type SaveFileDialog struct { + id uint + canCreateDirectories bool + showHiddenFiles bool + window *Window + + impl saveFileDialogImpl +} + +type saveFileDialogImpl interface { + show() (string, error) +} + +func (d *SaveFileDialog) CanCreateDirectories(canCreateDirectories bool) *SaveFileDialog { + d.canCreateDirectories = canCreateDirectories + return d +} + +func (d *SaveFileDialog) ShowHiddenFiles(showHiddenFiles bool) *SaveFileDialog { + d.showHiddenFiles = showHiddenFiles + return d +} + +func (d *SaveFileDialog) AttachToWindow(window *Window) *SaveFileDialog { + d.window = window + return d +} + +func (d *SaveFileDialog) PromptForSingleSelection() (string, error) { + if d.impl == nil { + d.impl = newSaveFileDialogImpl(d) + } + return d.impl.show() +} diff --git a/exp/pkg/application/dialogs_darwin.go b/exp/pkg/application/dialogs_darwin.go index 67eb8406c..3bb004dca 100644 --- a/exp/pkg/application/dialogs_darwin.go +++ b/exp/pkg/application/dialogs_darwin.go @@ -10,6 +10,7 @@ package application extern void openFileDialogCallback(uint id, char* path); extern void openFileDialogCallbackEnd(uint id); +extern void saveFileDialogCallback(uint id, char* path); static void showAboutBox(char* title, char *message, void *icon, int length) { @@ -146,6 +147,52 @@ static void showOpenFileDialog(unsigned int dialogID, bool canChooseFiles, bool }); } +static void showSaveFileDialog(unsigned int dialogID, bool canCreateDirectories, bool showHiddenFiles, void *window) { + // run on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + NSSavePanel *panel = [NSSavePanel savePanel]; + + [panel setCanCreateDirectories:canCreateDirectories]; + [panel setShowsHiddenFiles:showHiddenFiles]; + + //if (title != NULL) { + // [panel setTitle:[NSString stringWithUTF8String:title]]; + // free(title); + //} + + //if (defaultFilename != NULL) { + // [panel setNameFieldStringValue:[NSString stringWithUTF8String:defaultFilename]]; + // free(defaultFilename); + //} + // + //if (defaultDirectory != NULL) { + // [panel setDirectoryURL:[NSURL fileURLWithPath:[NSString stringWithUTF8String:defaultDirectory]]]; + // free(defaultDirectory); + //} + + if (window != NULL) { + [panel beginSheetModalForWindow:(__bridge NSWindow *)window completionHandler:^(NSInteger result) { + const char *path = NULL; + if (result == NSModalResponseOK) { + NSURL *url = [panel URL]; + const char *path = [[url path] UTF8String]; + } + saveFileDialogCallback(dialogID, (char *)path); + }]; + } else { + [panel beginWithCompletionHandler:^(NSInteger result) { + const char *path = NULL; + if (result == NSModalResponseOK) { + NSURL *url = [panel URL]; + const char *path = [[url path] UTF8String]; + } + saveFileDialogCallback(dialogID, (char *)path); + }]; + } + }); +} + + */ import "C" import ( @@ -296,3 +343,40 @@ func openFileDialogCallbackEnd(id C.uint) { panic("No channel found for open file dialog") } } + +type macosSaveFileDialog struct { + dialog *SaveFileDialog +} + +func newSaveFileDialogImpl(d *SaveFileDialog) *macosSaveFileDialog { + return &macosSaveFileDialog{ + dialog: d, + } +} + +func (m *macosSaveFileDialog) show() (string, error) { + saveFileResponses[dialogID] = make(chan string) + nsWindow := unsafe.Pointer(nil) + if m.dialog.window != nil { + // get NSWindow from window + nsWindow = m.dialog.window.impl.(*macosWindow).nsWindow + } + C.showSaveFileDialog(C.uint(m.dialog.id), + C.bool(m.dialog.canCreateDirectories), + C.bool(m.dialog.showHiddenFiles), + nsWindow) + return <-saveFileResponses[m.dialog.id], nil +} + +//export saveFileDialogCallback +func saveFileDialogCallback(id C.uint, path *C.char) { + // Covert the path to a string + filePath := C.GoString(path) + // put response on channel + channel, ok := saveFileResponses[uint(id)] + if ok { + channel <- filePath + } else { + panic("No channel found for save file dialog") + } +} diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index db0e187a4..f4471eac4 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -56,6 +56,15 @@ void* windowNew(unsigned int id, int width, int height) { return window; } +// setInvisibleTitleBarHeight sets the invisible title bar height +void setInvisibleTitleBarHeight(void* window, unsigned int height) { + NSWindow* nsWindow = (NSWindow*)window; + // Get delegate + WindowDelegate* delegate = (WindowDelegate*)[nsWindow delegate]; + // Set height + delegate.invisibleTitleBarHeight = height; +} + //// Make window toggle frameless //void windowSetFrameless(void* window, bool frameless) { // NSWindow* nsWindow = (NSWindow*)window; @@ -81,6 +90,18 @@ void windowSetTransparent(void* nsWindow) { }); } +void windowSetInvisibleTitleBar(void* nsWindow, unsigned int height) { + // On main thread + dispatch_async(dispatch_get_main_queue(), ^{ + NSWindow* window = (NSWindow*)nsWindow; + // Get delegate + WindowDelegate* delegate = (WindowDelegate*)[window delegate]; + // Set height + delegate.invisibleTitleBarHeight = height; + }); +} + + // Set the title of the NSWindow void windowSetTitle(void* nsWindow, char* title) { // Set window title on main thread @@ -407,7 +428,7 @@ void windowSetHideTitle(void* nsWindow, bool hideTitle) { } // Set Window use toolbar -void windowSetUseToolbar(void* nsWindow, bool useToolbar) { +void windowSetUseToolbar(void* nsWindow, bool useToolbar, int toolbarStyle) { // Set window use toolbar on main thread dispatch_async(dispatch_get_main_queue(), ^{ // get main window @@ -416,12 +437,35 @@ void windowSetUseToolbar(void* nsWindow, bool useToolbar) { NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"wails.toolbar"]; [toolbar autorelease]; [window setToolbar:toolbar]; + + // If macos 11 or higher, set toolbar style + if (@available(macOS 11.0, *)) { + [window setToolbarStyle:toolbarStyle]; + } + } else { [window setToolbar:nil]; } }); } +// Set window toolbar style +void windowSetToolbarStyle(void* nsWindow, int style) { + // use @available to check if the function is available + // if not, return + if (@available(macOS 11.0, *)) { + // Set window toolbar style on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + // get main window + NSWindow* window = (NSWindow*)nsWindow; + // get toolbar + NSToolbar* toolbar = [window toolbar]; + // set toolbar style + [toolbar setShowsBaselineSeparator:style]; + }); + } +} + // Set Hide Toolbar Separator void windowSetHideToolbarSeparator(void* nsWindow, bool hideSeparator) { // Set window hide toolbar separator on main thread @@ -808,7 +852,9 @@ func (w *macosWindow) run() { C.windowSetHideTitleBar(w.nsWindow, C.bool(titleBarOptions.Hide)) C.windowSetHideTitle(w.nsWindow, C.bool(titleBarOptions.HideTitle)) C.windowSetFullSizeContent(w.nsWindow, C.bool(titleBarOptions.FullSizeContent)) - C.windowSetUseToolbar(w.nsWindow, C.bool(titleBarOptions.UseToolbar)) + if titleBarOptions.UseToolbar { + C.windowSetUseToolbar(w.nsWindow, C.bool(titleBarOptions.UseToolbar), C.int(titleBarOptions.ToolbarStyle)) + } C.windowSetHideToolbarSeparator(w.nsWindow, C.bool(titleBarOptions.HideToolbarSeparator)) } @@ -816,15 +862,18 @@ func (w *macosWindow) run() { C.windowSetAppearanceTypeByName(w.nsWindow, C.CString(string(macOptions.Appearance))) } - switch w.parent.options.StartState { - case options.WindowStateMaximised: - w.setMaximised() - case options.WindowStateMinimised: - w.setMinimised() - case options.WindowStateFullscreen: - w.setFullscreen() - + if macOptions.InvisibleTitleBarHeight != 0 { + C.windowSetInvisibleTitleBar(w.nsWindow, C.uint(macOptions.InvisibleTitleBarHeight)) } + } + + switch w.parent.options.StartState { + case options.WindowStateMaximised: + w.setMaximised() + case options.WindowStateMinimised: + w.setMinimised() + case options.WindowStateFullscreen: + w.setFullscreen() } C.windowCenter(w.nsWindow) @@ -832,7 +881,7 @@ func (w *macosWindow) run() { if w.parent.options.URL != "" { w.navigateToURL(w.parent.options.URL) } - // Ee need to wait for the HTML to load before we can execute the javascript + // We need to wait for the HTML to load before we can execute the javascript w.parent.On(events.Mac.WebViewDidFinishNavigation, func() { if w.parent.options.JS != "" { w.execJS(w.parent.options.JS) diff --git a/exp/pkg/application/window_delegate.h b/exp/pkg/application/window_delegate.h index 3927efc6f..71baebef9 100644 --- a/exp/pkg/application/window_delegate.h +++ b/exp/pkg/application/window_delegate.h @@ -11,6 +11,11 @@ @property bool hideOnClose; @property (retain) WKWebView* webView; @property unsigned int windowId; +@property (retain) NSEvent* leftMouseEvent; +@property unsigned int invisibleTitleBarHeight; + +- (void)handleLeftMouseUp:(NSWindow *)window; +- (void)handleLeftMouseDown:(NSEvent*)event; @end diff --git a/exp/pkg/application/window_delegate.m b/exp/pkg/application/window_delegate.m index 8f21e7086..5f4ffb762 100644 --- a/exp/pkg/application/window_delegate.m +++ b/exp/pkg/application/window_delegate.m @@ -37,10 +37,26 @@ extern void processMessage(unsigned int, const char*); processMessage(self.windowId, _m); } -- (void) mouseDown:(NSEvent*)someEvent { - NSLog(@"MOUSE DOWN!!!"); +- (void)handleLeftMouseDown:(NSEvent *)event { + self.leftMouseEvent = event; + NSWindow *window = [event window]; + WindowDelegate* delegate = (WindowDelegate*)[window delegate]; + + if( self.invisibleTitleBarHeight > 0 ) { + NSPoint location = [event locationInWindow]; + NSRect frame = [window frame]; + if( location.y > frame.size.height - self.invisibleTitleBarHeight ) { + [window performWindowDragWithEvent:event]; + return; + } + } } +- (void)handleLeftMouseUp:(NSWindow *)window { + self.leftMouseEvent = nil; +} + + // GENERATED EVENTS START - (void)windowDidBecomeKey:(NSNotification *)notification { processWindowEvent(self.windowId, EventWindowDidBecomeKey); diff --git a/exp/pkg/application/window_devtools.go b/exp/pkg/application/window_devtools.go index d8382dfa1..d73e0c3b3 100644 --- a/exp/pkg/application/window_devtools.go +++ b/exp/pkg/application/window_devtools.go @@ -24,11 +24,6 @@ void showDevTools(void *window) { WindowDelegate* delegate = (WindowDelegate*)[(NSWindow*)window delegate]; dispatch_async(dispatch_get_main_queue(), ^{ [delegate.webView._inspector show]; - //dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC); - //dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ - // // Detach must be deferred a little bit and is ignored directly after a show. - // [delegate.webView._inspector detach]; - //}); }); } diff --git a/exp/pkg/options/mac.go b/exp/pkg/options/mac.go index 01a6c9d27..9851c925c 100644 --- a/exp/pkg/options/mac.go +++ b/exp/pkg/options/mac.go @@ -22,11 +22,27 @@ const ( MacBackdropTranslucent ) +type MacToolbarStyle int + +const ( + // MacToolbarStyleAutomatic - The default value. The style will be determined by the window's given configuration + MacToolbarStyleAutomatic MacToolbarStyle = iota + // MacToolbarStyleExpanded - The toolbar will appear below the window title + MacToolbarStyleExpanded + // MacToolbarStylePreference - The toolbar will appear below the window title and the items in the toolbar will attempt to have equal widths when possible + MacToolbarStylePreference + // MacToolbarStyleUnified - The window title will appear inline with the toolbar when visible + MacToolbarStyleUnified + // MacToolbarStyleUnifiedCompact - Same as MacToolbarStyleUnified, but with reduced margins in the toolbar allowing more focus to be on the contents of the window + MacToolbarStyleUnifiedCompact +) + // MacWindow contains macOS specific options type MacWindow struct { - Backdrop MacBackdrop - TitleBar *TitleBar - Appearance MacAppearanceType + Backdrop MacBackdrop + TitleBar *TitleBar + Appearance MacAppearanceType + InvisibleTitleBarHeight int } // TitleBar contains options for the Mac titlebar @@ -37,9 +53,10 @@ type TitleBar struct { FullSizeContent bool UseToolbar bool HideToolbarSeparator bool + ToolbarStyle MacToolbarStyle } -// TitleBarDefault results in the default Mac Titlebar +// TitleBarDefault results in the default Mac TitleBar var TitleBarDefault = &TitleBar{ AppearsTransparent: false, Hide: false, @@ -74,6 +91,18 @@ var TitleBarHiddenInset = &TitleBar{ HideToolbarSeparator: true, } +// TitleBarHiddenInsetUnified results in a hidden title bar with an alternative look where +// the traffic light buttons are even more inset from the window edge. +var TitleBarHiddenInsetUnified = &TitleBar{ + AppearsTransparent: true, + Hide: false, + HideTitle: true, + FullSizeContent: true, + UseToolbar: true, + HideToolbarSeparator: true, + ToolbarStyle: MacToolbarStyleUnified, +} + // MacAppearanceType is a type of Appearance for Cocoa windows type MacAppearanceType string From 4d58b56d54844771da5fc3268d20716173586fa5 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 21 Dec 2022 21:30:26 +1100 Subject: [PATCH 45/85] Improve dialogs --- exp/examples/dialogs/main.go | 76 ++++++++++++++ exp/pkg/application/dialogs.go | 137 +++++++++++++++++++++++--- exp/pkg/application/dialogs_darwin.go | 111 +++++++++++++++++---- 3 files changed, 290 insertions(+), 34 deletions(-) diff --git a/exp/examples/dialogs/main.go b/exp/examples/dialogs/main.go index 97b436575..96e5de440 100644 --- a/exp/examples/dialogs/main.go +++ b/exp/examples/dialogs/main.go @@ -3,6 +3,8 @@ package main import ( _ "embed" "log" + "os" + "runtime" "strings" "github.com/wailsapp/wails/exp/pkg/application" @@ -205,6 +207,63 @@ func main() { app.NewInfoDialog().SetMessage("No directory selected").Show() } }) + openMenu.Add("Open Directory (Resolves Aliases)").OnClick(func(ctx *application.Context) { + result, _ := app.NewOpenFileDialog(). + CanChooseDirectories(true). + CanCreateDirectories(true). + ResolvesAliases(true). + PromptForSingleSelection() + if result != "" { + app.NewInfoDialog().SetMessage(result).Show() + } else { + app.NewInfoDialog().SetMessage("No directory selected").Show() + } + }) + openMenu.Add("Open File/Directory (Set Title)").OnClick(func(ctx *application.Context) { + dialog := app.NewOpenFileDialog(). + CanChooseDirectories(true). + CanCreateDirectories(true). + ResolvesAliases(true) + if runtime.GOOS == "darwin" { + dialog.SetMessage("Select a file/directory") + } else { + dialog.SetTitle("Select a file/directory") + } + + result, _ := dialog.PromptForSingleSelection() + if result != "" { + app.NewInfoDialog().SetMessage(result).Show() + } else { + app.NewInfoDialog().SetMessage("No file/directory selected").Show() + } + }) + openMenu.Add("Open (Full Example)").OnClick(func(ctx *application.Context) { + cwd, _ := os.Getwd() + dialog := app.NewOpenFileDialog(). + SetTitle("Select a file"). + SetMessage("Select a file to open"). + SetButtonText("Let's do this!"). + SetDirectory(cwd). + CanCreateDirectories(true). + ResolvesAliases(true). + AllowsOtherFileTypes(true). + TreatsFilePackagesAsDirectories(true). + ShowHiddenFiles(true). + CanSelectHiddenExtension(true) + + if runtime.GOOS == "darwin" { + dialog.SetMessage("Select a file") + } else { + dialog.SetTitle("Select a file") + } + + result, _ := dialog.PromptForSingleSelection() + if result != "" { + app.NewInfoDialog().SetMessage(result).Show() + } else { + app.NewInfoDialog().SetMessage("No file selected").Show() + } + }) saveMenu := menu.AddSubmenu("Save") saveMenu.Add("Select File (Defaults)").OnClick(func(ctx *application.Context) { @@ -238,6 +297,23 @@ func main() { app.NewInfoDialog().SetMessage(result).Show() } }) + saveMenu.Add("Select File (Full Example)").OnClick(func(ctx *application.Context) { + result, _ := app.NewSaveFileDialog(). + CanCreateDirectories(false). + ShowHiddenFiles(true). + SetMessage("Select a file"). + SetDirectory("/Applications"). + SetButtonText("Let's do this!"). + SetFilename("README.md"). + HideExtension(true). + AllowsOtherFileTypes(true). + TreatsFilePackagesAsDirectories(true). + ShowHiddenFiles(true). + PromptForSingleSelection() + if result != "" { + app.NewInfoDialog().SetMessage(result).Show() + } + }) app.SetMenu(menu) diff --git a/exp/pkg/application/dialogs.go b/exp/pkg/application/dialogs.go index 7ba5b7628..f59123742 100644 --- a/exp/pkg/application/dialogs.go +++ b/exp/pkg/application/dialogs.go @@ -74,11 +74,6 @@ func (d *MessageDialog) SetTitle(title string) *MessageDialog { return d } -func (d *MessageDialog) SetMessage(message string) *MessageDialog { - d.message = message - return d -} - func (d *MessageDialog) Show() { if d.impl == nil { d.impl = newDialogImpl(d) @@ -115,18 +110,33 @@ func (d *MessageDialog) SetCancelButton(button *Button) *MessageDialog { return d } +func (d *MessageDialog) SetMessage(title string) *MessageDialog { + d.title = title + return d +} + type openFileDialogImpl interface { show() ([]string, error) } type OpenFileDialog struct { - id uint - canChooseDirectories bool - canChooseFiles bool - canCreateDirectories bool - showHiddenFiles bool - allowsMultipleSelection bool - window *Window + id uint + canChooseDirectories bool + canChooseFiles bool + canCreateDirectories bool + showHiddenFiles bool + resolvesAliases bool + allowsMultipleSelection bool + hideExtension bool + canSelectHiddenExtension bool + treatsFilePackagesAsDirectories bool + allowsOtherFileTypes bool + + title string + message string + buttonText string + directory string + window *Window impl openFileDialogImpl } @@ -146,16 +156,41 @@ func (d *OpenFileDialog) CanCreateDirectories(canCreateDirectories bool) *OpenFi return d } +func (d *OpenFileDialog) AllowsOtherFileTypes(allowsOtherFileTypes bool) *OpenFileDialog { + d.allowsOtherFileTypes = allowsOtherFileTypes + return d +} + func (d *OpenFileDialog) ShowHiddenFiles(showHiddenFiles bool) *OpenFileDialog { d.showHiddenFiles = showHiddenFiles return d } +func (d *OpenFileDialog) HideExtension(hideExtension bool) *OpenFileDialog { + d.hideExtension = hideExtension + return d +} + +func (d *OpenFileDialog) TreatsFilePackagesAsDirectories(treatsFilePackagesAsDirectories bool) *OpenFileDialog { + d.treatsFilePackagesAsDirectories = treatsFilePackagesAsDirectories + return d +} + func (d *OpenFileDialog) AttachToWindow(window *Window) *OpenFileDialog { d.window = window return d } +func (d *OpenFileDialog) ResolvesAliases(resolvesAliases bool) *OpenFileDialog { + d.resolvesAliases = resolvesAliases + return d +} + +func (d *OpenFileDialog) SetTitle(title string) *OpenFileDialog { + d.title = title + return d +} + func (d *OpenFileDialog) PromptForSingleSelection() (string, error) { d.allowsMultipleSelection = false if d.impl == nil { @@ -178,12 +213,33 @@ func (d *OpenFileDialog) PromptForMultipleSelection() ([]string, error) { return d.impl.show() } +func (d *OpenFileDialog) SetMessage(message string) *OpenFileDialog { + d.message = message + return d +} + +func (d *OpenFileDialog) SetButtonText(text string) *OpenFileDialog { + d.buttonText = text + return d +} + +func (d *OpenFileDialog) SetDirectory(directory string) *OpenFileDialog { + d.directory = directory + return d +} + +func (d *OpenFileDialog) CanSelectHiddenExtension(canSelectHiddenExtension bool) *OpenFileDialog { + d.canSelectHiddenExtension = canSelectHiddenExtension + return d +} + func newOpenFileDialog() *OpenFileDialog { return &OpenFileDialog{ id: getDialogID(), canChooseDirectories: false, canChooseFiles: true, canCreateDirectories: true, + resolvesAliases: false, } } @@ -195,10 +251,19 @@ func newSaveFileDialog() *SaveFileDialog { } type SaveFileDialog struct { - id uint - canCreateDirectories bool - showHiddenFiles bool - window *Window + id uint + canCreateDirectories bool + showHiddenFiles bool + canSelectHiddenExtension bool + allowOtherFileTypes bool + hideExtension bool + treatsFilePackagesAsDirectories bool + message string + directory string + filename string + buttonText string + + window *Window impl saveFileDialogImpl } @@ -212,11 +277,26 @@ func (d *SaveFileDialog) CanCreateDirectories(canCreateDirectories bool) *SaveFi return d } +func (d *SaveFileDialog) CanSelectHiddenExtension(canSelectHiddenExtension bool) *SaveFileDialog { + d.canSelectHiddenExtension = canSelectHiddenExtension + return d +} + func (d *SaveFileDialog) ShowHiddenFiles(showHiddenFiles bool) *SaveFileDialog { d.showHiddenFiles = showHiddenFiles return d } +func (d *SaveFileDialog) SetMessage(message string) *SaveFileDialog { + d.message = message + return d +} + +func (d *SaveFileDialog) SetDirectory(directory string) *SaveFileDialog { + d.directory = directory + return d +} + func (d *SaveFileDialog) AttachToWindow(window *Window) *SaveFileDialog { d.window = window return d @@ -228,3 +308,28 @@ func (d *SaveFileDialog) PromptForSingleSelection() (string, error) { } return d.impl.show() } + +func (d *SaveFileDialog) SetButtonText(text string) *SaveFileDialog { + d.buttonText = text + return d +} + +func (d *SaveFileDialog) SetFilename(filename string) *SaveFileDialog { + d.filename = filename + return d +} + +func (d *SaveFileDialog) AllowsOtherFileTypes(allowOtherFileTypes bool) *SaveFileDialog { + d.allowOtherFileTypes = allowOtherFileTypes + return d +} + +func (d *SaveFileDialog) HideExtension(hideExtension bool) *SaveFileDialog { + d.hideExtension = hideExtension + return d +} + +func (d *SaveFileDialog) TreatsFilePackagesAsDirectories(treatsFilePackagesAsDirectories bool) *SaveFileDialog { + d.treatsFilePackagesAsDirectories = treatsFilePackagesAsDirectories + return d +} diff --git a/exp/pkg/application/dialogs_darwin.go b/exp/pkg/application/dialogs_darwin.go index 3bb004dca..1aa47966d 100644 --- a/exp/pkg/application/dialogs_darwin.go +++ b/exp/pkg/application/dialogs_darwin.go @@ -123,17 +123,49 @@ static void processOpenFileDialogResults(NSOpenPanel *panel, NSInteger result, b } -static void showOpenFileDialog(unsigned int dialogID, bool canChooseFiles, bool canChooseDirectories, bool canCreateDirectories, bool showHiddenFiles, bool allowsMultipleSelection, void *window) { +static void showOpenFileDialog(unsigned int dialogID, + bool canChooseFiles, + bool canChooseDirectories, + bool canCreateDirectories, + bool showHiddenFiles, + bool allowsMultipleSelection, + bool resolvesAliases, + bool hideExtension, + bool treatsFilePackagesAsDirectories, + bool allowsOtherFileTypes, + char* message, + char* directory, + char* buttonText, + void *window) { // run on main thread dispatch_async(dispatch_get_main_queue(), ^{ NSOpenPanel *panel = [NSOpenPanel openPanel]; + if (message != NULL) { + [panel setMessage:[NSString stringWithUTF8String:message]]; + free(message); + } + + if (directory != NULL) { + [panel setDirectoryURL:[NSURL fileURLWithPath:[NSString stringWithUTF8String:directory]]]; + free(directory); + } + + if (buttonText != NULL) { + [panel setPrompt:[NSString stringWithUTF8String:buttonText]]; + free(buttonText); + } + [panel setCanChooseFiles:canChooseFiles]; [panel setCanChooseDirectories:canChooseDirectories]; [panel setCanCreateDirectories:canCreateDirectories]; [panel setShowsHiddenFiles:showHiddenFiles]; [panel setAllowsMultipleSelection:allowsMultipleSelection]; + [panel setResolvesAliases:resolvesAliases]; + [panel setExtensionHidden:hideExtension]; + [panel setTreatsFilePackagesAsDirectories:treatsFilePackagesAsDirectories]; + [panel setAllowsOtherFileTypes:allowsOtherFileTypes]; if (window != NULL) { [panel beginSheetModalForWindow:(__bridge NSWindow *)window completionHandler:^(NSInteger result) { @@ -147,28 +179,49 @@ static void showOpenFileDialog(unsigned int dialogID, bool canChooseFiles, bool }); } -static void showSaveFileDialog(unsigned int dialogID, bool canCreateDirectories, bool showHiddenFiles, void *window) { - // run on main thread +static void showSaveFileDialog(unsigned int dialogID, + bool canCreateDirectories, + bool showHiddenFiles, + bool canSelectHiddenExtension, + bool hideExtension, + bool treatsFilePackagesAsDirectories, + bool allowOtherFileTypes, + char* message, + char* directory, + char* buttonText, + char* filename, + void *window) { + +// run on main thread dispatch_async(dispatch_get_main_queue(), ^{ NSSavePanel *panel = [NSSavePanel savePanel]; + if (message != NULL) { + [panel setMessage:[NSString stringWithUTF8String:message]]; + free(message); + } + + if (directory != NULL) { + [panel setDirectoryURL:[NSURL fileURLWithPath:[NSString stringWithUTF8String:directory]]]; + free(directory); + } + + if (filename != NULL) { + [panel setNameFieldStringValue:[NSString stringWithUTF8String:filename]]; + free(filename); + } + + if (buttonText != NULL) { + [panel setPrompt:[NSString stringWithUTF8String:buttonText]]; + free(buttonText); + } + [panel setCanCreateDirectories:canCreateDirectories]; [panel setShowsHiddenFiles:showHiddenFiles]; - - //if (title != NULL) { - // [panel setTitle:[NSString stringWithUTF8String:title]]; - // free(title); - //} - - //if (defaultFilename != NULL) { - // [panel setNameFieldStringValue:[NSString stringWithUTF8String:defaultFilename]]; - // free(defaultFilename); - //} - // - //if (defaultDirectory != NULL) { - // [panel setDirectoryURL:[NSURL fileURLWithPath:[NSString stringWithUTF8String:defaultDirectory]]]; - // free(defaultDirectory); - //} + [panel setCanSelectHiddenExtension:canSelectHiddenExtension]; + [panel setExtensionHidden:hideExtension]; + [panel setTreatsFilePackagesAsDirectories:treatsFilePackagesAsDirectories]; + [panel setAllowsOtherFileTypes:allowOtherFileTypes]; if (window != NULL) { [panel beginSheetModalForWindow:(__bridge NSWindow *)window completionHandler:^(NSInteger result) { @@ -300,6 +353,13 @@ func newOpenFileDialogImpl(d *OpenFileDialog) *macosOpenFileDialog { } } +func toCString(s string) *C.char { + if s == "" { + return nil + } + return C.CString(s) +} + func (m *macosOpenFileDialog) show() ([]string, error) { openFileResponses[dialogID] = make(chan string) nsWindow := unsafe.Pointer(nil) @@ -313,6 +373,13 @@ func (m *macosOpenFileDialog) show() ([]string, error) { C.bool(m.dialog.canCreateDirectories), C.bool(m.dialog.showHiddenFiles), C.bool(m.dialog.allowsMultipleSelection), + C.bool(m.dialog.resolvesAliases), + C.bool(m.dialog.hideExtension), + C.bool(m.dialog.treatsFilePackagesAsDirectories), + C.bool(m.dialog.allowsOtherFileTypes), + toCString(m.dialog.message), + toCString(m.dialog.directory), + toCString(m.dialog.buttonText), nsWindow) var result []string for filename := range openFileResponses[m.dialog.id] { @@ -364,6 +431,14 @@ func (m *macosSaveFileDialog) show() (string, error) { C.showSaveFileDialog(C.uint(m.dialog.id), C.bool(m.dialog.canCreateDirectories), C.bool(m.dialog.showHiddenFiles), + C.bool(m.dialog.canSelectHiddenExtension), + C.bool(m.dialog.hideExtension), + C.bool(m.dialog.treatsFilePackagesAsDirectories), + C.bool(m.dialog.allowOtherFileTypes), + toCString(m.dialog.message), + toCString(m.dialog.directory), + toCString(m.dialog.buttonText), + toCString(m.dialog.filename), nsWindow) return <-saveFileResponses[m.dialog.id], nil } From b04312603194f15e78d13a15b7b7dc72aee7acf7 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Fri, 23 Dec 2022 07:34:12 +1100 Subject: [PATCH 46/85] Add open file dialog filters Add clipboard Fix mouse event handling --- .gitignore | 3 +- exp/.gitignore | 4 ++ exp/examples/clipboard/main.go | 65 +++++++++++++++++++++ exp/examples/dialogs/main.go | 4 +- exp/examples/plain/main.go | 11 ---- exp/pkg/application/application.go | 8 +++ exp/pkg/application/application_darwin.go | 24 +++++--- exp/pkg/application/clipboard.go | 26 +++++++++ exp/pkg/application/clipboard_darwin.go | 56 ++++++++++++++++++ exp/pkg/application/dialogs.go | 17 ++++++ exp/pkg/application/dialogs_darwin.go | 71 ++++++++++++++++++++--- exp/pkg/application/dialogs_delegate.h | 14 +++++ exp/pkg/application/dialogs_delegate.m | 36 ++++++++++++ 13 files changed, 310 insertions(+), 29 deletions(-) create mode 100644 exp/examples/clipboard/main.go create mode 100644 exp/pkg/application/clipboard.go create mode 100644 exp/pkg/application/clipboard_darwin.go create mode 100644 exp/pkg/application/dialogs_delegate.h create mode 100644 exp/pkg/application/dialogs_delegate.m diff --git a/.gitignore b/.gitignore index 8538f5c76..62acc1e8d 100644 --- a/.gitignore +++ b/.gitignore @@ -31,5 +31,4 @@ v2/test/kitchensink/frontend/package.json.md5 v2/cmd/wails/internal/commands/initialise/templates/testtemplates/ .env /website/static/img/.cache.json -/exp/examples/dialogs/menu -/exp/examples/menu/menu + diff --git a/exp/.gitignore b/exp/.gitignore index a57f29269..cc164c024 100644 --- a/exp/.gitignore +++ b/exp/.gitignore @@ -2,3 +2,7 @@ examples/kitchensink/kitchensink cmd/wails/wails /examples/systray/systray /examples/window/window +/examples/dialogs/dialogs +/examples/menu/menu +/examples/clipboard/clipboard +/examples/plain/plain diff --git a/exp/examples/clipboard/main.go b/exp/examples/clipboard/main.go new file mode 100644 index 000000000..7d5c777e0 --- /dev/null +++ b/exp/examples/clipboard/main.go @@ -0,0 +1,65 @@ +package main + +import ( + _ "embed" + "log" + "time" + + "github.com/wailsapp/wails/exp/pkg/application" +) + +func main() { + + app := application.New() + app.SetName("Clipboard Demo") + app.SetDescription("A demo of the clipboard") + + // Create a custom menu + menu := app.NewMenu() + menu.AddRole(application.AppMenu) + + setClipboardMenu := menu.AddSubmenu("Set Clipboard") + setClipboardMenu.Add("Set Text 'Hello'").OnClick(func(ctx *application.Context) { + success := app.Clipboard().SetText("Hello") + if !success { + app.NewInfoDialog().SetMessage("Failed to set clipboard text").Show() + } + }) + setClipboardMenu.Add("Set Text 'World'").OnClick(func(ctx *application.Context) { + success := app.Clipboard().SetText("World") + if !success { + app.NewInfoDialog().SetMessage("Failed to set clipboard text").Show() + } + }) + setClipboardMenu.Add("Set Text (current time)").OnClick(func(ctx *application.Context) { + success := app.Clipboard().SetText(time.Now().String()) + if !success { + app.NewInfoDialog().SetMessage("Failed to set clipboard text").Show() + } + }) + getClipboardMenu := menu.AddSubmenu("Get Clipboard") + getClipboardMenu.Add("Get Text").OnClick(func(ctx *application.Context) { + result := app.Clipboard().Text() + app.NewInfoDialog().SetMessage("Got:\n\n" + result).Show() + }) + + clearClipboardMenu := menu.AddSubmenu("Clear Clipboard") + clearClipboardMenu.Add("Clear Text").OnClick(func(ctx *application.Context) { + success := app.Clipboard().SetText("") + if success { + app.NewInfoDialog().SetMessage("Clipboard text cleared").Show() + } else { + app.NewInfoDialog().SetMessage("Clipboard text not cleared").Show() + } + }) + + app.SetMenu(menu) + + app.NewWindow() + + err := app.Run() + + if err != nil { + log.Fatal(err.Error()) + } +} diff --git a/exp/examples/dialogs/main.go b/exp/examples/dialogs/main.go index 96e5de440..1820b75b9 100644 --- a/exp/examples/dialogs/main.go +++ b/exp/examples/dialogs/main.go @@ -249,7 +249,9 @@ func main() { AllowsOtherFileTypes(true). TreatsFilePackagesAsDirectories(true). ShowHiddenFiles(true). - CanSelectHiddenExtension(true) + CanSelectHiddenExtension(true). + AddFilter("Text Files", "*.txt; *.md"). + AddFilter("Video Files", "*.mov; *.mp4; *.avi") if runtime.GOOS == "darwin" { dialog.SetMessage("Select a file") diff --git a/exp/examples/plain/main.go b/exp/examples/plain/main.go index 61329f7dd..cdd59c2af 100644 --- a/exp/examples/plain/main.go +++ b/exp/examples/plain/main.go @@ -24,17 +24,6 @@ func main() { TitleBar: options.TitleBarHiddenInset, }, }) - // Create window - app.NewWindowWithOptions(&options.Window{ - Title: "Plain Bundle", - EnableDevTools: true, - HTML: `Plain Bundle

Plain Bundle

This is a plain bundle. It has no frontend code.

`, - CSS: `body { background-color: rgba(255, 255, 255, 0); } .main { color: white; margin: 20%; }`, - Mac: &options.MacWindow{ - Backdrop: options.MacBackdropTranslucent, - TitleBar: options.TitleBarHiddenInset, - }, - }) err := app.Run() diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index 067372a0d..159c20423 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -91,6 +91,7 @@ type App struct { name string description string icon []byte + clipboard *Clipboard } func (a *App) getSystemTrayID() uint { @@ -348,3 +349,10 @@ func (a *App) NewOpenFileDialog() *OpenFileDialog { func (a *App) NewSaveFileDialog() *SaveFileDialog { return newSaveFileDialog() } + +func (a *App) Clipboard() *Clipboard { + if a.clipboard == nil { + a.clipboard = newClipboard() + } + return a.clipboard +} diff --git a/exp/pkg/application/application_darwin.go b/exp/pkg/application/application_darwin.go index ff13bbad1..b92677b67 100644 --- a/exp/pkg/application/application_darwin.go +++ b/exp/pkg/application/application_darwin.go @@ -23,23 +23,31 @@ static void init(void) { [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskLeftMouseDown handler:^NSEvent * _Nullable(NSEvent * _Nonnull event) { NSWindow* eventWindow = [event window]; - if (![eventWindow respondsToSelector:@selector(handleLeftMouseDown)]) { + if (eventWindow == nil ) { + return event; + } + WindowDelegate* windowDelegate = (WindowDelegate*)[eventWindow delegate]; + if (windowDelegate == nil) { return event; } - - WindowDelegate* windowDelegate = (WindowDelegate*)[eventWindow delegate]; - [windowDelegate handleLeftMouseDown:event]; + if ([windowDelegate respondsToSelector:@selector(handleLeftMouseDown:)]) { + [windowDelegate handleLeftMouseDown:event]; + } return event; }]; [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskLeftMouseUp handler:^NSEvent * _Nullable(NSEvent * _Nonnull event) { NSWindow* eventWindow = [event window]; - if (![eventWindow respondsToSelector:@selector(handleLeftMouseUp)]) { + if (eventWindow == nil ) { + return event; + } + WindowDelegate* windowDelegate = (WindowDelegate*)[eventWindow delegate]; + if (windowDelegate == nil) { return event; } - - WindowDelegate* windowDelegate = (WindowDelegate*)[eventWindow delegate]; - [windowDelegate handleLeftMouseUp:eventWindow]; + if ([windowDelegate respondsToSelector:@selector(handleLeftMouseUp:)]) { + [windowDelegate handleLeftMouseUp:eventWindow]; + } return event; }]; } diff --git a/exp/pkg/application/clipboard.go b/exp/pkg/application/clipboard.go new file mode 100644 index 000000000..e823ace92 --- /dev/null +++ b/exp/pkg/application/clipboard.go @@ -0,0 +1,26 @@ +package application + +import "C" + +type clipboardImpl interface { + setText(text string) bool + text() string +} + +type Clipboard struct { + impl clipboardImpl +} + +func newClipboard() *Clipboard { + return &Clipboard{ + impl: newClipboardImpl(), + } +} + +func (c *Clipboard) SetText(text string) bool { + return c.impl.setText(text) +} + +func (c *Clipboard) Text() string { + return c.impl.text() +} diff --git a/exp/pkg/application/clipboard_darwin.go b/exp/pkg/application/clipboard_darwin.go new file mode 100644 index 000000000..1d9fb0c59 --- /dev/null +++ b/exp/pkg/application/clipboard_darwin.go @@ -0,0 +1,56 @@ +//go:build darwin + +package application + +/* +#cgo CFLAGS: -x objective-c +#cgo LDFLAGS: -framework Cocoa -mmacosx-version-min=10.13 + +#import +#import + +bool setClipboardText(const char* text) { + NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard]; + NSError *error = nil; + NSString *string = [NSString stringWithUTF8String:text]; + [pasteBoard clearContents]; + return [pasteBoard setString:string forType:NSPasteboardTypeString]; +} + +const char* getClipboardText() { + NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + NSString *text = [pasteboard stringForType:NSPasteboardTypeString]; + return [text UTF8String]; +} + +*/ +import "C" +import ( + "sync" + "unsafe" +) + +var clipboardLock sync.RWMutex + +type macosClipboard struct{} + +func (m macosClipboard) setText(text string) bool { + clipboardLock.Lock() + defer clipboardLock.Unlock() + cText := C.CString(text) + success := C.setClipboardText(cText) + C.free(unsafe.Pointer(cText)) + return bool(success) +} + +func (m macosClipboard) text() string { + clipboardLock.RLock() + defer clipboardLock.RUnlock() + clipboardText := C.getClipboardText() + result := C.GoString(clipboardText) + return result +} + +func newClipboardImpl() *macosClipboard { + return &macosClipboard{} +} diff --git a/exp/pkg/application/dialogs.go b/exp/pkg/application/dialogs.go index f59123742..8cea0cdd9 100644 --- a/exp/pkg/application/dialogs.go +++ b/exp/pkg/application/dialogs.go @@ -2,6 +2,7 @@ package application import "C" import ( + "strings" "sync" ) @@ -119,6 +120,11 @@ type openFileDialogImpl interface { show() ([]string, error) } +type fileFilter struct { + displayName string // Filter information EG: "Image Files (*.jpg, *.png)" + pattern string // semicolon separated list of extensions, EG: "*.jpg;*.png" +} + type OpenFileDialog struct { id uint canChooseDirectories bool @@ -131,6 +137,7 @@ type OpenFileDialog struct { canSelectHiddenExtension bool treatsFilePackagesAsDirectories bool allowsOtherFileTypes bool + filters []fileFilter title string message string @@ -205,6 +212,16 @@ func (d *OpenFileDialog) PromptForSingleSelection() (string, error) { return result, err } +// AddFilter adds a filter to the dialog. The filter is a display name and a semicolon separated list of extensions. +// EG: AddFilter("Image Files", "*.jpg;*.png") +func (d *OpenFileDialog) AddFilter(displayName, pattern string) *OpenFileDialog { + d.filters = append(d.filters, fileFilter{ + displayName: strings.TrimSpace(displayName), + pattern: strings.TrimSpace(pattern), + }) + return d +} + func (d *OpenFileDialog) PromptForMultipleSelection() ([]string, error) { d.allowsMultipleSelection = true if d.impl == nil { diff --git a/exp/pkg/application/dialogs_darwin.go b/exp/pkg/application/dialogs_darwin.go index 1aa47966d..5cfa621a9 100644 --- a/exp/pkg/application/dialogs_darwin.go +++ b/exp/pkg/application/dialogs_darwin.go @@ -4,10 +4,13 @@ package application /* #cgo CFLAGS: -x objective-c -#cgo LDFLAGS: -framework Cocoa -mmacosx-version-min=10.13 +#cgo LDFLAGS: -framework Cocoa -mmacosx-version-min=10.13 -framework UniformTypeIdentifiers #import +#import +#import "dialogs_delegate.h" + extern void openFileDialogCallback(uint id, char* path); extern void openFileDialogCallbackEnd(uint id); extern void saveFileDialogCallback(uint id, char* path); @@ -103,16 +106,16 @@ static void alertAddButton(void *dialog, char *label, bool isDefault, bool isCan } } -static void processOpenFileDialogResults(NSOpenPanel *panel, NSInteger result, bool allowsMultipleSelection, uint dialogID) { +static void processOpenFileDialogResults(NSOpenPanel *panel, NSInteger result, uint dialogID) { const char *path = NULL; if (result == NSModalResponseOK) { - if (allowsMultipleSelection) { + NSArray *urls = [panel URLs]; + if ([urls count] > 0) { NSArray *urls = [panel URLs]; for (NSURL *url in urls) { path = [[url path] UTF8String]; openFileDialogCallback(dialogID, (char *)path); } - } else { NSURL *url = [panel URL]; path = [[url path] UTF8String]; @@ -133,15 +136,45 @@ static void showOpenFileDialog(unsigned int dialogID, bool hideExtension, bool treatsFilePackagesAsDirectories, bool allowsOtherFileTypes, + char *filterPatterns, + unsigned int filterPatternsCount, char* message, char* directory, char* buttonText, + void *window) { // run on main thread dispatch_async(dispatch_get_main_queue(), ^{ + NSOpenPanel *panel = [NSOpenPanel openPanel]; + // print out filterPatterns if length > 0 + if (filterPatternsCount > 0) { + OpenPanelDelegate *delegate = [[OpenPanelDelegate alloc] init]; + [panel setDelegate:delegate]; + // Initialise NSString with bytes and UTF8 encoding + NSString *filterPatternsString = [[NSString alloc] initWithBytes:filterPatterns length:filterPatternsCount encoding:NSUTF8StringEncoding]; + // Convert NSString to NSArray + delegate.allowedExtensions = [filterPatternsString componentsSeparatedByString:@";"]; + + // Use UTType if macOS 11 or higher to add file filters + if (@available(macOS 11, *)) { + NSMutableArray *filterTypes = [NSMutableArray array]; + // Iterate the filtertypes, create uti's that are limited to the file extensions then add + for (NSString *filterType in delegate.allowedExtensions) { + [filterTypes addObject:[UTType typeWithFilenameExtension:filterType]]; + } + [panel setAllowedContentTypes:filterTypes]; + } else { + [panel setAllowedFileTypes:delegate.allowedExtensions]; + } + + // Free the memory + free(filterPatterns); + } + + if (message != NULL) { [panel setMessage:[NSString stringWithUTF8String:message]]; free(message); @@ -167,13 +200,15 @@ static void showOpenFileDialog(unsigned int dialogID, [panel setTreatsFilePackagesAsDirectories:treatsFilePackagesAsDirectories]; [panel setAllowsOtherFileTypes:allowsOtherFileTypes]; + + if (window != NULL) { [panel beginSheetModalForWindow:(__bridge NSWindow *)window completionHandler:^(NSInteger result) { - processOpenFileDialogResults(panel, result, allowsMultipleSelection, dialogID); + processOpenFileDialogResults(panel, result, dialogID); }]; } else { [panel beginWithCompletionHandler:^(NSInteger result) { - processOpenFileDialogResults(panel, result, allowsMultipleSelection, dialogID); + processOpenFileDialogResults(panel, result, dialogID); }]; } }); @@ -192,7 +227,7 @@ static void showSaveFileDialog(unsigned int dialogID, char* filename, void *window) { -// run on main thread + // run on main thread dispatch_async(dispatch_get_main_queue(), ^{ NSSavePanel *panel = [NSSavePanel savePanel]; @@ -249,6 +284,7 @@ static void showSaveFileDialog(unsigned int dialogID, */ import "C" import ( + "strings" "unsafe" ) @@ -367,6 +403,25 @@ func (m *macosOpenFileDialog) show() ([]string, error) { // get NSWindow from window nsWindow = m.dialog.window.impl.(*macosWindow).nsWindow } + + // Massage filter patterns into macOS format + // We iterate all filter patterns, tidy them up and then join them with a semicolon + // This should produce a single string of extensions like "png;jpg;gif" + var filterPatterns string + if len(m.dialog.filters) > 0 { + var allPatterns []string + for _, filter := range m.dialog.filters { + patternComponents := strings.Split(filter.pattern, ";") + for i, component := range patternComponents { + filterPattern := strings.TrimSpace(component) + filterPattern = strings.TrimPrefix(filterPattern, "*.") + patternComponents[i] = filterPattern + } + allPatterns = append(allPatterns, strings.Join(patternComponents, ";")) + } + filterPatterns = strings.Join(allPatterns, ";") + } + C.showOpenFileDialog(C.uint(m.dialog.id), C.bool(m.dialog.canChooseFiles), C.bool(m.dialog.canChooseDirectories), @@ -377,6 +432,8 @@ func (m *macosOpenFileDialog) show() ([]string, error) { C.bool(m.dialog.hideExtension), C.bool(m.dialog.treatsFilePackagesAsDirectories), C.bool(m.dialog.allowsOtherFileTypes), + toCString(filterPatterns), + C.uint(len(filterPatterns)), toCString(m.dialog.message), toCString(m.dialog.directory), toCString(m.dialog.buttonText), diff --git a/exp/pkg/application/dialogs_delegate.h b/exp/pkg/application/dialogs_delegate.h new file mode 100644 index 000000000..07657f8b9 --- /dev/null +++ b/exp/pkg/application/dialogs_delegate.h @@ -0,0 +1,14 @@ +//go:build darwin + +#ifndef _DIALOGS_DELEGATE_H_ +#define _DIALOGS_DELEGATE_H_ + +#import +#import + +// create an NSOpenPanel delegate to handle the callback +@interface OpenPanelDelegate : NSObject +@property (nonatomic, strong) NSArray *allowedExtensions; +@end + +#endif \ No newline at end of file diff --git a/exp/pkg/application/dialogs_delegate.m b/exp/pkg/application/dialogs_delegate.m new file mode 100644 index 000000000..67f34e2eb --- /dev/null +++ b/exp/pkg/application/dialogs_delegate.m @@ -0,0 +1,36 @@ +//go:build darwin + +#import "dialogs_delegate.h" + +// Override shouldEnableURL +@implementation OpenPanelDelegate +- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url { + if (url == nil) { + return NO; + } + NSFileManager *fileManager = [NSFileManager defaultManager]; + BOOL isDirectory = NO; + if ([fileManager fileExistsAtPath:url.path isDirectory:&isDirectory] && isDirectory) { + return YES; + } + if (self.allowedExtensions == nil) { + return YES; + } + NSString *extension = url.pathExtension; + if (extension == nil) { + return NO; + } + if ([extension isEqualToString:@""]) { + return NO; + } + if ([self.allowedExtensions containsObject:extension]) { + return YES; + } + return NO; +} + +@end + + + + From 2946a0aa25359cbc866e397b3a44f964415f7eb9 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Fri, 23 Dec 2022 19:55:54 +1100 Subject: [PATCH 47/85] GetCurrentWindow -> CurrentWindow --- exp/examples/dialogs/main.go | 4 ++-- exp/examples/menu/main.go | 6 +++--- exp/pkg/application/application.go | 2 +- exp/pkg/application/menuitem_darwin.go | 20 ++++++++++---------- exp/pkg/application/roles.go | 2 +- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/exp/examples/dialogs/main.go b/exp/examples/dialogs/main.go index 1820b75b9..0354fee7a 100644 --- a/exp/examples/dialogs/main.go +++ b/exp/examples/dialogs/main.go @@ -166,7 +166,7 @@ func main() { CanChooseFiles(true). CanCreateDirectories(true). ShowHiddenFiles(true). - AttachToWindow(app.GetCurrentWindow()). + AttachToWindow(app.CurrentWindow()). PromptForSingleSelection() if result != "" { app.NewInfoDialog().SetMessage(result).Show() @@ -277,7 +277,7 @@ func main() { }) saveMenu.Add("Select File (Attach To Window)").OnClick(func(ctx *application.Context) { result, _ := app.NewSaveFileDialog(). - AttachToWindow(app.GetCurrentWindow()). + AttachToWindow(app.CurrentWindow()). PromptForSingleSelection() if result != "" { app.NewInfoDialog().SetMessage(result).Show() diff --git a/exp/examples/menu/main.go b/exp/examples/menu/main.go index 3f12f3962..6f3581113 100644 --- a/exp/examples/menu/main.go +++ b/exp/examples/menu/main.go @@ -30,11 +30,11 @@ func main() { // You can control the current window from the menu myMenu.Add("Lock Window Resize").OnClick(func(ctx *application.Context) { - if app.GetCurrentWindow().Resizable() { - app.GetCurrentWindow().SetResizable(false) + if app.CurrentWindow().Resizable() { + app.CurrentWindow().SetResizable(false) ctx.ClickedMenuItem().SetLabel("Unlock Window Resize") } else { - app.GetCurrentWindow().SetResizable(true) + app.CurrentWindow().SetResizable(true) ctx.ClickedMenuItem().SetLabel("Lock Window Resize") } }) diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index 159c20423..039b6eba1 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -245,7 +245,7 @@ func (a *App) handleMenuItemClicked(menuItemID uint) { menuItem.handleClick() } -func (a *App) GetCurrentWindow() *Window { +func (a *App) CurrentWindow() *Window { if a.impl == nil { return nil } diff --git a/exp/pkg/application/menuitem_darwin.go b/exp/pkg/application/menuitem_darwin.go index 0ec8e45d3..f26e374d5 100644 --- a/exp/pkg/application/menuitem_darwin.go +++ b/exp/pkg/application/menuitem_darwin.go @@ -509,7 +509,7 @@ func newCloseMenuItem() *MenuItem { return newMenuItem("Close"). SetAccelerator("CmdOrCtrl+w"). OnClick(func(ctx *Context) { - currentWindow := globalApplication.GetCurrentWindow() + currentWindow := globalApplication.CurrentWindow() if currentWindow != nil { currentWindow.Close() } @@ -520,7 +520,7 @@ func newReloadMenuItem() *MenuItem { return newMenuItem("Reload"). SetAccelerator("CmdOrCtrl+r"). OnClick(func(ctx *Context) { - currentWindow := globalApplication.GetCurrentWindow() + currentWindow := globalApplication.CurrentWindow() if currentWindow != nil { currentWindow.Reload() } @@ -531,7 +531,7 @@ func newForceReloadMenuItem() *MenuItem { return newMenuItem("Force Reload"). SetAccelerator("CmdOrCtrl+Shift+r"). OnClick(func(ctx *Context) { - currentWindow := globalApplication.GetCurrentWindow() + currentWindow := globalApplication.CurrentWindow() if currentWindow != nil { currentWindow.ForceReload() } @@ -541,7 +541,7 @@ func newForceReloadMenuItem() *MenuItem { func newToggleFullscreenMenuItem() *MenuItem { result := newMenuItem("Toggle Full Screen"). OnClick(func(ctx *Context) { - currentWindow := globalApplication.GetCurrentWindow() + currentWindow := globalApplication.CurrentWindow() if currentWindow != nil { currentWindow.ToggleFullscreen() } @@ -558,7 +558,7 @@ func newToggleDevToolsMenuItem() *MenuItem { return newMenuItem("Toggle Developer Tools"). SetAccelerator("Alt+Command+I"). OnClick(func(ctx *Context) { - currentWindow := globalApplication.GetCurrentWindow() + currentWindow := globalApplication.CurrentWindow() if currentWindow != nil { currentWindow.ToggleDevTools() } @@ -570,7 +570,7 @@ func newResetZoomMenuItem() *MenuItem { return newMenuItem("Actual Size"). SetAccelerator("CmdOrCtrl+0"). OnClick(func(ctx *Context) { - currentWindow := globalApplication.GetCurrentWindow() + currentWindow := globalApplication.CurrentWindow() if currentWindow != nil { currentWindow.ResetZoom() } @@ -581,7 +581,7 @@ func newZoomInMenuItem() *MenuItem { return newMenuItem("Zoom In"). SetAccelerator("CmdOrCtrl+plus"). OnClick(func(ctx *Context) { - currentWindow := globalApplication.GetCurrentWindow() + currentWindow := globalApplication.CurrentWindow() if currentWindow != nil { currentWindow.ZoomIn() } @@ -592,7 +592,7 @@ func newZoomOutMenuItem() *MenuItem { return newMenuItem("Zoom Out"). SetAccelerator("CmdOrCtrl+-"). OnClick(func(ctx *Context) { - currentWindow := globalApplication.GetCurrentWindow() + currentWindow := globalApplication.CurrentWindow() if currentWindow != nil { currentWindow.ZoomOut() } @@ -603,7 +603,7 @@ func newMinimizeMenuItem() *MenuItem { return newMenuItem("Minimize"). SetAccelerator("CmdOrCtrl+M"). OnClick(func(ctx *Context) { - currentWindow := globalApplication.GetCurrentWindow() + currentWindow := globalApplication.CurrentWindow() if currentWindow != nil { currentWindow.Minimize() } @@ -613,7 +613,7 @@ func newMinimizeMenuItem() *MenuItem { func newZoomMenuItem() *MenuItem { return newMenuItem("Zoom"). OnClick(func(ctx *Context) { - currentWindow := globalApplication.GetCurrentWindow() + currentWindow := globalApplication.CurrentWindow() if currentWindow != nil { currentWindow.Zoom() } diff --git a/exp/pkg/application/roles.go b/exp/pkg/application/roles.go index 00f32148d..b6f2b2da9 100644 --- a/exp/pkg/application/roles.go +++ b/exp/pkg/application/roles.go @@ -140,7 +140,7 @@ func newWindowMenu() *MenuItem { func newHelpMenu() *MenuItem { menu := NewMenu() menu.Add("Learn More").OnClick(func(ctx *Context) { - globalApplication.GetCurrentWindow().NavigateToURL("https://wails.io") + globalApplication.CurrentWindow().NavigateToURL("https://wails.io") }) subMenu := newSubMenuItem("Help") subMenu.submenu = menu From b7f1defbf33d16127024765e7a3317ac4f5b63b2 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Fri, 23 Dec 2022 23:18:28 +1100 Subject: [PATCH 48/85] NavigateToURL -> SetURL Fixed typo in colour Removed EnableDevTools --- exp/examples/kitchensink/main.go | 14 +-- exp/examples/window/main.go | 51 +++++--- exp/pkg/application/roles.go | 2 +- exp/pkg/application/window.go | 168 +++++++++++++-------------- exp/pkg/application/window_darwin.go | 33 ++++-- exp/pkg/options/window.go | 14 +-- 6 files changed, 150 insertions(+), 132 deletions(-) diff --git a/exp/examples/kitchensink/main.go b/exp/examples/kitchensink/main.go index fb35f9e31..a7138db78 100644 --- a/exp/examples/kitchensink/main.go +++ b/exp/examples/kitchensink/main.go @@ -109,12 +109,11 @@ func main() { mySystray.SetIconPosition(application.NSImageLeading) myWindow := app.NewWindowWithOptions(&options.Window{ - Title: "Kitchen Sink", - Width: 600, - Height: 400, - AlwaysOnTop: true, - DisableResize: false, - EnableDevTools: true, + Title: "Kitchen Sink", + Width: 600, + Height: 400, + AlwaysOnTop: true, + DisableResize: false, BackgroundColour: &options.RGBA{ Red: 255, Green: 255, @@ -207,9 +206,8 @@ func main() { myWindow2Lock.RLock() myWindow.SetTitle("Wooooo") myWindow.SetAlwaysOnTop(true) - myWindow2.EnableDevTools() myWindow2.SetTitle("OMFG") - myWindow2.NavigateToURL("https://wails.io") + myWindow2.SetURL("https://wails.io") myWindow.SetMinSize(600, 600) myWindow.SetMaxSize(650, 650) myWindow.Center() diff --git a/exp/examples/window/main.go b/exp/examples/window/main.go index cb0dea554..926a90d86 100644 --- a/exp/examples/window/main.go +++ b/exp/examples/window/main.go @@ -3,33 +3,54 @@ package main import ( _ "embed" "log" + "strconv" "github.com/wailsapp/wails/exp/pkg/options" - "github.com/wailsapp/wails/exp/pkg/events" - "github.com/wailsapp/wails/exp/pkg/application" ) func main() { app := application.New() + app.SetName("Window Demo") + app.SetDescription("A demo of the windowing capabilities") - // Create window - myWindow := app.NewWindowWithOptions(&options.Window{ - Title: "My Window", - Width: 800, - Height: 600, - URL: "https://wails.io", - EnableDevTools: true, - Mac: &options.MacWindow{ - Backdrop: options.MacBackdropTranslucent, - TitleBar: options.TitleBarHiddenInsetUnified, - }, + // Create a custom menu + menu := app.NewMenu() + menu.AddRole(application.AppMenu) + + windowCounter := 1 + + // Let's make a "Demo" menu + myMenu := menu.AddSubmenu("Window") + myMenu.Add("New Blank Window").OnClick(func(ctx *application.Context) { + app.NewWindow().SetTitle("Window " + strconv.Itoa(windowCounter)).Run() + windowCounter++ }) - myWindow.On(events.Mac.WindowDidBecomeMain, func() { - println("Window did become main") + myMenu.Add("New Window").OnClick(func(ctx *application.Context) { + app.NewWindow(). + SetTitle("Window " + strconv.Itoa(windowCounter)). + SetBackgroundColour(&options.RGBA{ + Red: 255, + Green: 0, + Blue: 0, + Alpha: 0, + }). + Run() + windowCounter++ + }) + myMenu.Add("New Webview").OnClick(func(ctx *application.Context) { + app.NewWindow(). + SetTitle("Webview " + strconv.Itoa(windowCounter)). + SetURL("https://wails.app"). + Run() + windowCounter++ }) + // Disabled menu item + myMenu.Add("Not Enabled").SetEnabled(false) + + app.SetMenu(menu) err := app.Run() if err != nil { diff --git a/exp/pkg/application/roles.go b/exp/pkg/application/roles.go index b6f2b2da9..e85844e24 100644 --- a/exp/pkg/application/roles.go +++ b/exp/pkg/application/roles.go @@ -140,7 +140,7 @@ func newWindowMenu() *MenuItem { func newHelpMenu() *MenuItem { menu := NewMenu() menu.Add("Learn More").OnClick(func(ctx *Context) { - globalApplication.CurrentWindow().NavigateToURL("https://wails.io") + globalApplication.CurrentWindow().SetURL("https://wails.io") }) subMenu := newSubMenuItem("Help") subMenu.submenu = menu diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index 2e90085e5..0eb9f9871 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -12,11 +12,10 @@ type windowImpl interface { setTitle(title string) setSize(width, height int) setAlwaysOnTop(alwaysOnTop bool) - navigateToURL(url string) + setURL(url string) setResizable(resizable bool) setMinSize(width, height int) setMaxSize(width, height int) - enableDevTools() execJS(js string) setMaximised() setMinimised() @@ -25,7 +24,7 @@ type windowImpl interface { isMaximised() bool isFullscreen() bool restore() - setBackgroundColor(color *options.RGBA) + setBackgroundColour(color *options.RGBA) run() center() size() (int, int) @@ -43,7 +42,7 @@ type windowImpl interface { close() zoom() minimize() - renderHTML(html string) + setHTML(html string) } type Window struct { @@ -80,97 +79,93 @@ func NewWindow(options *options.Window) *Window { } } -func (w *Window) SetTitle(title string) { +func (w *Window) SetTitle(title string) *Window { w.implLock.RLock() defer w.implLock.RUnlock() - if w.impl == nil { - w.options.Title = title - return + w.options.Title = title + if w.impl != nil { + w.impl.setTitle(title) } - w.impl.setTitle(title) + return w } -func (w *Window) SetSize(width, height int) { - if w.impl == nil { - w.options.Width = width - w.options.Height = height - return +func (w *Window) SetSize(width, height int) *Window { + w.options.Width = width + w.options.Height = height + if w.impl != nil { + w.impl.setSize(width, height) } - w.impl.setSize(width, height) + return w } func (w *Window) Run() { + if w.impl != nil { + return + } w.implLock.Lock() w.impl = newWindowImpl(w) w.implLock.Unlock() w.impl.run() } -func (w *Window) SetAlwaysOnTop(b bool) { +func (w *Window) SetAlwaysOnTop(b bool) *Window { + w.options.AlwaysOnTop = b if w.impl == nil { - w.options.AlwaysOnTop = b - return + w.impl.setAlwaysOnTop(b) } - w.impl.setAlwaysOnTop(b) + return w } -func (w *Window) NavigateToURL(s string) { - if w.impl == nil { - w.options.URL = s - return +func (w *Window) SetURL(s string) *Window { + w.options.URL = s + if w.impl != nil { + w.impl.setURL(s) } - w.impl.navigateToURL(s) + return w } -func (w *Window) SetResizable(b bool) { +func (w *Window) SetResizable(b bool) *Window { w.options.DisableResize = !b - if w.impl == nil { - return + if w.impl != nil { + w.impl.setResizable(b) } - w.impl.setResizable(b) + return w } func (w *Window) Resizable() bool { return !w.options.DisableResize } -func (w *Window) SetMinSize(minWidth, minHeight int) { - if w.impl == nil { - w.options.MinWidth = minWidth - if w.options.Width < minWidth { - w.options.Width = minWidth - } - w.options.MinHeight = minHeight - if w.options.Height < minHeight { - w.options.Height = minHeight - } - return +func (w *Window) SetMinSize(minWidth, minHeight int) *Window { + w.options.MinWidth = minWidth + if w.options.Width < minWidth { + w.options.Width = minWidth } - w.impl.setSize(w.options.Width, w.options.Height) - w.impl.setMinSize(minWidth, minHeight) -} -func (w *Window) SetMaxSize(maxWidth, maxHeight int) { - if w.impl == nil { - w.options.MinWidth = maxWidth - if w.options.Width > maxWidth { - w.options.Width = maxWidth - } - w.options.MinHeight = maxHeight - if w.options.Height > maxHeight { - w.options.Height = maxHeight - } - return + w.options.MinHeight = minHeight + if w.options.Height < minHeight { + w.options.Height = minHeight } - w.impl.setSize(w.options.Width, w.options.Height) - w.impl.setMaxSize(maxWidth, maxHeight) + if w.impl != nil { + w.impl.setSize(w.options.Width, w.options.Height) + w.impl.setMinSize(minWidth, minHeight) + } + return w } -func (w *Window) EnableDevTools() { - if w.impl == nil { - w.options.EnableDevTools = true - return +func (w *Window) SetMaxSize(maxWidth, maxHeight int) *Window { + w.options.MinWidth = maxWidth + if w.options.Width > maxWidth { + w.options.Width = maxWidth } - w.impl.enableDevTools() + w.options.MinHeight = maxHeight + if w.options.Height > maxHeight { + w.options.Height = maxHeight + } + if w.impl != nil { + w.impl.setSize(w.options.Width, w.options.Height) + w.impl.setMaxSize(maxWidth, maxHeight) + } + return w } func (w *Window) ExecJS(js string) { @@ -180,30 +175,29 @@ func (w *Window) ExecJS(js string) { w.impl.execJS(js) } -func (w *Window) SetMaximized() { +func (w *Window) SetMaximized() *Window { w.options.StartState = options.WindowStateMaximised - if w.impl == nil { - return + if w.impl != nil { + w.impl.setMaximised() } - w.impl.setMaximised() + return w } // Set Minimized -func (w *Window) SetMinimized() { +func (w *Window) SetMinimized() *Window { w.options.StartState = options.WindowStateMinimised if w.impl == nil { - return + w.impl.setMinimised() } - w.impl.setMinimised() + return w } -// Set Fullscreen -func (w *Window) SetFullscreen() { +func (w *Window) SetFullscreen() *Window { w.options.StartState = options.WindowStateFullscreen if w.impl == nil { - return + w.impl.setFullscreen() } - w.impl.setFullscreen() + return w } // IsMinimised returns true if the window is minimised @@ -240,12 +234,12 @@ func (w *Window) IsFullscreen() bool { return w.impl.isFullscreen() } -func (w *Window) SetBackgroundColor(color *options.RGBA) { - w.options.BackgroundColour = color - if w.impl == nil { - return +func (w *Window) SetBackgroundColour(colour *options.RGBA) *Window { + w.options.BackgroundColour = colour + if w.impl != nil { + w.impl.setBackgroundColour(colour) } - w.impl.setBackgroundColor(color) + return w } func (w *Window) handleMessage(message string) { @@ -278,10 +272,6 @@ func (w *Window) handleWindowEvent(id uint) { w.eventListenersLock.RUnlock() } -func (w *Window) ID() uint { - return w.id -} - func (w *Window) Width() int { if w.impl == nil { return 0 @@ -340,11 +330,12 @@ func (w *Window) ToggleDevTools() { w.impl.toggleDevTools() } -func (w *Window) ResetZoom() { - if w.impl == nil { - return +func (w *Window) ResetZoom() *Window { + if w.impl != nil { + w.impl.resetZoom() } - w.impl.resetZoom() + return w + } func (w *Window) ZoomIn() { @@ -382,9 +373,10 @@ func (w *Window) Zoom() { w.impl.zoom() } -func (w *Window) RenderHTML(html string) { - if w.impl == nil { - return +func (w *Window) SetHTML(html string) *Window { + w.options.HTML = html + if w.impl != nil { + w.impl.setHTML(html) } - w.impl.renderHTML(html) + return w } diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index f4471eac4..d4704b1cf 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -301,8 +301,8 @@ void webviewSetTransparent(void* nsWindow) { }); } -// Set webview background color -void webviewSetBackgroundColor(void* nsWindow, int r, int g, int b, int alpha) { +// Set webview background colour +void webviewSetBackgroundColour(void* nsWindow, int r, int g, int b, int alpha) { // Set webview background color on main thread dispatch_async(dispatch_get_main_queue(), ^{ // Get window delegate @@ -312,6 +312,17 @@ void webviewSetBackgroundColor(void* nsWindow, int r, int g, int b, int alpha) { }); } +// Set the window background colour +void windowSetBackgroundColour(void* nsWindow, int r, int g, int b, int alpha) { + // Set window background color on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + // Get window + NSWindow* window = (NSWindow*)nsWindow; + // Set window background color + [window setBackgroundColor:[NSColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:alpha/255.0]]; + }); +} + // Set Window maximised void windowSetMaximised(void* nsWindow) { // Set window maximized on main thread @@ -746,7 +757,7 @@ func (w *macosWindow) execJS(js string) { C.windowExecJS(w.nsWindow, C.CString(js)) } -func (w *macosWindow) navigateToURL(url string) { +func (w *macosWindow) setURL(url string) { C.navigationLoadURL(w.nsWindow, C.CString(url)) } @@ -831,10 +842,8 @@ func (w *macosWindow) run() { if w.parent.options.MaxWidth != 0 || w.parent.options.MaxHeight != 0 { w.setMaxSize(w.parent.options.MaxWidth, w.parent.options.MaxHeight) } - if w.parent.options.EnableDevTools { - w.enableDevTools() - } - w.setBackgroundColor(w.parent.options.BackgroundColour) + w.enableDevTools() + w.setBackgroundColour(w.parent.options.BackgroundColour) if w.parent.options.Mac != nil { macOptions := w.parent.options.Mac switch macOptions.Backdrop { @@ -879,7 +888,7 @@ func (w *macosWindow) run() { C.windowCenter(w.nsWindow) if w.parent.options.URL != "" { - w.navigateToURL(w.parent.options.URL) + w.setURL(w.parent.options.URL) } // We need to wait for the HTML to load before we can execute the javascript w.parent.On(events.Mac.WebViewDidFinishNavigation, func() { @@ -891,18 +900,18 @@ func (w *macosWindow) run() { } }) if w.parent.options.HTML != "" { - w.renderHTML(w.parent.options.HTML) + w.setHTML(w.parent.options.HTML) } C.windowShow(w.nsWindow) }) } -func (w *macosWindow) setBackgroundColor(colour *options.RGBA) { +func (w *macosWindow) setBackgroundColour(colour *options.RGBA) { if colour == nil { return } - C.webviewSetBackgroundColor(w.nsWindow, C.int(colour.Red), C.int(colour.Green), C.int(colour.Blue), C.int(colour.Alpha)) + C.windowSetBackgroundColour(w.nsWindow, C.int(colour.Red), C.int(colour.Green), C.int(colour.Blue), C.int(colour.Alpha)) } func (w *macosWindow) position() (int, int) { @@ -921,7 +930,7 @@ func (w *macosWindow) destroy() { C.windowDestroy(w.nsWindow) } -func (w *macosWindow) renderHTML(html string) { +func (w *macosWindow) setHTML(html string) { // Convert HTML to C string cHTML := C.CString(html) // Render HTML diff --git a/exp/pkg/options/window.go b/exp/pkg/options/window.go index fc931f95b..b6ce5e280 100644 --- a/exp/pkg/options/window.go +++ b/exp/pkg/options/window.go @@ -27,7 +27,6 @@ type Window struct { MinHeight int MaxWidth int MaxHeight int - EnableDevTools bool StartState WindowState Mac *MacWindow BackgroundColour *RGBA @@ -38,11 +37,10 @@ type Window struct { } var WindowDefaults = &Window{ - Title: "", - Width: 1024, - Height: 768, - URL: "https://wails.io", - EnableDevTools: true, + Title: "", + Width: 800, + Height: 600, + URL: "", } type Assets struct { @@ -50,9 +48,9 @@ type Assets struct { URL string // FS to use for loading assets from FS fs.FS - // Handler is a custom handler to use for serving assets. If this is set, the `URL` and `FS` fields are ignored. + // Handler is a custom handler to use for serving assets. If this is set, the `SetURL` and `FS` fields are ignored. Handler http.Handler - // Middleware is a custom middleware to use for serving assets. If this is set, the `URL` and `FS` fields are ignored. + // Middleware is a custom middleware to use for serving assets. If this is set, the `SetURL` and `FS` fields are ignored. Middleware func(http.Handler) http.Handler } From 2b91ced1b70a4d162d1ba266dd4936eccf30b66c Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sat, 24 Dec 2022 13:38:48 +1100 Subject: [PATCH 49/85] Support SetPosition Optimise event listener callbacks --- exp/examples/window/main.go | 15 +- exp/pkg/application/app_delegate.m | 84 ++++-- exp/pkg/application/application.go | 17 +- exp/pkg/application/application_darwin.go | 11 + exp/pkg/application/window.go | 90 +++--- exp/pkg/application/window_darwin.go | 20 ++ exp/pkg/application/window_delegate.m | 325 ++++++++++++++++------ exp/pkg/events/events.h | 2 + exp/pkg/events/events_darwin.go | 26 ++ exp/pkg/options/window.go | 2 + exp/tasks/events/generate.go | 175 ++++++------ 11 files changed, 533 insertions(+), 234 deletions(-) create mode 100644 exp/pkg/events/events_darwin.go diff --git a/exp/examples/window/main.go b/exp/examples/window/main.go index 926a90d86..9f17be321 100644 --- a/exp/examples/window/main.go +++ b/exp/examples/window/main.go @@ -5,15 +5,19 @@ import ( "log" "strconv" - "github.com/wailsapp/wails/exp/pkg/options" + "github.com/wailsapp/wails/exp/pkg/events" "github.com/wailsapp/wails/exp/pkg/application" + "github.com/wailsapp/wails/exp/pkg/options" ) func main() { app := application.New() app.SetName("Window Demo") app.SetDescription("A demo of the windowing capabilities") + app.On(events.Mac.ApplicationDidFinishLaunching, func() { + log.Println("ApplicationDidFinishLaunching") + }) // Create a custom menu menu := app.NewMenu() @@ -22,7 +26,7 @@ func main() { windowCounter := 1 // Let's make a "Demo" menu - myMenu := menu.AddSubmenu("Window") + myMenu := menu.AddSubmenu("New") myMenu.Add("New Blank Window").OnClick(func(ctx *application.Context) { app.NewWindow().SetTitle("Window " + strconv.Itoa(windowCounter)).Run() windowCounter++ @@ -48,8 +52,11 @@ func main() { }) // Disabled menu item - myMenu.Add("Not Enabled").SetEnabled(false) - + adjustMenu := menu.AddSubmenu("Adjust") + adjustMenu.Add("Set Position (0,0)").OnClick(func(ctx *application.Context) { + app.CurrentWindow().SetPosition(0, 0) + windowCounter++ + }) app.SetMenu(menu) err := app.Run() diff --git a/exp/pkg/application/app_delegate.m b/exp/pkg/application/app_delegate.m index c3a7bdcde..555fae2a3 100644 --- a/exp/pkg/application/app_delegate.m +++ b/exp/pkg/application/app_delegate.m @@ -1,6 +1,10 @@ //go:build darwin + #import "app_delegate.h" #import "../events/events.h" + +extern bool hasListeners(unsigned int); + @implementation AppDelegate - (void)dealloc { @@ -9,83 +13,123 @@ // GENERATED EVENTS START - (void)applicationDidBecomeActive:(NSNotification *)notification { - processApplicationEvent(EventApplicationDidBecomeActive); + if( hasListeners(EventApplicationDidBecomeActive) ) { + processApplicationEvent(EventApplicationDidBecomeActive); + } } - (void)applicationDidChangeBackingProperties:(NSNotification *)notification { - processApplicationEvent(EventApplicationDidChangeBackingProperties); + if( hasListeners(EventApplicationDidChangeBackingProperties) ) { + processApplicationEvent(EventApplicationDidChangeBackingProperties); + } } - (void)applicationDidChangeEffectiveAppearance:(NSNotification *)notification { - processApplicationEvent(EventApplicationDidChangeEffectiveAppearance); + if( hasListeners(EventApplicationDidChangeEffectiveAppearance) ) { + processApplicationEvent(EventApplicationDidChangeEffectiveAppearance); + } } - (void)applicationDidChangeIcon:(NSNotification *)notification { - processApplicationEvent(EventApplicationDidChangeIcon); + if( hasListeners(EventApplicationDidChangeIcon) ) { + processApplicationEvent(EventApplicationDidChangeIcon); + } } - (void)applicationDidChangeOcclusionState:(NSNotification *)notification { - processApplicationEvent(EventApplicationDidChangeOcclusionState); + if( hasListeners(EventApplicationDidChangeOcclusionState) ) { + processApplicationEvent(EventApplicationDidChangeOcclusionState); + } } - (void)applicationDidChangeScreenParameters:(NSNotification *)notification { - processApplicationEvent(EventApplicationDidChangeScreenParameters); + if( hasListeners(EventApplicationDidChangeScreenParameters) ) { + processApplicationEvent(EventApplicationDidChangeScreenParameters); + } } - (void)applicationDidChangeStatusBarFrame:(NSNotification *)notification { - processApplicationEvent(EventApplicationDidChangeStatusBarFrame); + if( hasListeners(EventApplicationDidChangeStatusBarFrame) ) { + processApplicationEvent(EventApplicationDidChangeStatusBarFrame); + } } - (void)applicationDidChangeStatusBarOrientation:(NSNotification *)notification { - processApplicationEvent(EventApplicationDidChangeStatusBarOrientation); + if( hasListeners(EventApplicationDidChangeStatusBarOrientation) ) { + processApplicationEvent(EventApplicationDidChangeStatusBarOrientation); + } } - (void)applicationDidFinishLaunching:(NSNotification *)notification { - processApplicationEvent(EventApplicationDidFinishLaunching); + if( hasListeners(EventApplicationDidFinishLaunching) ) { + processApplicationEvent(EventApplicationDidFinishLaunching); + } } - (void)applicationDidHide:(NSNotification *)notification { - processApplicationEvent(EventApplicationDidHide); + if( hasListeners(EventApplicationDidHide) ) { + processApplicationEvent(EventApplicationDidHide); + } } - (void)applicationDidResignActive:(NSNotification *)notification { - processApplicationEvent(EventApplicationDidResignActive); + if( hasListeners(EventApplicationDidResignActive) ) { + processApplicationEvent(EventApplicationDidResignActive); + } } - (void)applicationDidUnhide:(NSNotification *)notification { - processApplicationEvent(EventApplicationDidUnhide); + if( hasListeners(EventApplicationDidUnhide) ) { + processApplicationEvent(EventApplicationDidUnhide); + } } - (void)applicationDidUpdate:(NSNotification *)notification { - processApplicationEvent(EventApplicationDidUpdate); + if( hasListeners(EventApplicationDidUpdate) ) { + processApplicationEvent(EventApplicationDidUpdate); + } } - (void)applicationWillBecomeActive:(NSNotification *)notification { - processApplicationEvent(EventApplicationWillBecomeActive); + if( hasListeners(EventApplicationWillBecomeActive) ) { + processApplicationEvent(EventApplicationWillBecomeActive); + } } - (void)applicationWillFinishLaunching:(NSNotification *)notification { - processApplicationEvent(EventApplicationWillFinishLaunching); + if( hasListeners(EventApplicationWillFinishLaunching) ) { + processApplicationEvent(EventApplicationWillFinishLaunching); + } } - (void)applicationWillHide:(NSNotification *)notification { - processApplicationEvent(EventApplicationWillHide); + if( hasListeners(EventApplicationWillHide) ) { + processApplicationEvent(EventApplicationWillHide); + } } - (void)applicationWillResignActive:(NSNotification *)notification { - processApplicationEvent(EventApplicationWillResignActive); + if( hasListeners(EventApplicationWillResignActive) ) { + processApplicationEvent(EventApplicationWillResignActive); + } } - (void)applicationWillTerminate:(NSNotification *)notification { - processApplicationEvent(EventApplicationWillTerminate); + if( hasListeners(EventApplicationWillTerminate) ) { + processApplicationEvent(EventApplicationWillTerminate); + } } - (void)applicationWillUnhide:(NSNotification *)notification { - processApplicationEvent(EventApplicationWillUnhide); + if( hasListeners(EventApplicationWillUnhide) ) { + processApplicationEvent(EventApplicationWillUnhide); + } } - (void)applicationWillUpdate:(NSNotification *)notification { - processApplicationEvent(EventApplicationWillUpdate); + if( hasListeners(EventApplicationWillUpdate) ) { + processApplicationEvent(EventApplicationWillUpdate); + } } // GENERATED EVENTS END diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index 039b6eba1..bc58fda06 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -48,6 +48,7 @@ type platformApp interface { getCurrentWindowID() uint showAboutDialog(name string, description string, icon []byte) setIcon(icon []byte) + on(id uint) } // Messages sent from javascript get routed here @@ -59,8 +60,9 @@ type windowMessage struct { var windowMessageBuffer = make(chan *windowMessage) type App struct { - options *options.Application - applicationEventListeners map[uint][]func() + options *options.Application + applicationEventListeners map[uint][]func() + applicationEventListenersLock sync.RWMutex // Windows windows map[uint]*Window @@ -102,7 +104,12 @@ func (a *App) getSystemTrayID() uint { } func (a *App) On(eventType events.ApplicationEventType, callback func()) { eventID := uint(eventType) + a.applicationEventListenersLock.Lock() + defer a.applicationEventListenersLock.Unlock() a.applicationEventListeners[eventID] = append(a.applicationEventListeners[eventID], callback) + if a.impl != nil { + a.impl.on(eventID) + } } func (a *App) NewWindow() *Window { return a.NewWindowWithOptions(nil) @@ -196,13 +203,17 @@ func (a *App) Run() error { a.impl.setApplicationMenu(a.ApplicationMenu) // set the application icon - a.impl.setIcon(a.icon) + if a.icon != nil { + a.impl.setIcon(a.icon) + } return a.impl.run() } func (a *App) handleApplicationEvent(event uint) { + a.applicationEventListenersLock.RLock() listeners, ok := a.applicationEventListeners[event] + a.applicationEventListenersLock.RUnlock() if !ok { return } diff --git a/exp/pkg/application/application_darwin.go b/exp/pkg/application/application_darwin.go index b92677b67..84b3c4433 100644 --- a/exp/pkg/application/application_darwin.go +++ b/exp/pkg/application/application_darwin.go @@ -12,6 +12,8 @@ package application #include "window_delegate.h" #include +extern void registerListener(unsigned int event); + #import static AppDelegate *appDelegate = nil; @@ -119,6 +121,10 @@ type macosApp struct { parent *App } +func (m *macosApp) on(eventID uint) { + C.registerListener(C.uint(eventID)) +} + func (m *macosApp) setIcon(icon []byte) { C.setApplicationIcon(unsafe.Pointer(&icon[0]), C.int(len(icon))) } @@ -146,12 +152,17 @@ func (m *macosApp) setApplicationMenu(menu *Menu) { } func (m *macosApp) run() error { + // Add a hook to the ApplicationDidFinishLaunching event m.parent.On(events.Mac.ApplicationDidFinishLaunching, func() { if m.parent.options != nil && m.parent.options.Mac != nil { C.setActivationPolicy(C.int(m.parent.options.Mac.ActivationPolicy)) } C.activateIgnoringOtherApps() }) + // setup event listeners + for eventID := range m.parent.applicationEventListeners { + m.on(eventID) + } C.run() return nil } diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index 0eb9f9871..a7ca3bfc7 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -8,42 +8,46 @@ import ( "github.com/wailsapp/wails/exp/pkg/options" ) -type windowImpl interface { - setTitle(title string) - setSize(width, height int) - setAlwaysOnTop(alwaysOnTop bool) - setURL(url string) - setResizable(resizable bool) - setMinSize(width, height int) - setMaxSize(width, height int) - execJS(js string) - setMaximised() - setMinimised() - setFullscreen() - isMinimised() bool - isMaximised() bool - isFullscreen() bool - restore() - setBackgroundColour(color *options.RGBA) - run() - center() - size() (int, int) - width() int - height() int - position() (int, int) - destroy() - reload() - forceReload() - toggleFullscreen() - toggleDevTools() - resetZoom() - zoomIn() - zoomOut() - close() - zoom() - minimize() - setHTML(html string) -} +type ( + windowImpl interface { + setTitle(title string) + setSize(width, height int) + setAlwaysOnTop(alwaysOnTop bool) + setURL(url string) + setResizable(resizable bool) + setMinSize(width, height int) + setMaxSize(width, height int) + execJS(js string) + setMaximised() + setMinimised() + setFullscreen() + isMinimised() bool + isMaximised() bool + isFullscreen() bool + restore() + setBackgroundColour(color *options.RGBA) + run() + center() + size() (int, int) + width() int + height() int + position() (int, int) + destroy() + reload() + forceReload() + toggleFullscreen() + toggleDevTools() + resetZoom() + zoomIn() + zoomOut() + close() + zoom() + minimize() + setHTML(html string) + setPosition(x int, y int) + on(eventID uint) + } +) type Window struct { options *options.Window @@ -260,8 +264,11 @@ func (w *Window) Center() { func (w *Window) On(eventType events.WindowEventType, callback func()) { eventID := uint(eventType) w.eventListenersLock.Lock() + defer w.eventListenersLock.Unlock() w.eventListeners[eventID] = append(w.eventListeners[eventID], callback) - w.eventListenersLock.Unlock() + if w.impl != nil { + w.impl.on(eventID) + } } func (w *Window) handleWindowEvent(id uint) { @@ -380,3 +387,12 @@ func (w *Window) SetHTML(html string) *Window { } return w } + +func (w *Window) SetPosition(x, y int) *Window { + w.options.X = x + w.options.Y = y + if w.impl != nil { + w.impl.setPosition(x, y) + } + return w +} diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index d4704b1cf..f638159e7 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -12,6 +12,7 @@ package application #include "Cocoa/Cocoa.h" #import +extern void registerListener(unsigned int event); // Create a new Window void* windowNew(unsigned int id, int width, int height) { @@ -252,6 +253,14 @@ void windowZoomOut(void* nsWindow) { }); } +// set the window position +void windowSetPosition(void* nsWindow, int x, int y) { + // Set window position on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + [(NSWindow*)nsWindow setFrameOrigin:NSMakePoint(x, y)]; + }); +} + // Execute JS in NSWindow void windowExecJS(void* nsWindow, const char* js) { printf("windowExecJS\n"); @@ -651,6 +660,10 @@ type macosWindow struct { parent *Window } +func (w *macosWindow) on(eventID uint) { + C.registerListener(C.uint(eventID)) +} + func (w *macosWindow) zoom() { C.windowZoom(w.nsWindow) } @@ -807,6 +820,10 @@ func (w *macosWindow) size() (int, int) { return int(width), int(height) } +func (w *macosWindow) setPosition(x, y int) { + C.windowSetPosition(w.nsWindow, C.int(x), C.int(y)) +} + func (w *macosWindow) width() int { var width C.int var wg sync.WaitGroup @@ -831,6 +848,9 @@ func (w *macosWindow) height() int { } func (w *macosWindow) run() { + for eventId := range w.parent.eventListeners { + w.on(eventId) + } DispatchOnMainThread(func() { w.nsWindow = C.windowNew(C.uint(w.parent.id), C.int(w.parent.options.Width), C.int(w.parent.options.Height)) w.setTitle(w.parent.options.Title) diff --git a/exp/pkg/application/window_delegate.m b/exp/pkg/application/window_delegate.m index 5f4ffb762..e9be47f51 100644 --- a/exp/pkg/application/window_delegate.m +++ b/exp/pkg/application/window_delegate.m @@ -1,16 +1,15 @@ //go:build darwin -// -// WindowDelegate.m -// test -// -// Created by Lea Anthony on 10/10/21. -// + #import #import #import "window_delegate.h" #import "../events/events.h" + extern void processMessage(unsigned int, const char*); +extern bool hasListeners(unsigned int); + @implementation WindowDelegate + - (BOOL)windowShouldClose:(NSWindow *)sender { if( self.hideOnClose ) { [NSApp hide:nil]; @@ -18,6 +17,7 @@ extern void processMessage(unsigned int, const char*); } return true; } + // Handle script messages from the external bridge - (void)userContentController:(nonnull WKUserContentController *)userContentController didReceiveScriptMessage:(nonnull WKScriptMessage *)message { NSString *m = message.body; @@ -36,12 +36,10 @@ extern void processMessage(unsigned int, const char*); const char *_m = [m UTF8String]; processMessage(self.windowId, _m); } - - (void)handleLeftMouseDown:(NSEvent *)event { self.leftMouseEvent = event; NSWindow *window = [event window]; WindowDelegate* delegate = (WindowDelegate*)[window delegate]; - if( self.invisibleTitleBarHeight > 0 ) { NSPoint location = [event locationInWindow]; NSRect frame = [window frame]; @@ -51,319 +49,470 @@ extern void processMessage(unsigned int, const char*); } } } - - (void)handleLeftMouseUp:(NSWindow *)window { self.leftMouseEvent = nil; } - - // GENERATED EVENTS START - (void)windowDidBecomeKey:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidBecomeKey); + if( hasListeners(EventWindowDidBecomeKey) ) { + processWindowEvent(self.windowId, EventWindowDidBecomeKey); + } } - (void)windowDidBecomeMain:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidBecomeMain); + if( hasListeners(EventWindowDidBecomeMain) ) { + processWindowEvent(self.windowId, EventWindowDidBecomeMain); + } } - (void)windowDidBeginSheet:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidBeginSheet); + if( hasListeners(EventWindowDidBeginSheet) ) { + processWindowEvent(self.windowId, EventWindowDidBeginSheet); + } } - (void)windowDidChangeAlpha:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidChangeAlpha); + if( hasListeners(EventWindowDidChangeAlpha) ) { + processWindowEvent(self.windowId, EventWindowDidChangeAlpha); + } } - (void)windowDidChangeBackingLocation:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidChangeBackingLocation); + if( hasListeners(EventWindowDidChangeBackingLocation) ) { + processWindowEvent(self.windowId, EventWindowDidChangeBackingLocation); + } } - (void)windowDidChangeBackingProperties:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidChangeBackingProperties); + if( hasListeners(EventWindowDidChangeBackingProperties) ) { + processWindowEvent(self.windowId, EventWindowDidChangeBackingProperties); + } } - (void)windowDidChangeCollectionBehavior:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidChangeCollectionBehavior); + if( hasListeners(EventWindowDidChangeCollectionBehavior) ) { + processWindowEvent(self.windowId, EventWindowDidChangeCollectionBehavior); + } } - (void)windowDidChangeEffectiveAppearance:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidChangeEffectiveAppearance); + if( hasListeners(EventWindowDidChangeEffectiveAppearance) ) { + processWindowEvent(self.windowId, EventWindowDidChangeEffectiveAppearance); + } } - (void)windowDidChangeOcclusionState:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidChangeOcclusionState); + if( hasListeners(EventWindowDidChangeOcclusionState) ) { + processWindowEvent(self.windowId, EventWindowDidChangeOcclusionState); + } } - (void)windowDidChangeOrderingMode:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidChangeOrderingMode); + if( hasListeners(EventWindowDidChangeOrderingMode) ) { + processWindowEvent(self.windowId, EventWindowDidChangeOrderingMode); + } } - (void)windowDidChangeScreen:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidChangeScreen); + if( hasListeners(EventWindowDidChangeScreen) ) { + processWindowEvent(self.windowId, EventWindowDidChangeScreen); + } } - (void)windowDidChangeScreenParameters:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidChangeScreenParameters); + if( hasListeners(EventWindowDidChangeScreenParameters) ) { + processWindowEvent(self.windowId, EventWindowDidChangeScreenParameters); + } } - (void)windowDidChangeScreenProfile:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidChangeScreenProfile); + if( hasListeners(EventWindowDidChangeScreenProfile) ) { + processWindowEvent(self.windowId, EventWindowDidChangeScreenProfile); + } } - (void)windowDidChangeScreenSpace:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidChangeScreenSpace); + if( hasListeners(EventWindowDidChangeScreenSpace) ) { + processWindowEvent(self.windowId, EventWindowDidChangeScreenSpace); + } } - (void)windowDidChangeScreenSpaceProperties:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidChangeScreenSpaceProperties); + if( hasListeners(EventWindowDidChangeScreenSpaceProperties) ) { + processWindowEvent(self.windowId, EventWindowDidChangeScreenSpaceProperties); + } } - (void)windowDidChangeSharingType:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidChangeSharingType); + if( hasListeners(EventWindowDidChangeSharingType) ) { + processWindowEvent(self.windowId, EventWindowDidChangeSharingType); + } } - (void)windowDidChangeSpace:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidChangeSpace); + if( hasListeners(EventWindowDidChangeSpace) ) { + processWindowEvent(self.windowId, EventWindowDidChangeSpace); + } } - (void)windowDidChangeSpaceOrderingMode:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidChangeSpaceOrderingMode); + if( hasListeners(EventWindowDidChangeSpaceOrderingMode) ) { + processWindowEvent(self.windowId, EventWindowDidChangeSpaceOrderingMode); + } } - (void)windowDidChangeTitle:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidChangeTitle); + if( hasListeners(EventWindowDidChangeTitle) ) { + processWindowEvent(self.windowId, EventWindowDidChangeTitle); + } } - (void)windowDidChangeToolbar:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidChangeToolbar); + if( hasListeners(EventWindowDidChangeToolbar) ) { + processWindowEvent(self.windowId, EventWindowDidChangeToolbar); + } } - (void)windowDidChangeVisibility:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidChangeVisibility); + if( hasListeners(EventWindowDidChangeVisibility) ) { + processWindowEvent(self.windowId, EventWindowDidChangeVisibility); + } } - (void)windowDidClose:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidClose); + if( hasListeners(EventWindowDidClose) ) { + processWindowEvent(self.windowId, EventWindowDidClose); + } } - (void)windowDidDeminiaturize:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidDeminiaturize); + if( hasListeners(EventWindowDidDeminiaturize) ) { + processWindowEvent(self.windowId, EventWindowDidDeminiaturize); + } } - (void)windowDidEndSheet:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidEndSheet); + if( hasListeners(EventWindowDidEndSheet) ) { + processWindowEvent(self.windowId, EventWindowDidEndSheet); + } } - (void)windowDidEnterFullScreen:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidEnterFullScreen); + if( hasListeners(EventWindowDidEnterFullScreen) ) { + processWindowEvent(self.windowId, EventWindowDidEnterFullScreen); + } } - (void)windowDidEnterVersionBrowser:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidEnterVersionBrowser); + if( hasListeners(EventWindowDidEnterVersionBrowser) ) { + processWindowEvent(self.windowId, EventWindowDidEnterVersionBrowser); + } } - (void)windowDidExitFullScreen:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidExitFullScreen); + if( hasListeners(EventWindowDidExitFullScreen) ) { + processWindowEvent(self.windowId, EventWindowDidExitFullScreen); + } } - (void)windowDidExitVersionBrowser:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidExitVersionBrowser); + if( hasListeners(EventWindowDidExitVersionBrowser) ) { + processWindowEvent(self.windowId, EventWindowDidExitVersionBrowser); + } } - (void)windowDidExpose:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidExpose); + if( hasListeners(EventWindowDidExpose) ) { + processWindowEvent(self.windowId, EventWindowDidExpose); + } } - (void)windowDidFocus:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidFocus); + if( hasListeners(EventWindowDidFocus) ) { + processWindowEvent(self.windowId, EventWindowDidFocus); + } } - (void)windowDidMiniaturize:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidMiniaturize); + if( hasListeners(EventWindowDidMiniaturize) ) { + processWindowEvent(self.windowId, EventWindowDidMiniaturize); + } } - (void)windowDidMove:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidMove); + if( hasListeners(EventWindowDidMove) ) { + processWindowEvent(self.windowId, EventWindowDidMove); + } } - (void)windowDidOrderOffScreen:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidOrderOffScreen); + if( hasListeners(EventWindowDidOrderOffScreen) ) { + processWindowEvent(self.windowId, EventWindowDidOrderOffScreen); + } } - (void)windowDidOrderOnScreen:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidOrderOnScreen); + if( hasListeners(EventWindowDidOrderOnScreen) ) { + processWindowEvent(self.windowId, EventWindowDidOrderOnScreen); + } } - (void)windowDidResignKey:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidResignKey); + if( hasListeners(EventWindowDidResignKey) ) { + processWindowEvent(self.windowId, EventWindowDidResignKey); + } } - (void)windowDidResignMain:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidResignMain); + if( hasListeners(EventWindowDidResignMain) ) { + processWindowEvent(self.windowId, EventWindowDidResignMain); + } } - (void)windowDidResize:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidResize); + if( hasListeners(EventWindowDidResize) ) { + processWindowEvent(self.windowId, EventWindowDidResize); + } } - (void)windowDidUnfocus:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidUnfocus); + if( hasListeners(EventWindowDidUnfocus) ) { + processWindowEvent(self.windowId, EventWindowDidUnfocus); + } } - (void)windowDidUpdate:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidUpdate); + if( hasListeners(EventWindowDidUpdate) ) { + processWindowEvent(self.windowId, EventWindowDidUpdate); + } } - (void)windowDidUpdateAlpha:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidUpdateAlpha); + if( hasListeners(EventWindowDidUpdateAlpha) ) { + processWindowEvent(self.windowId, EventWindowDidUpdateAlpha); + } } - (void)windowDidUpdateCollectionBehavior:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidUpdateCollectionBehavior); + if( hasListeners(EventWindowDidUpdateCollectionBehavior) ) { + processWindowEvent(self.windowId, EventWindowDidUpdateCollectionBehavior); + } } - (void)windowDidUpdateCollectionProperties:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidUpdateCollectionProperties); + if( hasListeners(EventWindowDidUpdateCollectionProperties) ) { + processWindowEvent(self.windowId, EventWindowDidUpdateCollectionProperties); + } } - (void)windowDidUpdateShadow:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidUpdateShadow); + if( hasListeners(EventWindowDidUpdateShadow) ) { + processWindowEvent(self.windowId, EventWindowDidUpdateShadow); + } } - (void)windowDidUpdateTitle:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidUpdateTitle); + if( hasListeners(EventWindowDidUpdateTitle) ) { + processWindowEvent(self.windowId, EventWindowDidUpdateTitle); + } } - (void)windowDidUpdateToolbar:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidUpdateToolbar); + if( hasListeners(EventWindowDidUpdateToolbar) ) { + processWindowEvent(self.windowId, EventWindowDidUpdateToolbar); + } } - (void)windowDidUpdateVisibility:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowDidUpdateVisibility); + if( hasListeners(EventWindowDidUpdateVisibility) ) { + processWindowEvent(self.windowId, EventWindowDidUpdateVisibility); + } } - (void)windowWillBecomeKey:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillBecomeKey); + if( hasListeners(EventWindowWillBecomeKey) ) { + processWindowEvent(self.windowId, EventWindowWillBecomeKey); + } } - (void)windowWillBecomeMain:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillBecomeMain); + if( hasListeners(EventWindowWillBecomeMain) ) { + processWindowEvent(self.windowId, EventWindowWillBecomeMain); + } } - (void)windowWillBeginSheet:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillBeginSheet); + if( hasListeners(EventWindowWillBeginSheet) ) { + processWindowEvent(self.windowId, EventWindowWillBeginSheet); + } } - (void)windowWillChangeOrderingMode:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillChangeOrderingMode); + if( hasListeners(EventWindowWillChangeOrderingMode) ) { + processWindowEvent(self.windowId, EventWindowWillChangeOrderingMode); + } } - (void)windowWillClose:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillClose); + if( hasListeners(EventWindowWillClose) ) { + processWindowEvent(self.windowId, EventWindowWillClose); + } } - (void)windowWillDeminiaturize:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillDeminiaturize); + if( hasListeners(EventWindowWillDeminiaturize) ) { + processWindowEvent(self.windowId, EventWindowWillDeminiaturize); + } } - (void)windowWillEnterFullScreen:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillEnterFullScreen); + if( hasListeners(EventWindowWillEnterFullScreen) ) { + processWindowEvent(self.windowId, EventWindowWillEnterFullScreen); + } } - (void)windowWillEnterVersionBrowser:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillEnterVersionBrowser); + if( hasListeners(EventWindowWillEnterVersionBrowser) ) { + processWindowEvent(self.windowId, EventWindowWillEnterVersionBrowser); + } } - (void)windowWillExitFullScreen:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillExitFullScreen); + if( hasListeners(EventWindowWillExitFullScreen) ) { + processWindowEvent(self.windowId, EventWindowWillExitFullScreen); + } } - (void)windowWillExitVersionBrowser:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillExitVersionBrowser); + if( hasListeners(EventWindowWillExitVersionBrowser) ) { + processWindowEvent(self.windowId, EventWindowWillExitVersionBrowser); + } } - (void)windowWillFocus:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillFocus); + if( hasListeners(EventWindowWillFocus) ) { + processWindowEvent(self.windowId, EventWindowWillFocus); + } } - (void)windowWillMiniaturize:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillMiniaturize); + if( hasListeners(EventWindowWillMiniaturize) ) { + processWindowEvent(self.windowId, EventWindowWillMiniaturize); + } } - (void)windowWillMove:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillMove); + if( hasListeners(EventWindowWillMove) ) { + processWindowEvent(self.windowId, EventWindowWillMove); + } } - (void)windowWillOrderOffScreen:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillOrderOffScreen); + if( hasListeners(EventWindowWillOrderOffScreen) ) { + processWindowEvent(self.windowId, EventWindowWillOrderOffScreen); + } } - (void)windowWillOrderOnScreen:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillOrderOnScreen); + if( hasListeners(EventWindowWillOrderOnScreen) ) { + processWindowEvent(self.windowId, EventWindowWillOrderOnScreen); + } } - (void)windowWillResignMain:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillResignMain); + if( hasListeners(EventWindowWillResignMain) ) { + processWindowEvent(self.windowId, EventWindowWillResignMain); + } } - (void)windowWillResize:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillResize); + if( hasListeners(EventWindowWillResize) ) { + processWindowEvent(self.windowId, EventWindowWillResize); + } } - (void)windowWillUnfocus:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillUnfocus); + if( hasListeners(EventWindowWillUnfocus) ) { + processWindowEvent(self.windowId, EventWindowWillUnfocus); + } } - (void)windowWillUpdate:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillUpdate); + if( hasListeners(EventWindowWillUpdate) ) { + processWindowEvent(self.windowId, EventWindowWillUpdate); + } } - (void)windowWillUpdateAlpha:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillUpdateAlpha); + if( hasListeners(EventWindowWillUpdateAlpha) ) { + processWindowEvent(self.windowId, EventWindowWillUpdateAlpha); + } } - (void)windowWillUpdateCollectionBehavior:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillUpdateCollectionBehavior); + if( hasListeners(EventWindowWillUpdateCollectionBehavior) ) { + processWindowEvent(self.windowId, EventWindowWillUpdateCollectionBehavior); + } } - (void)windowWillUpdateCollectionProperties:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillUpdateCollectionProperties); + if( hasListeners(EventWindowWillUpdateCollectionProperties) ) { + processWindowEvent(self.windowId, EventWindowWillUpdateCollectionProperties); + } } - (void)windowWillUpdateShadow:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillUpdateShadow); + if( hasListeners(EventWindowWillUpdateShadow) ) { + processWindowEvent(self.windowId, EventWindowWillUpdateShadow); + } } - (void)windowWillUpdateTitle:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillUpdateTitle); + if( hasListeners(EventWindowWillUpdateTitle) ) { + processWindowEvent(self.windowId, EventWindowWillUpdateTitle); + } } - (void)windowWillUpdateToolbar:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillUpdateToolbar); + if( hasListeners(EventWindowWillUpdateToolbar) ) { + processWindowEvent(self.windowId, EventWindowWillUpdateToolbar); + } } - (void)windowWillUpdateVisibility:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillUpdateVisibility); + if( hasListeners(EventWindowWillUpdateVisibility) ) { + processWindowEvent(self.windowId, EventWindowWillUpdateVisibility); + } } - (void)windowWillUseStandardFrame:(NSNotification *)notification { - processWindowEvent(self.windowId, EventWindowWillUseStandardFrame); + if( hasListeners(EventWindowWillUseStandardFrame) ) { + processWindowEvent(self.windowId, EventWindowWillUseStandardFrame); + } } - (void)webView:(WKWebView *)webview didStartProvisionalNavigation:(WKNavigation *)navigation { - processWindowEvent(self.windowId, EventWebViewDidStartProvisionalNavigation); + if( hasListeners(EventWebViewDidStartProvisionalNavigation) ) { + processWindowEvent(self.windowId, EventWebViewDidStartProvisionalNavigation); + } } - (void)webView:(WKWebView *)webview didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation { - processWindowEvent(self.windowId, EventWebViewDidReceiveServerRedirectForProvisionalNavigation); + if( hasListeners(EventWebViewDidReceiveServerRedirectForProvisionalNavigation) ) { + processWindowEvent(self.windowId, EventWebViewDidReceiveServerRedirectForProvisionalNavigation); + } } - (void)webView:(WKWebView *)webview didFinishNavigation:(WKNavigation *)navigation { - processWindowEvent(self.windowId, EventWebViewDidFinishNavigation); + if( hasListeners(EventWebViewDidFinishNavigation) ) { + processWindowEvent(self.windowId, EventWebViewDidFinishNavigation); + } } - (void)webView:(WKWebView *)webview didCommitNavigation:(WKNavigation *)navigation { - processWindowEvent(self.windowId, EventWebViewDidCommitNavigation); + if( hasListeners(EventWebViewDidCommitNavigation) ) { + processWindowEvent(self.windowId, EventWebViewDidCommitNavigation); + } } // GENERATED EVENTS END diff --git a/exp/pkg/events/events.h b/exp/pkg/events/events.h index 02de910be..2d1e56d6d 100644 --- a/exp/pkg/events/events.h +++ b/exp/pkg/events/events.h @@ -127,5 +127,7 @@ extern void processWindowEvent(unsigned int, unsigned int); #define EventWebViewDidFinishNavigation 118 #define EventWebViewDidCommitNavigation 119 +#define MAX_EVENTS 120 + #endif \ No newline at end of file diff --git a/exp/pkg/events/events_darwin.go b/exp/pkg/events/events_darwin.go new file mode 100644 index 000000000..12a7c3af4 --- /dev/null +++ b/exp/pkg/events/events_darwin.go @@ -0,0 +1,26 @@ +//go:build darwin + +package events + +/* +#cgo CFLAGS: -x objective-c +#cgo LDFLAGS: -framework Cocoa -mmacosx-version-min=10.13 + +#include "events.h" +#include +#include + +#include "events.h" + +bool hasListener[MAX_EVENTS] = {false}; + +void registerListener(unsigned int event) { + hasListener[event] = true; +} + +bool hasListeners(unsigned int event) { + return hasListener[event]; +} + +*/ +import "C" diff --git a/exp/pkg/options/window.go b/exp/pkg/options/window.go index b6ce5e280..2156919f3 100644 --- a/exp/pkg/options/window.go +++ b/exp/pkg/options/window.go @@ -34,6 +34,8 @@ type Window struct { HTML string JS string CSS string + X int + Y int } var WindowDefaults = &Window{ diff --git a/exp/tasks/events/generate.go b/exp/tasks/events/generate.go index c3810ecd9..b14af8b7c 100644 --- a/exp/tasks/events/generate.go +++ b/exp/tasks/events/generate.go @@ -49,8 +49,10 @@ func main() { applicationDelegateEvents := bytes.NewBufferString("") webviewDelegateEvents := bytes.NewBufferString("") + var id int + var line []byte // Loop over each line in the file - for id, line := range bytes.Split(eventNames, []byte{'\n'}) { + for id, line = range bytes.Split(eventNames, []byte{'\n'}) { // Skip empty lines if len(line) == 0 { @@ -91,7 +93,9 @@ func main() { // Check if this is a window event if strings.HasPrefix(event, "Window") { windowDelegateEvents.WriteString(`- (void)` + delegateEventFunction + `:(NSNotification *)notification { - processWindowEvent(self.windowId, Event` + eventTitle + `); + if( hasListeners(Event` + eventTitle + `) ) { + processWindowEvent(self.windowId, Event` + eventTitle + `); + } } `) @@ -101,104 +105,111 @@ func main() { webViewFunction := strings.TrimPrefix(event, "WebView") webViewFunction = string(bytes.ToLower([]byte{webViewFunction[0]})) + webViewFunction[1:] webviewDelegateEvents.WriteString(`- (void)webView:(WKWebView *)webview ` + webViewFunction + `:(WKNavigation *)navigation { - processWindowEvent(self.windowId, Event` + eventTitle + `); + if( hasListeners(Event` + eventTitle + `) ) { + processWindowEvent(self.windowId, Event` + eventTitle + `); + } } `) } if strings.HasPrefix(event, "Application") { applicationDelegateEvents.WriteString(`- (void)` + delegateEventFunction + `:(NSNotification *)notification { - processApplicationEvent(Event` + eventTitle + `); + if( hasListeners(Event` + eventTitle + `) ) { + processApplicationEvent(Event` + eventTitle + `); + } } `) } } + } - // Save the eventsGo template substituting the values and decls - templateToWrite := strings.ReplaceAll(eventsGo, "$$MACEVENTSDECL", macEventsDecl.String()) - templateToWrite = strings.ReplaceAll(templateToWrite, "$$MACEVENTSVALUES", macEventsValues.String()) - err = os.WriteFile("../../pkg/events/events.go", []byte(templateToWrite), 0644) - if err != nil { - panic(err) - } + cHeaderEvents.WriteString("\n#define MAX_EVENTS " + strconv.Itoa(id-1) + "\n") - // Save the eventsH template substituting the values and decls - templateToWrite = strings.ReplaceAll(eventsH, "$$CHEADEREVENTS", cHeaderEvents.String()) - err = os.WriteFile("../../pkg/events/events.h", []byte(templateToWrite), 0644) - if err != nil { - panic(err) - } + // Save the eventsGo template substituting the values and decls + templateToWrite := strings.ReplaceAll(eventsGo, "$$MACEVENTSDECL", macEventsDecl.String()) + templateToWrite = strings.ReplaceAll(templateToWrite, "$$MACEVENTSVALUES", macEventsValues.String()) + err = os.WriteFile("../../pkg/events/events.go", []byte(templateToWrite), 0644) + if err != nil { + panic(err) + } - // Load the window_delegate.m file - windowDelegate, err := os.ReadFile("../../pkg/application/window_delegate.m") - if err != nil { - panic(err) - } - // iterate over the lines until we reach a line that says "// GENERATED EVENTS START" - // then we insert the events - // then we iterate until we reach a line that says "// GENERATED EVENTS END" - // then we write the file - var buffer bytes.Buffer - var inGeneratedEvents bool - for _, line := range bytes.Split(windowDelegate, []byte{'\n'}) { - if bytes.Contains(line, []byte("// GENERATED EVENTS START")) { - inGeneratedEvents = true - buffer.WriteString("// GENERATED EVENTS START\n") - buffer.WriteString(windowDelegateEvents.String()) - buffer.WriteString(webviewDelegateEvents.String()) - continue - } - if bytes.Contains(line, []byte("// GENERATED EVENTS END")) { - inGeneratedEvents = false - buffer.WriteString("// GENERATED EVENTS END\n") - continue - } - if !inGeneratedEvents { - if len(line) > 0 { - buffer.Write(line) - buffer.WriteString("\n") - } - } - } - err = os.WriteFile("../../pkg/application/window_delegate.m", buffer.Bytes(), 0755) - if err != nil { - panic(err) - } + // Save the eventsH template substituting the values and decls + templateToWrite = strings.ReplaceAll(eventsH, "$$CHEADEREVENTS", cHeaderEvents.String()) + err = os.WriteFile("../../pkg/events/events.h", []byte(templateToWrite), 0644) + if err != nil { + panic(err) + } - // Load the app_delegate.m file - appDelegate, err := os.ReadFile("../../pkg/application/app_delegate.m") - if err != nil { - panic(err) + // Load the window_delegate.m file + windowDelegate, err := os.ReadFile("../../pkg/application/window_delegate.m") + if err != nil { + panic(err) + } + // iterate over the lines until we reach a line that says "// GENERATED EVENTS START" + // then we insert the events + // then we iterate until we reach a line that says "// GENERATED EVENTS END" + // then we write the file + var buffer bytes.Buffer + var inGeneratedEvents bool + for _, line := range bytes.Split(windowDelegate, []byte{'\n'}) { + if bytes.Contains(line, []byte("// GENERATED EVENTS START")) { + inGeneratedEvents = true + buffer.WriteString("// GENERATED EVENTS START\n") + buffer.WriteString(windowDelegateEvents.String()) + buffer.WriteString(webviewDelegateEvents.String()) + continue } - // iterate over the lines until we reach a line that says "// GENERATED EVENTS START" - // then we insert the events - // then we iterate until we reach a line that says "// GENERATED EVENTS END" - // then we write the file - buffer.Reset() - for _, line := range bytes.Split(appDelegate, []byte{'\n'}) { - if bytes.Contains(line, []byte("// GENERATED EVENTS START")) { - inGeneratedEvents = true - buffer.WriteString("// GENERATED EVENTS START\n") - buffer.WriteString(applicationDelegateEvents.String()) - continue - } - if bytes.Contains(line, []byte("// GENERATED EVENTS END")) { - inGeneratedEvents = false - buffer.WriteString("// GENERATED EVENTS END\n") - continue - } - if !inGeneratedEvents { - if len(line) > 0 { - buffer.Write(line) - buffer.WriteString("\n") - } - } + if bytes.Contains(line, []byte("// GENERATED EVENTS END")) { + inGeneratedEvents = false + buffer.WriteString("// GENERATED EVENTS END\n") + continue } - err = os.WriteFile("../../pkg/application/app_delegate.m", buffer.Bytes(), 0755) - if err != nil { - panic(err) + if !inGeneratedEvents { + if len(line) > 0 { + buffer.Write(line) + buffer.WriteString("\n") + } } } + err = os.WriteFile("../../pkg/application/window_delegate.m", buffer.Bytes(), 0755) + if err != nil { + panic(err) + } + + // Load the app_delegate.m file + appDelegate, err := os.ReadFile("../../pkg/application/app_delegate.m") + if err != nil { + panic(err) + } + // iterate over the lines until we reach a line that says "// GENERATED EVENTS START" + // then we insert the events + // then we iterate until we reach a line that says "// GENERATED EVENTS END" + // then we write the file + buffer.Reset() + for _, line := range bytes.Split(appDelegate, []byte{'\n'}) { + if bytes.Contains(line, []byte("// GENERATED EVENTS START")) { + inGeneratedEvents = true + buffer.WriteString("// GENERATED EVENTS START\n") + buffer.WriteString(applicationDelegateEvents.String()) + continue + } + if bytes.Contains(line, []byte("// GENERATED EVENTS END")) { + inGeneratedEvents = false + buffer.WriteString("// GENERATED EVENTS END\n") + continue + } + if !inGeneratedEvents { + if len(line) > 0 { + buffer.Write(line) + buffer.WriteString("\n") + } + } + } + err = os.WriteFile("../../pkg/application/app_delegate.m", buffer.Bytes(), 0755) + if err != nil { + panic(err) + } + } From f240f2100cfe2857ca409b6791aff2dae3757a52 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sat, 24 Dec 2022 15:35:04 +1100 Subject: [PATCH 50/85] Refactor mainthread dispatch --- exp/pkg/application/application.go | 10 ++++++++++ exp/pkg/application/dialogs_darwin.go | 2 +- exp/pkg/application/mainthread.go | 9 --------- exp/pkg/application/mainthread_darwin.go | 14 +++++++------- exp/pkg/application/systemtray_darwin.go | 6 +++--- exp/pkg/application/window_darwin.go | 12 ++++++------ 6 files changed, 27 insertions(+), 26 deletions(-) diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index bc58fda06..698306418 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -49,6 +49,7 @@ type platformApp interface { showAboutDialog(name string, description string, icon []byte) setIcon(icon []byte) on(id uint) + dispatchOnMainThread(id uint) } // Messages sent from javascript get routed here @@ -367,3 +368,12 @@ func (a *App) Clipboard() *Clipboard { } return a.clipboard } + +func (a *App) dispatchOnMainThread(fn func()) { + mainThreadFunctionStoreLock.Lock() + id := generateFunctionStoreID() + mainThreadFunctionStore[id] = fn + mainThreadFunctionStoreLock.Unlock() + // Call platform specific dispatch function + a.impl.dispatchOnMainThread(id) +} diff --git a/exp/pkg/application/dialogs_darwin.go b/exp/pkg/application/dialogs_darwin.go index 5cfa621a9..d59deab9f 100644 --- a/exp/pkg/application/dialogs_darwin.go +++ b/exp/pkg/application/dialogs_darwin.go @@ -314,7 +314,7 @@ type macosDialog struct { } func (m *macosDialog) show() { - DispatchOnMainThread(func() { + globalApplication.dispatchOnMainThread(func() { // Mac can only have 4 buttons on a dialog if len(m.dialog.buttons) > 4 { diff --git a/exp/pkg/application/mainthread.go b/exp/pkg/application/mainthread.go index 8c62a8672..f0ae2803b 100644 --- a/exp/pkg/application/mainthread.go +++ b/exp/pkg/application/mainthread.go @@ -19,12 +19,3 @@ func generateFunctionStoreID() uint { } } } - -func DispatchOnMainThread(fn func()) { - mainThreadFunctionStoreLock.Lock() - id := generateFunctionStoreID() - mainThreadFunctionStore[id] = fn - mainThreadFunctionStoreLock.Unlock() - // Call platform specific dispatch function - platformDispatch(id) -} diff --git a/exp/pkg/application/mainthread_darwin.go b/exp/pkg/application/mainthread_darwin.go index 5a026d1ca..5603ea0d0 100644 --- a/exp/pkg/application/mainthread_darwin.go +++ b/exp/pkg/application/mainthread_darwin.go @@ -8,23 +8,23 @@ package application #include "Cocoa/Cocoa.h" -extern void dispatchCallback(unsigned int); +extern void dispatchOnMainThreadCallback(unsigned int); -static void dispatch(unsigned int id) { +static void dispatchOnMainThread(unsigned int id) { dispatch_async(dispatch_get_main_queue(), ^{ - dispatchCallback(id); + dispatchOnMainThreadCallback(id); }); } */ import "C" -func platformDispatch(id uint) { - C.dispatch(C.uint(id)) +func (m *macosApp) dispatchOnMainThread(id uint) { + C.dispatchOnMainThread(C.uint(id)) } -//export dispatchCallback -func dispatchCallback(callbackID C.uint) { +//export dispatchOnMainThreadCallback +func dispatchOnMainThreadCallback(callbackID C.uint) { mainThreadFunctionStoreLock.RLock() id := uint(callbackID) fn := mainThreadFunctionStore[id] diff --git a/exp/pkg/application/systemtray_darwin.go b/exp/pkg/application/systemtray_darwin.go index d26690f9d..2baade1b2 100644 --- a/exp/pkg/application/systemtray_darwin.go +++ b/exp/pkg/application/systemtray_darwin.go @@ -100,7 +100,7 @@ func (s *macosSystemTray) setMenu(menu *Menu) { } func (s *macosSystemTray) run() { - DispatchOnMainThread(func() { + globalApplication.dispatchOnMainThread(func() { if s.nsStatusItem != nil { Fatal("System tray '%d' already running", s.id) } @@ -124,7 +124,7 @@ func (s *macosSystemTray) run() { func (s *macosSystemTray) setIcon(icon []byte) { s.icon = icon - DispatchOnMainThread(func() { + globalApplication.dispatchOnMainThread(func() { s.nsImage = unsafe.Pointer(C.imageFromBytes((*C.uchar)(&icon[0]), C.int(len(icon)))) C.systemTraySetIcon(s.nsStatusItem, s.nsImage, C.int(s.iconPosition), C.bool(s.isTemplateIcon)) }) @@ -133,7 +133,7 @@ func (s *macosSystemTray) setIcon(icon []byte) { func (s *macosSystemTray) setTemplateIcon(icon []byte) { s.icon = icon s.isTemplateIcon = true - DispatchOnMainThread(func() { + globalApplication.dispatchOnMainThread(func() { s.nsImage = unsafe.Pointer(C.imageFromBytes((*C.uchar)(&icon[0]), C.int(len(icon)))) C.systemTraySetIcon(s.nsStatusItem, s.nsImage, C.int(s.iconPosition), C.bool(s.isTemplateIcon)) }) diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index f638159e7..011846d0a 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -736,7 +736,7 @@ func (w *macosWindow) syncMainThreadReturningBool(fn func() bool) bool { var wg sync.WaitGroup wg.Add(1) var result bool - DispatchOnMainThread(func() { + globalApplication.dispatchOnMainThread(func() { result = fn() wg.Done() }) @@ -812,7 +812,7 @@ func (w *macosWindow) size() (int, int) { var width, height C.int var wg sync.WaitGroup wg.Add(1) - DispatchOnMainThread(func() { + globalApplication.dispatchOnMainThread(func() { C.windowGetSize(w.nsWindow, &width, &height) wg.Done() }) @@ -828,7 +828,7 @@ func (w *macosWindow) width() int { var width C.int var wg sync.WaitGroup wg.Add(1) - DispatchOnMainThread(func() { + globalApplication.dispatchOnMainThread(func() { width = C.windowGetWidth(w.nsWindow) wg.Done() }) @@ -839,7 +839,7 @@ func (w *macosWindow) height() int { var height C.int var wg sync.WaitGroup wg.Add(1) - DispatchOnMainThread(func() { + globalApplication.dispatchOnMainThread(func() { height = C.windowGetHeight(w.nsWindow) wg.Done() }) @@ -851,7 +851,7 @@ func (w *macosWindow) run() { for eventId := range w.parent.eventListeners { w.on(eventId) } - DispatchOnMainThread(func() { + globalApplication.dispatchOnMainThread(func() { w.nsWindow = C.windowNew(C.uint(w.parent.id), C.int(w.parent.options.Width), C.int(w.parent.options.Height)) w.setTitle(w.parent.options.Title) w.setAlwaysOnTop(w.parent.options.AlwaysOnTop) @@ -938,7 +938,7 @@ func (w *macosWindow) position() (int, int) { var x, y C.int var wg sync.WaitGroup wg.Add(1) - go DispatchOnMainThread(func() { + go globalApplication.dispatchOnMainThread(func() { C.windowGetPosition(w.nsWindow, &x, &y) wg.Done() }) From 6a0c101b08284b67c1263f56f0372a20f9a23b54 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sat, 24 Dec 2022 20:40:34 +1100 Subject: [PATCH 51/85] Fix dialog ID issue Use map instead of uint for dialog IDs --- exp/pkg/application/dialogs.go | 21 +++++++++++++--- exp/pkg/application/dialogs_darwin.go | 36 ++++++++++++++++----------- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/exp/pkg/application/dialogs.go b/exp/pkg/application/dialogs.go index 8cea0cdd9..bad3e6d66 100644 --- a/exp/pkg/application/dialogs.go +++ b/exp/pkg/application/dialogs.go @@ -8,17 +8,32 @@ import ( type DialogType int -// TODO: Make this a map and clear it when the dialog is closed -var dialogID uint +var dialogMapID = make(map[uint]struct{}) var dialogIDLock sync.RWMutex func getDialogID() uint { dialogIDLock.Lock() defer dialogIDLock.Unlock() - dialogID++ + var dialogID uint + for { + if _, ok := dialogMapID[dialogID]; !ok { + dialogMapID[dialogID] = struct{}{} + break + } + dialogID++ + if dialogID == 0 { + panic("no more dialog IDs") + } + } return dialogID } +func freeDialogID(id uint) { + dialogIDLock.Lock() + defer dialogIDLock.Unlock() + delete(dialogMapID, id) +} + var openFileResponses = make(map[uint]chan string) var saveFileResponses = make(map[uint]chan string) diff --git a/exp/pkg/application/dialogs_darwin.go b/exp/pkg/application/dialogs_darwin.go index d59deab9f..b2818750a 100644 --- a/exp/pkg/application/dialogs_darwin.go +++ b/exp/pkg/application/dialogs_darwin.go @@ -280,7 +280,6 @@ static void showSaveFileDialog(unsigned int dialogID, }); } - */ import "C" import ( @@ -397,7 +396,7 @@ func toCString(s string) *C.char { } func (m *macosOpenFileDialog) show() ([]string, error) { - openFileResponses[dialogID] = make(chan string) + openFileResponses[m.dialog.id] = make(chan string) nsWindow := unsafe.Pointer(nil) if m.dialog.window != nil { // get NSWindow from window @@ -446,23 +445,25 @@ func (m *macosOpenFileDialog) show() ([]string, error) { } //export openFileDialogCallback -func openFileDialogCallback(id C.uint, path *C.char) { - // Covert the path to a string - filePath := C.GoString(path) - // put response on channel - channel, ok := openFileResponses[uint(id)] +func openFileDialogCallback(cid C.uint, cpath *C.char) { + path := C.GoString(cpath) + id := uint(cid) + channel, ok := openFileResponses[id] if ok { - channel <- filePath + channel <- path } else { panic("No channel found for open file dialog") } } //export openFileDialogCallbackEnd -func openFileDialogCallbackEnd(id C.uint) { - channel, ok := openFileResponses[uint(id)] +func openFileDialogCallbackEnd(cid C.uint) { + id := uint(cid) + channel, ok := openFileResponses[id] if ok { close(channel) + delete(openFileResponses, id) + freeDialogID(id) } else { panic("No channel found for open file dialog") } @@ -479,7 +480,7 @@ func newSaveFileDialogImpl(d *SaveFileDialog) *macosSaveFileDialog { } func (m *macosSaveFileDialog) show() (string, error) { - saveFileResponses[dialogID] = make(chan string) + saveFileResponses[m.dialog.id] = make(chan string) nsWindow := unsafe.Pointer(nil) if m.dialog.window != nil { // get NSWindow from window @@ -501,13 +502,18 @@ func (m *macosSaveFileDialog) show() (string, error) { } //export saveFileDialogCallback -func saveFileDialogCallback(id C.uint, path *C.char) { +func saveFileDialogCallback(cid C.uint, cpath *C.char) { // Covert the path to a string - filePath := C.GoString(path) + path := C.GoString(cpath) + id := uint(cid) // put response on channel - channel, ok := saveFileResponses[uint(id)] + channel, ok := saveFileResponses[id] if ok { - channel <- filePath + channel <- path + close(channel) + delete(saveFileResponses, id) + freeDialogID(id) + } else { panic("No channel found for save file dialog") } From 7dbb8c137794fe9ee998bc106392192facade048 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Mon, 26 Dec 2022 20:21:51 +1100 Subject: [PATCH 52/85] Improve Minimise, Maximise Add Restore setAutoenablesItems:NO --- exp/examples/window/main.go | 91 +++++++++++++++------ exp/pkg/application/menu_darwin.go | 1 + exp/pkg/application/window.go | 63 ++++++++++----- exp/pkg/application/window_darwin.go | 113 +++++++++++++++++---------- 4 files changed, 180 insertions(+), 88 deletions(-) diff --git a/exp/examples/window/main.go b/exp/examples/window/main.go index 9f17be321..60ebc1ab5 100644 --- a/exp/examples/window/main.go +++ b/exp/examples/window/main.go @@ -3,12 +3,13 @@ package main import ( _ "embed" "log" + "math/rand" "strconv" + "time" "github.com/wailsapp/wails/exp/pkg/events" "github.com/wailsapp/wails/exp/pkg/application" - "github.com/wailsapp/wails/exp/pkg/options" ) func main() { @@ -27,40 +28,78 @@ func main() { // Let's make a "Demo" menu myMenu := menu.AddSubmenu("New") - myMenu.Add("New Blank Window").OnClick(func(ctx *application.Context) { - app.NewWindow().SetTitle("Window " + strconv.Itoa(windowCounter)).Run() - windowCounter++ - }) - myMenu.Add("New Window").OnClick(func(ctx *application.Context) { - app.NewWindow(). - SetTitle("Window " + strconv.Itoa(windowCounter)). - SetBackgroundColour(&options.RGBA{ - Red: 255, - Green: 0, - Blue: 0, - Alpha: 0, - }). - Run() - windowCounter++ - }) - myMenu.Add("New Webview").OnClick(func(ctx *application.Context) { - app.NewWindow(). - SetTitle("Webview " + strconv.Itoa(windowCounter)). - SetURL("https://wails.app"). - Run() - windowCounter++ - }) + + myMenu.Add("New Window"). + SetAccelerator("CmdOrCtrl+N"). + OnClick(func(ctx *application.Context) { + app.NewWindow(). + SetTitle("Window "+strconv.Itoa(windowCounter)). + SetPosition(rand.Intn(1000), rand.Intn(800)). + SetURL("https://wails.io"). + Run() + windowCounter++ + }) // Disabled menu item adjustMenu := menu.AddSubmenu("Adjust") adjustMenu.Add("Set Position (0,0)").OnClick(func(ctx *application.Context) { - app.CurrentWindow().SetPosition(0, 0) - windowCounter++ + w := app.CurrentWindow() + if w != nil { + w.SetPosition(0, 0) + } }) + adjustMenu.Add("Set Position (Random)").OnClick(func(ctx *application.Context) { + w := app.CurrentWindow() + if w != nil { + w.SetPosition(rand.Intn(1000), rand.Intn(800)) + } + }) + adjustMenu.Add("Set Size (800,600)").OnClick(func(ctx *application.Context) { + w := app.CurrentWindow() + if w != nil { + w.SetSize(800, 600) + } + }) + adjustMenu.Add("Set Size (Random)").OnClick(func(ctx *application.Context) { + w := app.CurrentWindow() + if w != nil { + w.SetSize(rand.Intn(800)+200, rand.Intn(600)+200) + } + }) + adjustMenu.Add("Center").OnClick(func(ctx *application.Context) { + w := app.CurrentWindow() + if w != nil { + w.Center() + } + }) + adjustMenu.Add("Minimise (for 2 secs)").OnClick(func(ctx *application.Context) { + w := app.CurrentWindow() + if w != nil { + w.Minimise() + time.Sleep(2 * time.Second) + w.Restore() + } + }) + adjustMenu.Add("Maximise").OnClick(func(ctx *application.Context) { + w := app.CurrentWindow() + if w != nil { + w.Maximise() + } + }) + adjustMenu.Add("Restore").OnClick(func(ctx *application.Context) { + w := app.CurrentWindow() + if w != nil { + w.Restore() + } + }) + + app.NewWindow() + app.SetMenu(menu) err := app.Run() if err != nil { log.Fatal(err) } + } diff --git a/exp/pkg/application/menu_darwin.go b/exp/pkg/application/menu_darwin.go index fccf85559..b14be232a 100644 --- a/exp/pkg/application/menu_darwin.go +++ b/exp/pkg/application/menu_darwin.go @@ -24,6 +24,7 @@ void* createNSMenu(char* label) { menu.title = [NSString stringWithUTF8String:label]; free(label); } + [menu setAutoenablesItems:NO]; return (void*)menu; } diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index a7ca3bfc7..4a8d613b5 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -18,8 +18,6 @@ type ( setMinSize(width, height int) setMaxSize(width, height int) execJS(js string) - setMaximised() - setMinimised() setFullscreen() isMinimised() bool isMaximised() bool @@ -46,6 +44,10 @@ type ( setHTML(html string) setPosition(x int, y int) on(eventID uint) + minimise() + maximise() + unminimise() + unmaximise() } ) @@ -179,26 +181,12 @@ func (w *Window) ExecJS(js string) { w.impl.execJS(js) } -func (w *Window) SetMaximized() *Window { - w.options.StartState = options.WindowStateMaximised - if w.impl != nil { - w.impl.setMaximised() - } - return w -} - -// Set Minimized -func (w *Window) SetMinimized() *Window { - w.options.StartState = options.WindowStateMinimised - if w.impl == nil { - w.impl.setMinimised() - } - return w -} - func (w *Window) SetFullscreen() *Window { - w.options.StartState = options.WindowStateFullscreen if w.impl == nil { + w.options.StartState = options.WindowStateFullscreen + return w + } + if !w.IsFullscreen() { w.impl.setFullscreen() } return w @@ -396,3 +384,38 @@ func (w *Window) SetPosition(x, y int) *Window { } return w } + +func (w *Window) Minimise() *Window { + if w.impl == nil { + w.options.StartState = options.WindowStateMinimised + return w + } + if !w.IsMinimised() { + w.impl.minimise() + } + return w +} + +func (w *Window) Maximise() *Window { + if w.impl == nil { + w.options.StartState = options.WindowStateMaximised + return w + } + if !w.IsMaximised() { + w.impl.maximise() + } + return w +} + +func (w *Window) Restore() { + if w.impl == nil { + return + } + if w.IsMinimised() { + w.impl.unminimise() + } else if w.IsMaximised() { + w.impl.unmaximise() + } else if w.IsFullscreen() { + w.impl.toggleFullscreen() + } +} diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index 011846d0a..c2e307dab 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -121,7 +121,7 @@ void windowSetSize(void* nsWindow, int width, int height) { NSRect frame = [(NSWindow*)nsWindow frame]; frame.size.width = width; frame.size.height = height; - [(NSWindow*)nsWindow setFrame:frame display:YES]; + [(NSWindow*)nsWindow setFrame:frame display:YES animate:YES]; }); } @@ -332,14 +332,6 @@ void windowSetBackgroundColour(void* nsWindow, int r, int g, int b, int alpha) { }); } -// Set Window maximised -void windowSetMaximised(void* nsWindow) { - // Set window maximized on main thread - dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)nsWindow zoom:nil]; - }); -} - // toggle fullscreen void windowToggleFullscreen(void* nsWindow) { // Toggle fullscreen on main thread @@ -356,18 +348,6 @@ void windowSetFullscreen(void* nsWindow) { }); } -// Set Window Minimised -void windowSetMinimised(void* nsWindow) { - // Set window minimised on main thread - dispatch_async(dispatch_get_main_queue(), ^{ - // Get screen that the window is on - NSScreen* screen = [(NSWindow*)nsWindow screen]; - NSRect screenRect = [screen frame]; - // Set window to top left corner - [(NSWindow*)nsWindow setFrame:NSMakeRect(0, screenRect.size.height, 0, 0) display:YES]; - }); -} - // restore window to normal size void windowRestore(void* nsWindow) { // Set window normal on main thread @@ -610,14 +590,6 @@ static void windowMiniaturize(void *window) { }); } -// zoom maximizes the window to the screen dimensions -static void windowMaximize(void *window) { - dispatch_async(dispatch_get_main_queue(), ^{ - // maximize window - [(NSWindow*)window zoom:nil]; - }); -} - // webviewRenderHTML renders the given HTML static void windowRenderHTML(void *window, const char *html) { dispatch_async(dispatch_get_main_queue(), ^{ @@ -642,6 +614,55 @@ static void windowInjectCSS(void *window, const char *css) { }); } +static void windowMinimise(void *window) { + dispatch_async(dispatch_get_main_queue(), ^{ + // minimize window + [(NSWindow*)window miniaturize:nil]; + }); +} + +// zoom maximizes the window to the screen dimensions +static void windowMaximise(void *window) { + dispatch_async(dispatch_get_main_queue(), ^{ + // maximize window + [(NSWindow*)window zoom:nil]; + }); +} + +static bool isFullScreen(void *window) { + // get main window + NSWindow* nsWindow = (NSWindow*)window; + long mask = [nsWindow styleMask]; + return (mask & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen; +} + +// windowSetFullScreen +static void windowSetFullScreen(void *window, bool fullscreen) { + if (isFullScreen(window)) { + return; + } + dispatch_async(dispatch_get_main_queue(), ^{ + NSWindow* nsWindow = (NSWindow*)window; + [nsWindow toggleFullScreen:nil]; + }); +} + +// windowUnminimise +static void windowUnminimise(void *window) { + dispatch_async(dispatch_get_main_queue(), ^{ + // unminimize window + [(NSWindow*)window deminiaturize:nil]; + }); +} + +// windowUnmaximise +static void windowUnmaximise(void *window) { + dispatch_async(dispatch_get_main_queue(), ^{ + // unmaximize window + [(NSWindow*)window zoom:nil]; + }); +} + */ import "C" import ( @@ -660,6 +681,22 @@ type macosWindow struct { parent *Window } +func (w *macosWindow) unminimise() { + C.windowUnminimise(w.nsWindow) +} + +func (w *macosWindow) unmaximise() { + C.windowUnmaximise(w.nsWindow) +} + +func (w *macosWindow) maximise() { + C.windowMaximise(w.nsWindow) +} + +func (w *macosWindow) minimise() { + C.windowMinimise(w.nsWindow) +} + func (w *macosWindow) on(eventID uint) { C.registerListener(C.uint(eventID)) } @@ -716,19 +753,19 @@ func (w *macosWindow) center() { func (w *macosWindow) isMinimised() bool { return w.syncMainThreadReturningBool(func() bool { - return C.windowIsMinimised(w.nsWindow) == C.bool(true) + return bool(C.windowIsMinimised(w.nsWindow)) }) } func (w *macosWindow) isMaximised() bool { return w.syncMainThreadReturningBool(func() bool { - return C.windowIsMaximised(w.nsWindow) == C.bool(true) + return bool(C.windowIsMaximised(w.nsWindow)) }) } func (w *macosWindow) isFullscreen() bool { return w.syncMainThreadReturningBool(func() bool { - return C.windowIsFullscreen(w.nsWindow) == C.bool(true) + return bool(C.windowIsFullscreen(w.nsWindow)) }) } @@ -749,14 +786,6 @@ func (w *macosWindow) restore() { C.windowRestore(w.nsWindow) } -func (w *macosWindow) setMaximised() { - C.windowSetMaximised(w.nsWindow) -} - -func (w *macosWindow) setMinimised() { - C.windowSetMinimised(w.nsWindow) -} - func (w *macosWindow) setFullscreen() { C.windowSetFullscreen(w.nsWindow) } @@ -898,9 +927,9 @@ func (w *macosWindow) run() { switch w.parent.options.StartState { case options.WindowStateMaximised: - w.setMaximised() + w.maximise() case options.WindowStateMinimised: - w.setMinimised() + w.minimise() case options.WindowStateFullscreen: w.setFullscreen() From 0c364b28135671ca4f25e4c1cd6845cb68cfac43 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Tue, 27 Dec 2022 09:23:54 +1100 Subject: [PATCH 53/85] Fix sizing of window/contentrect Fix set min/max size Ignore SetSize when in fullscreen Disable size constraints when going fullscreen --- exp/examples/window/main.go | 75 +++++++++++------ exp/pkg/application/window.go | 117 +++++++++++++++++++++------ exp/pkg/application/window_darwin.go | 104 ++++++++++++++---------- 3 files changed, 205 insertions(+), 91 deletions(-) diff --git a/exp/examples/window/main.go b/exp/examples/window/main.go index 60ebc1ab5..83fcff7ee 100644 --- a/exp/examples/window/main.go +++ b/exp/examples/window/main.go @@ -20,6 +20,14 @@ func main() { log.Println("ApplicationDidFinishLaunching") }) + currentWindow := func(fn func(window *application.Window)) { + if app.CurrentWindow() != nil { + fn(app.CurrentWindow()) + } else { + println("Current Window is nil") + } + } + // Create a custom menu menu := app.NewMenu() menu.AddRole(application.AppMenu) @@ -43,54 +51,73 @@ func main() { // Disabled menu item adjustMenu := menu.AddSubmenu("Adjust") adjustMenu.Add("Set Position (0,0)").OnClick(func(ctx *application.Context) { - w := app.CurrentWindow() - if w != nil { + currentWindow(func(w *application.Window) { w.SetPosition(0, 0) - } + }) }) adjustMenu.Add("Set Position (Random)").OnClick(func(ctx *application.Context) { - w := app.CurrentWindow() - if w != nil { + currentWindow(func(w *application.Window) { w.SetPosition(rand.Intn(1000), rand.Intn(800)) - } + }) }) adjustMenu.Add("Set Size (800,600)").OnClick(func(ctx *application.Context) { - w := app.CurrentWindow() - if w != nil { + currentWindow(func(w *application.Window) { w.SetSize(800, 600) - } + }) }) + adjustMenu.Add("Set Size (Random)").OnClick(func(ctx *application.Context) { - w := app.CurrentWindow() - if w != nil { + currentWindow(func(w *application.Window) { w.SetSize(rand.Intn(800)+200, rand.Intn(600)+200) - } + }) + }) + adjustMenu.Add("Set Min Size (200,200)").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.Window) { + w.SetMinSize(200, 200) + }) + }) + adjustMenu.Add("Set Max Size (600,600)").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.Window) { + w.SetMaxSize(600, 600) + }) + }) + adjustMenu.Add("Reset Min Size").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.Window) { + w.SetMinSize(0, 0) + }) + }) + + adjustMenu.Add("Reset Max Size").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.Window) { + w.SetMaxSize(0, 0) + }) }) adjustMenu.Add("Center").OnClick(func(ctx *application.Context) { - w := app.CurrentWindow() - if w != nil { + currentWindow(func(w *application.Window) { w.Center() - } + }) }) adjustMenu.Add("Minimise (for 2 secs)").OnClick(func(ctx *application.Context) { - w := app.CurrentWindow() - if w != nil { + currentWindow(func(w *application.Window) { w.Minimise() time.Sleep(2 * time.Second) w.Restore() - } + }) }) adjustMenu.Add("Maximise").OnClick(func(ctx *application.Context) { - w := app.CurrentWindow() - if w != nil { + currentWindow(func(w *application.Window) { w.Maximise() - } + }) + }) + adjustMenu.Add("Fullscreen").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.Window) { + w.Fullscreen() + }) }) adjustMenu.Add("Restore").OnClick(func(ctx *application.Context) { - w := app.CurrentWindow() - if w != nil { + currentWindow(func(w *application.Window) { w.Restore() - } + }) }) app.NewWindow() diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index 4a8d613b5..6a90dc2d8 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -18,10 +18,6 @@ type ( setMinSize(width, height int) setMaxSize(width, height int) execJS(js string) - setFullscreen() - isMinimised() bool - isMaximised() bool - isFullscreen() bool restore() setBackgroundColour(color *options.RGBA) run() @@ -45,9 +41,15 @@ type ( setPosition(x int, y int) on(eventID uint) minimise() - maximise() unminimise() + maximise() unmaximise() + fullscreen() + unfullscreen() + isMinimised() bool + isMaximised() bool + isFullscreen() bool + disableSizeConstraints() } ) @@ -96,6 +98,10 @@ func (w *Window) SetTitle(title string) *Window { } func (w *Window) SetSize(width, height int) *Window { + // Don't set size if fullscreen + if w.IsFullscreen() { + return w + } w.options.Width = width w.options.Height = height if w.impl != nil { @@ -144,31 +150,53 @@ func (w *Window) Resizable() bool { func (w *Window) SetMinSize(minWidth, minHeight int) *Window { w.options.MinWidth = minWidth - if w.options.Width < minWidth { - w.options.Width = minWidth - } w.options.MinHeight = minHeight - if w.options.Height < minHeight { - w.options.Height = minHeight + + currentWidth, currentHeight := w.Size() + newWidth, newHeight := currentWidth, currentHeight + + var newSize bool + if minHeight != 0 && currentHeight < minHeight { + newHeight = minHeight + w.options.Height = newHeight + newSize = true + } + if minWidth != 0 && currentWidth < minWidth { + newWidth = minWidth + w.options.Width = newWidth + newSize = true } if w.impl != nil { - w.impl.setSize(w.options.Width, w.options.Height) + if newSize { + w.impl.setSize(newWidth, newHeight) + } w.impl.setMinSize(minWidth, minHeight) } return w } func (w *Window) SetMaxSize(maxWidth, maxHeight int) *Window { - w.options.MinWidth = maxWidth - if w.options.Width > maxWidth { - w.options.Width = maxWidth - } - w.options.MinHeight = maxHeight - if w.options.Height > maxHeight { + w.options.MaxWidth = maxWidth + w.options.MaxHeight = maxHeight + + currentWidth, currentHeight := w.Size() + newWidth, newHeight := currentWidth, currentHeight + + var newSize bool + if maxHeight != 0 && currentHeight > maxHeight { + newHeight = maxHeight w.options.Height = maxHeight + newSize = true + } + if maxWidth != 0 && currentWidth > maxWidth { + newWidth = maxWidth + w.options.Width = maxWidth + newSize = true } if w.impl != nil { - w.impl.setSize(w.options.Width, w.options.Height) + if newSize { + w.impl.setSize(newWidth, newHeight) + } w.impl.setMaxSize(maxWidth, maxHeight) } return w @@ -181,13 +209,14 @@ func (w *Window) ExecJS(js string) { w.impl.execJS(js) } -func (w *Window) SetFullscreen() *Window { +func (w *Window) Fullscreen() *Window { if w.impl == nil { w.options.StartState = options.WindowStateFullscreen return w } if !w.IsFullscreen() { - w.impl.setFullscreen() + w.disableSizeConstraints() + w.impl.fullscreen() } return w } @@ -208,8 +237,8 @@ func (w *Window) IsMaximised() bool { return w.impl.isMaximised() } -// Size returns the current size of the window -func (w *Window) Size() (int, int) { +// Size returns the size of the window +func (w *Window) Size() (width int, height int) { if w.impl == nil { return 0, 0 } @@ -407,15 +436,53 @@ func (w *Window) Maximise() *Window { return w } +func (w *Window) UnMinimise() { + if w.impl == nil { + return + } + w.impl.unminimise() +} + +func (w *Window) UnMaximise() { + if w.impl == nil { + return + } + w.enableConstraints() + w.impl.unmaximise() +} + +func (w *Window) UnFullscreen() { + if w.impl == nil { + return + } + w.enableConstraints() + w.impl.unfullscreen() +} + func (w *Window) Restore() { if w.impl == nil { return } if w.IsMinimised() { - w.impl.unminimise() + w.UnMinimise() } else if w.IsMaximised() { - w.impl.unmaximise() + w.UnMaximise() } else if w.IsFullscreen() { - w.impl.toggleFullscreen() + w.UnFullscreen() } } + +func (w *Window) disableSizeConstraints() { + if w.impl == nil { + return + } + w.impl.disableSizeConstraints() +} + +func (w *Window) enableConstraints() { + if w.impl == nil { + return + } + w.SetMinSize(w.options.MinWidth, w.options.MinHeight) + w.SetMaxSize(w.options.MaxWidth, w.options.MaxHeight) +} diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index c2e307dab..b0bc30fa4 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -117,13 +117,11 @@ void windowSetTitle(void* nsWindow, char* title) { void windowSetSize(void* nsWindow, int width, int height) { // Set window size on main thread dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)nsWindow setContentSize:NSMakeSize(width, height)]; - NSRect frame = [(NSWindow*)nsWindow frame]; - frame.size.width = width; - frame.size.height = height; - [(NSWindow*)nsWindow setFrame:frame display:YES animate:YES]; + NSWindow* window = (NSWindow*)nsWindow; + NSSize contentSize = [window contentRectForFrameRect:NSMakeRect(0, 0, width, height)].size; + [window setContentSize:contentSize]; + [window setFrame:NSMakeRect(window.frame.origin.x, window.frame.origin.y, width, height) display:YES animate:YES]; }); - } // Show the NSWindow @@ -178,7 +176,11 @@ void windowSetResizable(void* nsWindow, bool resizable) { void windowSetMinSize(void* nsWindow, int width, int height) { // Set window min size on main thread dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)nsWindow setContentMinSize:NSMakeSize(width, height)]; + NSWindow* window = (NSWindow*)nsWindow; + NSSize contentSize = [window contentRectForFrameRect:NSMakeRect(0, 0, width, height)].size; + [window setContentMinSize:contentSize]; + NSSize size = { width, height }; + [window setMinSize:size]; }); } @@ -186,22 +188,13 @@ void windowSetMinSize(void* nsWindow, int width, int height) { void windowSetMaxSize(void* nsWindow, int width, int height) { // Set window max size on main thread dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)nsWindow setContentMaxSize:NSMakeSize(width, height)]; - }); -} - -// Reset NSWindow min and max size -void windowResetMinSize(void* nsWindow) { - // Reset window min size on main thread - dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)nsWindow setContentMinSize:NSMakeSize(0, 0)]; - }); -} - -void windowResetMaxSize(void* nsWindow) { - // Reset window max size on main thread - dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)nsWindow setContentMaxSize:NSMakeSize(0, 0)]; + NSSize size = { FLT_MAX, FLT_MAX }; + size.width = width > 0 ? width : FLT_MAX; + size.height = height > 0 ? height : FLT_MAX; + NSWindow* window = (NSWindow*)nsWindow; + NSSize contentSize = [window contentRectForFrameRect:NSMakeRect(0, 0, size.width, size.height)].size; + [window setContentMaxSize:contentSize]; + [window setMaxSize:size]; }); } @@ -332,6 +325,18 @@ void windowSetBackgroundColour(void* nsWindow, int r, int g, int b, int alpha) { }); } +bool windowIsMaximised(void* nsWindow) { + return [(NSWindow*)nsWindow isZoomed]; +} + +bool windowIsFullscreen(void* nsWindow) { + return [(NSWindow*)nsWindow styleMask] & NSWindowStyleMaskFullScreen; +} + +bool windowIsMinimised(void* nsWindow) { + return [(NSWindow*)nsWindow isMiniaturized]; +} + // toggle fullscreen void windowToggleFullscreen(void* nsWindow) { // Toggle fullscreen on main thread @@ -341,8 +346,17 @@ void windowToggleFullscreen(void* nsWindow) { } // Set Window fullscreen -void windowSetFullscreen(void* nsWindow) { - // Set window fullscreen on main thread +void windowFullscreen(void* nsWindow) { + if( windowIsFullscreen(nsWindow) ) { + return; + } + windowToggleFullscreen(nsWindow); +} + +void windowUnFullscreen(void* nsWindow) { + if( !windowIsFullscreen(nsWindow) ) { + return; + } dispatch_async(dispatch_get_main_queue(), ^{ [(NSWindow*)nsWindow toggleFullScreen:nil]; }); @@ -367,18 +381,6 @@ void windowRestore(void* nsWindow) { }); } -bool windowIsMaximised(void* nsWindow) { - return [(NSWindow*)nsWindow isZoomed]; -} - -bool windowIsFullscreen(void* nsWindow) { - return [(NSWindow*)nsWindow styleMask] & NSWindowStyleMaskFullScreen; -} - -bool windowIsMinimised(void* nsWindow) { - return [(NSWindow*)nsWindow isMiniaturized]; -} - // Set the titlebar style void windowSetTitleBarAppearsTransparent(void* nsWindow, bool transparent) { // Set window titlebar style on main thread @@ -663,6 +665,16 @@ static void windowUnmaximise(void *window) { }); } +static void windowDisableSizeConstraints(void *window) { + dispatch_async(dispatch_get_main_queue(), ^{ + // get main window + NSWindow* nsWindow = (NSWindow*)window; + // disable size constraints + [nsWindow setContentMinSize:CGSizeZero]; + [nsWindow setContentMaxSize:CGSizeZero]; + }); +} + */ import "C" import ( @@ -681,6 +693,18 @@ type macosWindow struct { parent *Window } +func (w *macosWindow) disableSizeConstraints() { + C.windowDisableSizeConstraints(w.nsWindow) +} + +func (w *macosWindow) unfullscreen() { + C.windowUnFullscreen(w.nsWindow) +} + +func (w *macosWindow) fullscreen() { + C.windowFullscreen(w.nsWindow) +} + func (w *macosWindow) unminimise() { C.windowUnminimise(w.nsWindow) } @@ -786,10 +810,6 @@ func (w *macosWindow) restore() { C.windowRestore(w.nsWindow) } -func (w *macosWindow) setFullscreen() { - C.windowSetFullscreen(w.nsWindow) -} - func (w *macosWindow) restoreWindow() { C.windowRestore(w.nsWindow) } @@ -931,7 +951,7 @@ func (w *macosWindow) run() { case options.WindowStateMinimised: w.minimise() case options.WindowStateFullscreen: - w.setFullscreen() + w.fullscreen() } C.windowCenter(w.nsWindow) From f800222781fd5716a62a906f224bcd51e0a35191 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Tue, 27 Dec 2022 09:38:00 +1100 Subject: [PATCH 54/85] Allow SetSize to adjust min/max constraints --- exp/pkg/application/window.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index 6a90dc2d8..5e77783de 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -104,6 +104,33 @@ func (w *Window) SetSize(width, height int) *Window { } w.options.Width = width w.options.Height = height + + var newMaxWidth = w.options.MaxWidth + var newMaxHeight = w.options.MaxHeight + if width > w.options.MaxWidth && w.options.MaxWidth != 0 { + newMaxWidth = width + } + if height > w.options.MaxHeight && w.options.MaxHeight != 0 { + newMaxHeight = height + } + + if newMaxWidth != 0 || newMaxHeight != 0 { + w.SetMaxSize(newMaxWidth, newMaxHeight) + } + + var newMinWidth = w.options.MinWidth + var newMinHeight = w.options.MinHeight + if width < w.options.MinWidth && w.options.MinWidth != 0 { + newMinWidth = width + } + if height < w.options.MinHeight && w.options.MinHeight != 0 { + newMinHeight = height + } + + if newMinWidth != 0 || newMinHeight != 0 { + w.SetMinSize(newMinWidth, newMinHeight) + } + if w.impl != nil { w.impl.setSize(width, height) } From 41779866c45d9109a4b95673cf50d4573c18a062 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Tue, 27 Dec 2022 13:42:57 +1100 Subject: [PATCH 55/85] Disable fullscreen button if there are size constraints --- exp/examples/window/main.go | 54 ++++++++++++++++------------ exp/pkg/application/window.go | 18 +++++++--- exp/pkg/application/window_darwin.go | 22 ++++++++++-- exp/pkg/options/window.go | 41 ++++++++++----------- 4 files changed, 85 insertions(+), 50 deletions(-) diff --git a/exp/examples/window/main.go b/exp/examples/window/main.go index 83fcff7ee..6b385be13 100644 --- a/exp/examples/window/main.go +++ b/exp/examples/window/main.go @@ -48,73 +48,81 @@ func main() { windowCounter++ }) - // Disabled menu item - adjustMenu := menu.AddSubmenu("Adjust") - adjustMenu.Add("Set Position (0,0)").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { - w.SetPosition(0, 0) - }) - }) - adjustMenu.Add("Set Position (Random)").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { - w.SetPosition(rand.Intn(1000), rand.Intn(800)) - }) - }) - adjustMenu.Add("Set Size (800,600)").OnClick(func(ctx *application.Context) { + sizeMenu := menu.AddSubmenu("Size") + sizeMenu.Add("Set Size (800,600)").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.Window) { w.SetSize(800, 600) }) }) - adjustMenu.Add("Set Size (Random)").OnClick(func(ctx *application.Context) { + sizeMenu.Add("Set Size (Random)").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.Window) { w.SetSize(rand.Intn(800)+200, rand.Intn(600)+200) }) }) - adjustMenu.Add("Set Min Size (200,200)").OnClick(func(ctx *application.Context) { + sizeMenu.Add("Set Min Size (200,200)").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.Window) { w.SetMinSize(200, 200) }) }) - adjustMenu.Add("Set Max Size (600,600)").OnClick(func(ctx *application.Context) { + sizeMenu.Add("Set Max Size (600,600)").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.Window) { + w.SetFullscreenButtonEnabled(false) w.SetMaxSize(600, 600) }) }) - adjustMenu.Add("Reset Min Size").OnClick(func(ctx *application.Context) { + sizeMenu.Add("Reset Min Size").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.Window) { w.SetMinSize(0, 0) }) }) - adjustMenu.Add("Reset Max Size").OnClick(func(ctx *application.Context) { + sizeMenu.Add("Reset Max Size").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.Window) { w.SetMaxSize(0, 0) + w.SetFullscreenButtonEnabled(true) }) }) - adjustMenu.Add("Center").OnClick(func(ctx *application.Context) { + positionMenu := menu.AddSubmenu("Position") + positionMenu.Add("Set Position (0,0)").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.Window) { + w.SetPosition(0, 0) + }) + }) + positionMenu.Add("Set Position (Random)").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.Window) { + w.SetPosition(rand.Intn(1000), rand.Intn(800)) + }) + }) + positionMenu.Add("Center").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.Window) { w.Center() }) }) - adjustMenu.Add("Minimise (for 2 secs)").OnClick(func(ctx *application.Context) { + stateMenu := menu.AddSubmenu("State") + stateMenu.Add("Minimise (for 2 secs)").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.Window) { w.Minimise() time.Sleep(2 * time.Second) w.Restore() }) }) - adjustMenu.Add("Maximise").OnClick(func(ctx *application.Context) { + stateMenu.Add("Maximise").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.Window) { w.Maximise() }) }) - adjustMenu.Add("Fullscreen").OnClick(func(ctx *application.Context) { + stateMenu.Add("Fullscreen").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.Window) { w.Fullscreen() }) }) - adjustMenu.Add("Restore").OnClick(func(ctx *application.Context) { + stateMenu.Add("UnFullscreen").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.Window) { + w.UnFullscreen() + }) + }) + stateMenu.Add("Restore").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.Window) { w.Restore() }) diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index 5e77783de..3c117416b 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -50,6 +50,7 @@ type ( isMaximised() bool isFullscreen() bool disableSizeConstraints() + setFullscreenButtonEnabled(enabled bool) } ) @@ -248,6 +249,14 @@ func (w *Window) Fullscreen() *Window { return w } +func (w *Window) SetFullscreenButtonEnabled(enabled bool) *Window { + w.options.FullscreenButtonEnabled = enabled + if w.impl != nil { + w.impl.setFullscreenButtonEnabled(enabled) + } + return w +} + // IsMinimised returns true if the window is minimised func (w *Window) IsMinimised() bool { if w.impl == nil { @@ -474,7 +483,7 @@ func (w *Window) UnMaximise() { if w.impl == nil { return } - w.enableConstraints() + w.enableSizeConstraints() w.impl.unmaximise() } @@ -482,7 +491,7 @@ func (w *Window) UnFullscreen() { if w.impl == nil { return } - w.enableConstraints() + w.enableSizeConstraints() w.impl.unfullscreen() } @@ -503,10 +512,11 @@ func (w *Window) disableSizeConstraints() { if w.impl == nil { return } - w.impl.disableSizeConstraints() + w.impl.setMinSize(0, 0) + w.impl.setMaxSize(0, 0) } -func (w *Window) enableConstraints() { +func (w *Window) enableSizeConstraints() { if w.impl == nil { return } diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index b0bc30fa4..f79647bff 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -11,6 +11,7 @@ package application #include #include "Cocoa/Cocoa.h" #import +#import extern void registerListener(unsigned int event); @@ -357,9 +358,7 @@ void windowUnFullscreen(void* nsWindow) { if( !windowIsFullscreen(nsWindow) ) { return; } - dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)nsWindow toggleFullScreen:nil]; - }); + windowToggleFullscreen(nsWindow); } // restore window to normal size @@ -381,6 +380,17 @@ void windowRestore(void* nsWindow) { }); } +// disable window fullscreen button +void setFullscreenButtonEnabled(void* nsWindow, bool enabled) { + // Disable fullscreen button on main thread + dispatch_async(dispatch_get_main_queue(), ^{ + // Get window + NSWindow* window = (NSWindow*)nsWindow; + NSButton *fullscreenButton = [window standardWindowButton:NSWindowZoomButton]; + fullscreenButton.enabled = enabled; + }); +} + // Set the titlebar style void windowSetTitleBarAppearsTransparent(void* nsWindow, bool transparent) { // Set window titlebar style on main thread @@ -645,6 +655,8 @@ static void windowSetFullScreen(void *window, bool fullscreen) { } dispatch_async(dispatch_get_main_queue(), ^{ NSWindow* nsWindow = (NSWindow*)window; + windowSetMaxSize(nsWindow, 0, 0); + windowSetMinSize(nsWindow, 0, 0); [nsWindow toggleFullScreen:nil]; }); } @@ -693,6 +705,10 @@ type macosWindow struct { parent *Window } +func (w *macosWindow) setFullscreenButtonEnabled(enabled bool) { + C.setFullscreenButtonEnabled(w.nsWindow, C.bool(enabled)) +} + func (w *macosWindow) disableSizeConstraints() { C.windowDisableSizeConstraints(w.nsWindow) } diff --git a/exp/pkg/options/window.go b/exp/pkg/options/window.go index 2156919f3..214bd092f 100644 --- a/exp/pkg/options/window.go +++ b/exp/pkg/options/window.go @@ -16,26 +16,27 @@ const ( type Window struct { // Alias is a human-readable name for the window. This can be used to reference the window in the frontend. - Alias string - Title string - Width, Height int - AlwaysOnTop bool - URL string - DisableResize bool - Frameless bool - MinWidth int - MinHeight int - MaxWidth int - MaxHeight int - StartState WindowState - Mac *MacWindow - BackgroundColour *RGBA - Assets Assets - HTML string - JS string - CSS string - X int - Y int + Alias string + Title string + Width, Height int + AlwaysOnTop bool + URL string + DisableResize bool + Frameless bool + MinWidth int + MinHeight int + MaxWidth int + MaxHeight int + StartState WindowState + Mac *MacWindow + BackgroundColour *RGBA + Assets Assets + HTML string + JS string + CSS string + X int + Y int + FullscreenButtonEnabled bool } var WindowDefaults = &Window{ From 5187641e25162a31fe4cd496af9520812bda95b8 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Tue, 27 Dec 2022 15:29:57 +1100 Subject: [PATCH 56/85] Remove C.toggleFullscreen --- exp/pkg/application/window.go | 8 ++++++-- exp/pkg/application/window_darwin.go | 21 ++++++--------------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index 3c117416b..6c4b2a29e 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -29,7 +29,6 @@ type ( destroy() reload() forceReload() - toggleFullscreen() toggleDevTools() resetZoom() zoomIn() @@ -380,7 +379,11 @@ func (w *Window) ToggleFullscreen() { if w.impl == nil { return } - w.impl.toggleFullscreen() + if w.IsFullscreen() { + w.UnFullscreen() + } else { + w.Fullscreen() + } } func (w *Window) ToggleDevTools() { @@ -467,6 +470,7 @@ func (w *Window) Maximise() *Window { return w } if !w.IsMaximised() { + w.disableSizeConstraints() w.impl.maximise() } return w diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index f79647bff..aa3da4243 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -338,27 +338,22 @@ bool windowIsMinimised(void* nsWindow) { return [(NSWindow*)nsWindow isMiniaturized]; } -// toggle fullscreen -void windowToggleFullscreen(void* nsWindow) { - // Toggle fullscreen on main thread - dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)nsWindow toggleFullScreen:nil]; - }); -} - // Set Window fullscreen void windowFullscreen(void* nsWindow) { if( windowIsFullscreen(nsWindow) ) { return; } - windowToggleFullscreen(nsWindow); -} + dispatch_async(dispatch_get_main_queue(), ^{ + [(NSWindow*)nsWindow toggleFullScreen:nil]; + });} void windowUnFullscreen(void* nsWindow) { if( !windowIsFullscreen(nsWindow) ) { return; } - windowToggleFullscreen(nsWindow); + dispatch_async(dispatch_get_main_queue(), ^{ + [(NSWindow*)nsWindow toggleFullScreen:nil]; + }); } // restore window to normal size @@ -773,10 +768,6 @@ func (w *macosWindow) toggleDevTools() { showDevTools(w.nsWindow) } -func (w *macosWindow) toggleFullscreen() { - C.windowToggleFullscreen(w.nsWindow) -} - func (w *macosWindow) reload() { //TODO: Implement println("reload called on Window", w.parent.id) From b6b6acf1d9582e0caa265cc5f2d192b85116e99b Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Tue, 27 Dec 2022 15:31:24 +1100 Subject: [PATCH 57/85] Remove debug printfs --- exp/pkg/application/menuitem_darwin.go | 1 - exp/pkg/application/window_darwin.go | 6 ------ 2 files changed, 7 deletions(-) diff --git a/exp/pkg/application/menuitem_darwin.go b/exp/pkg/application/menuitem_darwin.go index f26e374d5..9288aaa65 100644 --- a/exp/pkg/application/menuitem_darwin.go +++ b/exp/pkg/application/menuitem_darwin.go @@ -48,7 +48,6 @@ void setMenuItemLabel(void* nsMenuItem, char *label) { void setMenuItemDisabled(void* nsMenuItem, bool disabled) { dispatch_async(dispatch_get_main_queue(), ^{ MenuItem *menuItem = (MenuItem *)nsMenuItem; - printf("setMenuItemDisabled: %d\n", disabled); [menuItem setEnabled:!disabled]; // remove target if( disabled ) { diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index aa3da4243..8f2717a2d 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -257,15 +257,9 @@ void windowSetPosition(void* nsWindow, int x, int y) { // Execute JS in NSWindow void windowExecJS(void* nsWindow, const char* js) { -printf("windowExecJS\n"); // Execute JS on main thread dispatch_async(dispatch_get_main_queue(), ^{ -printf("windowExecJS 2\n"); - - // Get window delegate WindowDelegate* delegate = (WindowDelegate*)[(NSWindow*)nsWindow delegate]; - // Execute JS in webview - printf("windowExecJS: %s\n", js); [delegate.webView evaluateJavaScript:[NSString stringWithUTF8String:js] completionHandler:nil]; free((void*)js); }); From 92af7455ad8ea2de9129883f11f0c8b7f69fe413 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Tue, 27 Dec 2022 21:15:43 +1100 Subject: [PATCH 58/85] Support Show/Hide window Better demo window.Run() -> window.Show() --- exp/examples/window/main.go | 44 +++++++++++++++++++++++++++- exp/pkg/application/application.go | 4 +-- exp/pkg/application/window.go | 20 ++++++++++++- exp/pkg/application/window_darwin.go | 42 ++++++++++++++------------ exp/pkg/options/window.go | 1 + 5 files changed, 89 insertions(+), 22 deletions(-) diff --git a/exp/examples/window/main.go b/exp/examples/window/main.go index 6b385be13..b6cf12856 100644 --- a/exp/examples/window/main.go +++ b/exp/examples/window/main.go @@ -44,7 +44,7 @@ func main() { SetTitle("Window "+strconv.Itoa(windowCounter)). SetPosition(rand.Intn(1000), rand.Intn(800)). SetURL("https://wails.io"). - Run() + Show() windowCounter++ }) @@ -71,6 +71,13 @@ func main() { w.SetMaxSize(600, 600) }) }) + sizeMenu.Add("Get Current Window Size").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.Window) { + width, height := w.Size() + app.NewInfoDialog().SetTitle("Current Window Size").SetMessage("Width: " + strconv.Itoa(width) + " Height: " + strconv.Itoa(height)).Show() + }) + }) + sizeMenu.Add("Reset Min Size").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.Window) { w.SetMinSize(0, 0) @@ -94,6 +101,14 @@ func main() { w.SetPosition(rand.Intn(1000), rand.Intn(800)) }) }) + + positionMenu.Add("Get Position").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.Window) { + x, y := w.Position() + app.NewInfoDialog().SetTitle("Current Window Position").SetMessage("X: " + strconv.Itoa(x) + " Y: " + strconv.Itoa(y)).Show() + }) + }) + positionMenu.Add("Center").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.Window) { w.Center() @@ -127,6 +142,33 @@ func main() { w.Restore() }) }) + stateMenu.Add("Hide (for 2 seconds)").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.Window) { + w.Hide() + time.Sleep(2 * time.Second) + w.Show() + }) + }) + stateMenu.Add("Always on Top").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.Window) { + w.SetAlwaysOnTop(true) + }) + }) + stateMenu.Add("Not always on Top").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.Window) { + w.SetAlwaysOnTop(false) + }) + }) + stateMenu.Add("Google.com").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.Window) { + w.SetURL("https://google.com") + }) + }) + stateMenu.Add("wails.io").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.Window) { + w.SetURL("https://wails.io") + }) + }) app.NewWindow() diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index 698306418..b556580bb 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -140,7 +140,7 @@ func (a *App) NewWindowWithOptions(windowOptions *options.Window) *Window { a.windowAliasesLock.Unlock() } if a.running { - newWindow.Run() + newWindow.run() } return newWindow @@ -192,7 +192,7 @@ func (a *App) Run() error { // run windows for _, window := range a.windows { - go window.Run() + go window.run() } // run system trays diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index 6c4b2a29e..6198933d6 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -50,6 +50,8 @@ type ( isFullscreen() bool disableSizeConstraints() setFullscreenButtonEnabled(enabled bool) + show() + hide() } ) @@ -137,7 +139,7 @@ func (w *Window) SetSize(width, height int) *Window { return w } -func (w *Window) Run() { +func (w *Window) run() { if w.impl != nil { return } @@ -155,6 +157,22 @@ func (w *Window) SetAlwaysOnTop(b bool) *Window { return w } +func (w *Window) Show() *Window { + if w.impl == nil { + w.run() + return w + } + w.impl.show() + return w +} +func (w *Window) Hide() *Window { + w.options.Hidden = true + if w.impl != nil { + w.impl.hide() + } + return w +} + func (w *Window) SetURL(s string) *Window { w.options.URL = s if w.impl != nil { diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index 8f2717a2d..f29a05635 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -125,22 +125,6 @@ void windowSetSize(void* nsWindow, int width, int height) { }); } -// Show the NSWindow -void windowShow(void* nsWindow) { - // Show window on main thread - dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)nsWindow makeKeyAndOrderFront:nil]; - }); -} - -// Hide the NSWindow -void windowHide(void* nsWindow) { - // Hide window on main thread - dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)nsWindow orderOut:nil]; - }); -} - // Set NSWindow always on top void windowSetAlwaysOnTop(void* nsWindow, bool alwaysOnTop) { // Set window always on top on main thread @@ -676,6 +660,19 @@ static void windowDisableSizeConstraints(void *window) { }); } +static void windowShow(void *window) { + dispatch_async(dispatch_get_main_queue(), ^{ + // show window + [(NSWindow*)window makeKeyAndOrderFront:nil]; + }); +} + +static void windowHide(void *window) { + dispatch_async(dispatch_get_main_queue(), ^{ + [(NSWindow*)window orderOut:nil]; + }); +} + */ import "C" import ( @@ -694,6 +691,14 @@ type macosWindow struct { parent *Window } +func (w *macosWindow) show() { + C.windowShow(w.nsWindow) +} + +func (w *macosWindow) hide() { + C.windowHide(w.nsWindow) +} + func (w *macosWindow) setFullscreenButtonEnabled(enabled bool) { C.setFullscreenButtonEnabled(w.nsWindow, C.bool(enabled)) } @@ -972,8 +977,9 @@ func (w *macosWindow) run() { if w.parent.options.HTML != "" { w.setHTML(w.parent.options.HTML) } - - C.windowShow(w.nsWindow) + if w.parent.options.Hidden == false { + C.windowShow(w.nsWindow) + } }) } diff --git a/exp/pkg/options/window.go b/exp/pkg/options/window.go index 214bd092f..de4f15603 100644 --- a/exp/pkg/options/window.go +++ b/exp/pkg/options/window.go @@ -37,6 +37,7 @@ type Window struct { X int Y int FullscreenButtonEnabled bool + Hidden bool } var WindowDefaults = &Window{ From ad1d104d85daddffa334d4ba6e3b8abf77a577b3 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 28 Dec 2022 14:07:13 +1100 Subject: [PATCH 59/85] Add screen support Co-authored-by: Oleg Gulevskyy <43781031+oleggulevskyy@users.noreply.github.com> --- exp/examples/window/main.go | 33 +++++- exp/pkg/application/application.go | 8 ++ exp/pkg/application/screen.go | 26 +++++ exp/pkg/application/screen_darwin.go | 151 +++++++++++++++++++++++++++ exp/pkg/application/window.go | 8 ++ exp/pkg/application/window_darwin.go | 4 + 6 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 exp/pkg/application/screen.go create mode 100644 exp/pkg/application/screen_darwin.go diff --git a/exp/examples/window/main.go b/exp/examples/window/main.go index b6cf12856..6c704f7b7 100644 --- a/exp/examples/window/main.go +++ b/exp/examples/window/main.go @@ -2,6 +2,7 @@ package main import ( _ "embed" + "fmt" "log" "math/rand" "strconv" @@ -169,7 +170,37 @@ func main() { w.SetURL("https://wails.io") }) }) - + stateMenu.Add("Get Primary Screen").OnClick(func(ctx *application.Context) { + screen, err := app.GetPrimaryScreen() + if err != nil { + app.NewErrorDialog().SetTitle("Error").SetMessage(err.Error()).Show() + return + } + msg := fmt.Sprintf("Screen: %+v", screen) + app.NewInfoDialog().SetTitle("Primary Screen").SetMessage(msg).Show() + }) + stateMenu.Add("Get Screens").OnClick(func(ctx *application.Context) { + screens, err := app.GetScreens() + if err != nil { + app.NewErrorDialog().SetTitle("Error").SetMessage(err.Error()).Show() + return + } + for _, screen := range screens { + msg := fmt.Sprintf("Screen: %+v", screen) + app.NewInfoDialog().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show() + } + }) + stateMenu.Add("Get Screen for Window").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.Window) { + screen, err := w.GetScreen() + if err != nil { + app.NewErrorDialog().SetTitle("Error").SetMessage(err.Error()).Show() + return + } + msg := fmt.Sprintf("Screen: %+v", screen) + app.NewInfoDialog().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show() + }) + }) app.NewWindow() app.SetMenu(menu) diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index b556580bb..9ee8608b0 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -362,6 +362,14 @@ func (a *App) NewSaveFileDialog() *SaveFileDialog { return newSaveFileDialog() } +func (a *App) GetPrimaryScreen() (*Screen, error) { + return getPrimaryScreen() +} + +func (a *App) GetScreens() ([]*Screen, error) { + return getScreens() +} + func (a *App) Clipboard() *Clipboard { if a.clipboard == nil { a.clipboard = newClipboard() diff --git a/exp/pkg/application/screen.go b/exp/pkg/application/screen.go new file mode 100644 index 000000000..b3712c9df --- /dev/null +++ b/exp/pkg/application/screen.go @@ -0,0 +1,26 @@ +package application + +type Screen struct { + ID string // A unique identifier for the display + Name string // The name of the display + Scale float32 // The scale factor of the display + X int // The x-coordinate of the top-left corner of the rectangle + Y int // The y-coordinate of the top-left corner of the rectangle + Size Size // The size of the display + Bounds Rect // The bounds of the display + WorkArea Rect // The work area of the display + IsPrimary bool // Whether this is the primary display + Rotation float32 // The rotation of the display +} + +type Rect struct { + X int + Y int + Width int + Height int +} + +type Size struct { + Width int + Height int +} diff --git a/exp/pkg/application/screen_darwin.go b/exp/pkg/application/screen_darwin.go new file mode 100644 index 000000000..8ca6ca15b --- /dev/null +++ b/exp/pkg/application/screen_darwin.go @@ -0,0 +1,151 @@ +//go:build darwin + +package application + +/* +#cgo CFLAGS: -x objective-c +#cgo LDFLAGS: -framework Foundation -framework Cocoa -framework WebKit -framework AppKit +#import +#import +#import +#import +#include + +typedef struct Screen { + const char* id; + const char* name; + int p_width; + int p_height; + int width; + int height; + int x; + int y; + int w_width; + int w_height; + int w_x; + int w_y; + float scale; + double rotation; + bool isPrimary; +} Screen; + + +int GetNumScreens(){ + return [[NSScreen screens] count]; +} + +Screen processScreen(NSScreen* screen){ + Screen returnScreen; + returnScreen.scale = screen.backingScaleFactor; + + // screen bounds + returnScreen.height = screen.frame.size.height; + returnScreen.width = screen.frame.size.width; + returnScreen.x = screen.frame.origin.x; + returnScreen.y = screen.frame.origin.y; + + // work area + NSRect workArea = [screen visibleFrame]; + returnScreen.w_height = workArea.size.height; + returnScreen.w_width = workArea.size.width; + returnScreen.w_x = workArea.origin.x; + returnScreen.w_y = workArea.origin.y; + + + // adapted from https://stackoverflow.com/a/1237490/4188138 + NSDictionary* screenDictionary = [screen deviceDescription]; + NSNumber* screenID = [screenDictionary objectForKey:@"NSScreenNumber"]; + CGDirectDisplayID displayID = [screenID unsignedIntValue]; + returnScreen.id = [[NSString stringWithFormat:@"%d", displayID] UTF8String]; + + // Get physical monitor size + NSValue *sizeValue = [screenDictionary objectForKey:@"NSDeviceSize"]; + NSSize physicalSize = sizeValue.sizeValue; + returnScreen.p_height = physicalSize.height; + returnScreen.p_width = physicalSize.width; + + // Get the rotation + double rotation = CGDisplayRotation(displayID); + returnScreen.rotation = rotation; + + if( @available(macOS 10.15, *) ){ + returnScreen.name = [screen.localizedName UTF8String]; + } + + return returnScreen; +} + +// Get primary screen +Screen GetPrimaryScreen(){ + // Get primary screen + NSScreen *mainScreen = [NSScreen mainScreen]; + return processScreen(mainScreen); +} + +Screen* getAllScreens() { + NSArray *screens = [NSScreen screens]; + Screen* returnScreens = malloc(sizeof(Screen) * screens.count); + for (int i = 0; i < screens.count; i++) { + NSScreen* screen = [screens objectAtIndex:i]; + returnScreens[i] = processScreen(screen); + } + return returnScreens; +} + +Screen getScreenForWindow(void* window){ + NSScreen* screen = ((NSWindow*)window).screen; + return processScreen(screen); +} + +*/ +import "C" +import "unsafe" + +func cScreenToScreen(screen C.Screen) *Screen { + + return &Screen{ + Size: Size{ + Width: int(screen.p_width), + Height: int(screen.p_height), + }, + Bounds: Rect{ + X: int(screen.x), + Y: int(screen.y), + Height: int(screen.height), + Width: int(screen.width), + }, + WorkArea: Rect{ + X: int(screen.w_x), + Y: int(screen.w_y), + Height: int(screen.w_height), + Width: int(screen.w_width), + }, + Scale: float32(screen.scale), + ID: C.GoString(screen.id), + Name: C.GoString(screen.name), + IsPrimary: bool(screen.isPrimary), + Rotation: float32(screen.rotation), + } +} + +func getPrimaryScreen() (*Screen, error) { + cScreen := C.GetPrimaryScreen() + return cScreenToScreen(cScreen), nil +} + +func getScreens() ([]*Screen, error) { + cScreens := C.getAllScreens() + defer C.free(unsafe.Pointer(cScreens)) + numScreens := int(C.GetNumScreens()) + displays := make([]*Screen, numScreens) + cScreenHeaders := (*[1 << 30]C.Screen)(unsafe.Pointer(cScreens))[:numScreens:numScreens] + for i := 0; i < numScreens; i++ { + displays[i] = cScreenToScreen(cScreenHeaders[i]) + } + return displays, nil +} + +func getScreenForWindow(window *macosWindow) (*Screen, error) { + cScreen := C.getScreenForWindow(window.nsWindow) + return cScreenToScreen(cScreen), nil +} diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index 6198933d6..d765179c1 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -52,6 +52,7 @@ type ( setFullscreenButtonEnabled(enabled bool) show() hide() + getScreen() (*Screen, error) } ) @@ -545,3 +546,10 @@ func (w *Window) enableSizeConstraints() { w.SetMinSize(w.options.MinWidth, w.options.MinHeight) w.SetMaxSize(w.options.MaxWidth, w.options.MaxHeight) } + +func (w *Window) GetScreen() (*Screen, error) { + if w.impl == nil { + return nil, nil + } + return w.impl.getScreen() +} diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index f29a05635..e3cddf6c0 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -691,6 +691,10 @@ type macosWindow struct { parent *Window } +func (w *macosWindow) getScreen() (*Screen, error) { + return getScreenForWindow(w) +} + func (w *macosWindow) show() { C.windowShow(w.nsWindow) } From 287039a8f396f43c5711f0fac7b318ac96dc6d40 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 28 Dec 2022 19:17:38 +1100 Subject: [PATCH 60/85] Task experiment --- exp/cmd/wails/main.go | 2 ++ exp/go.mod | 23 ++++++++++++- exp/go.sum | 53 +++++++++++++++++++++++++++++ exp/internal/commands/build.go | 18 +++++++++- exp/internal/commands/build_test.go | 30 ++++++++++++++++ exp/internal/commands/icon.go | 18 ++++++++++ 6 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 exp/internal/commands/build_test.go create mode 100644 exp/internal/commands/icon.go diff --git a/exp/cmd/wails/main.go b/exp/cmd/wails/main.go index f531802d4..453f62255 100644 --- a/exp/cmd/wails/main.go +++ b/exp/cmd/wails/main.go @@ -12,6 +12,8 @@ func main() { app := clir.NewCli("wails", "The Wails CLI", "v3") app.NewSubCommandFunction("init", "Initialise a new project", commands.Init) app.NewSubCommandFunction("build", "Build the project", commands.Build) + tool := app.NewSubCommand("tool", "Various build tools") + tool.NewSubCommandFunction("icon", "Generate icons", commands.Icon) err := app.Run() if err != nil { diff --git a/exp/go.mod b/exp/go.mod index 1969eb348..caef91ba5 100644 --- a/exp/go.mod +++ b/exp/go.mod @@ -2,4 +2,25 @@ module github.com/wailsapp/wails/exp go 1.19 -require github.com/leaanthony/clir v1.3.0 +require ( + github.com/go-task/task/v3 v3.19.0 + github.com/leaanthony/clir v1.3.0 +) + +require ( + github.com/fatih/color v1.13.0 // indirect + github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect + github.com/joho/godotenv v1.4.0 // indirect + github.com/mattn/go-colorable v0.1.9 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mattn/go-zglob v0.0.4 // indirect + github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect + github.com/radovskyb/watcher v1.0.7 // indirect + github.com/sajari/fuzzy v1.0.0 // indirect + golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9 // indirect + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect + golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + mvdan.cc/sh/v3 v3.6.0-0.dev.0.20220704111049-a6e3029cd899 // indirect +) diff --git a/exp/go.sum b/exp/go.sum index ec90627a4..309dfc7f6 100644 --- a/exp/go.sum +++ b/exp/go.sum @@ -1,2 +1,55 @@ +github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-task/task/v3 v3.19.0 h1:jS1s2fHoSgYySw+kHEtbSxS6emE620unBsDDcNqdRbc= +github.com/go-task/task/v3 v3.19.0/go.mod h1:AjwL1xWWs8EwSZ0enL496mwqSTeIgXbPOXi+5of3MR4= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= +github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/leaanthony/clir v1.3.0 h1:L9nPDWrmc/qU9UWZZvRaFajWYuO0np9V5p+5gxyYno0= github.com/leaanthony/clir v1.3.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= +github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-zglob v0.0.4 h1:LQi2iOm0/fGgu80AioIJ/1j9w9Oh+9DZ39J4VAGzHQM= +github.com/mattn/go-zglob v0.0.4/go.mod h1:MxxjyoXXnMxfIpxTK2GAkw1w8glPsQILx3N5wrKakiY= +github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= +github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/radovskyb/watcher v1.0.7 h1:AYePLih6dpmS32vlHfhCeli8127LzkIgwJGcwwe8tUE= +github.com/radovskyb/watcher v1.0.7/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm+ZuvsUYIg= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/sajari/fuzzy v1.0.0 h1:+FmwVvJErsd0d0hAPlj4CxqxUtQY/fOoY0DwX4ykpRY= +github.com/sajari/fuzzy v1.0.0/go.mod h1:OjYR6KxoWOe9+dOlXeiCJd4dIbED4Oo8wpS89o0pwOo= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9 h1:RjggHMcaTVp0LOVZcW0bo8alwHrOaCrGUDgfWUHhnN4= +golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +mvdan.cc/sh/v3 v3.6.0-0.dev.0.20220704111049-a6e3029cd899 h1:nwm4t5PtLlFd/H342GP50CtYf7vyMCOZkPx3g9shO0c= +mvdan.cc/sh/v3 v3.6.0-0.dev.0.20220704111049-a6e3029cd899/go.mod h1:1JcoyAKm1lZw/2bZje/iYKWicU/KMd0rsyJeKHnsK4E= diff --git a/exp/internal/commands/build.go b/exp/internal/commands/build.go index 66fde3150..ef610ec27 100644 --- a/exp/internal/commands/build.go +++ b/exp/internal/commands/build.go @@ -1,8 +1,24 @@ package commands +import ( + "context" + + "github.com/go-task/task/v3" + "github.com/go-task/task/v3/taskfile" +) + type BuildOptions struct { } func Build(options *BuildOptions) error { - return nil + e := task.Executor{} + err := e.Setup() + if err != nil { + return err + } + build := taskfile.Call{ + Task: "build", + Vars: nil, + } + return e.Run(context.Background(), build) } diff --git a/exp/internal/commands/build_test.go b/exp/internal/commands/build_test.go new file mode 100644 index 000000000..669d99ae3 --- /dev/null +++ b/exp/internal/commands/build_test.go @@ -0,0 +1,30 @@ +package commands + +import "testing" + +func TestBuild(t *testing.T) { + type args struct { + options *BuildOptions + } + tests := []struct { + name string + args args + wantErr bool + }{ + // TODO: Add test cases. + { + name: "TestBuild", + args: args{ + options: &BuildOptions{}, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := Build(tt.args.options); (err != nil) != tt.wantErr { + t.Errorf("Build() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/exp/internal/commands/icon.go b/exp/internal/commands/icon.go new file mode 100644 index 000000000..b77027f73 --- /dev/null +++ b/exp/internal/commands/icon.go @@ -0,0 +1,18 @@ +package commands + +import "fmt" + +type IconOptions struct { + Input string + + WindowsFilename string + MacFilename string +} + +func Icon(options *IconOptions) error { + if options.Input == "" { + return fmt.Errorf("input is required") + } + + return nil +} From ad802a3ad071c8668914078cbd0e8727d84f9b95 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Fri, 30 Dec 2022 14:14:28 +1100 Subject: [PATCH 61/85] Frameless support applicationShouldTerminateAfterLastWindowClosed support --- exp/examples/window/main.go | 59 ++++++++++++++ exp/pkg/application/app_delegate.h | 1 + exp/pkg/application/app_delegate.m | 6 ++ exp/pkg/application/application.go | 15 ++-- exp/pkg/application/application_darwin.go | 18 ++--- exp/pkg/application/window.go | 9 +++ exp/pkg/application/window_darwin.go | 95 +++++++++++++---------- exp/pkg/options/application.go | 6 +- exp/pkg/options/mac.go | 13 ++-- exp/pkg/options/window.go | 2 +- 10 files changed, 157 insertions(+), 67 deletions(-) diff --git a/exp/examples/window/main.go b/exp/examples/window/main.go index 6c704f7b7..38bc80b94 100644 --- a/exp/examples/window/main.go +++ b/exp/examples/window/main.go @@ -5,9 +5,12 @@ import ( "fmt" "log" "math/rand" + "runtime" "strconv" "time" + "github.com/wailsapp/wails/exp/pkg/options" + "github.com/wailsapp/wails/exp/pkg/events" "github.com/wailsapp/wails/exp/pkg/application" @@ -16,6 +19,7 @@ import ( func main() { app := application.New() app.SetName("Window Demo") + app.ApplicationShouldTerminateAfterLastWindowClosed() app.SetDescription("A demo of the windowing capabilities") app.On(events.Mac.ApplicationDidFinishLaunching, func() { log.Println("ApplicationDidFinishLaunching") @@ -48,6 +52,61 @@ func main() { Show() windowCounter++ }) + myMenu.Add("New Frameless Window"). + SetAccelerator("CmdOrCtrl+F"). + OnClick(func(ctx *application.Context) { + app.NewWindow(). + SetTitle("Window "+strconv.Itoa(windowCounter)). + SetPosition(rand.Intn(1000), rand.Intn(800)). + SetURL("https://wails.io"). + SetFrameless(true). + Show() + windowCounter++ + }) + if runtime.GOOS == "darwin" { + myMenu.Add("New Window (TitleBarHiddenInset)"). + OnClick(func(ctx *application.Context) { + app.NewWindowWithOptions(&options.Window{ + Mac: options.MacWindow{ + TitleBar: options.TitleBarHiddenInset, + InvisibleTitleBarHeight: 25, + }, + }). + SetTitle("Window "+strconv.Itoa(windowCounter)). + SetPosition(rand.Intn(1000), rand.Intn(800)). + SetHTML("

A TitleBarHiddenInset Window example

"). + Show() + windowCounter++ + }) + myMenu.Add("New Window (TitleBarHiddenInsetUnified)"). + OnClick(func(ctx *application.Context) { + app.NewWindowWithOptions(&options.Window{ + Mac: options.MacWindow{ + TitleBar: options.TitleBarHiddenInsetUnified, + InvisibleTitleBarHeight: 50, + }, + }). + SetTitle("Window "+strconv.Itoa(windowCounter)). + SetPosition(rand.Intn(1000), rand.Intn(800)). + SetHTML("

A TitleBarHiddenInsetUnified Window example

"). + Show() + windowCounter++ + }) + myMenu.Add("New Window (TitleBarHidden)"). + OnClick(func(ctx *application.Context) { + app.NewWindowWithOptions(&options.Window{ + Mac: options.MacWindow{ + TitleBar: options.TitleBarHidden, + InvisibleTitleBarHeight: 25, + }, + }). + SetTitle("Window "+strconv.Itoa(windowCounter)). + SetPosition(rand.Intn(1000), rand.Intn(800)). + SetHTML("

A TitleBarHidden Window example

"). + Show() + windowCounter++ + }) + } sizeMenu := menu.AddSubmenu("Size") sizeMenu.Add("Set Size (800,600)").OnClick(func(ctx *application.Context) { diff --git a/exp/pkg/application/app_delegate.h b/exp/pkg/application/app_delegate.h index 1d288bd6b..50ff8b6e9 100644 --- a/exp/pkg/application/app_delegate.h +++ b/exp/pkg/application/app_delegate.h @@ -6,6 +6,7 @@ #import @interface AppDelegate : NSObject +@property bool shouldTerminateWhenLastWindowClosed; @end #endif diff --git a/exp/pkg/application/app_delegate.m b/exp/pkg/application/app_delegate.m index 555fae2a3..af7510935 100644 --- a/exp/pkg/application/app_delegate.m +++ b/exp/pkg/application/app_delegate.m @@ -11,6 +11,12 @@ extern bool hasListeners(unsigned int); [super dealloc]; } +// Create the applicationShouldTerminateAfterLastWindowClosed: method +- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication +{ + return self.shouldTerminateWhenLastWindowClosed; +} + // GENERATED EVENTS START - (void)applicationDidBecomeActive:(NSNotification *)notification { if( hasListeners(EventApplicationDidBecomeActive) ) { diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index 9ee8608b0..e670d391a 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -20,16 +20,14 @@ func New() *App { if globalApplication != nil { return globalApplication } - return NewWithOptions(nil) + return NewWithOptions(options.ApplicationDefaults) } -func NewWithOptions(appOptions *options.Application) *App { +func NewWithOptions(appOptions options.Application) *App { if globalApplication != nil { return globalApplication } - if appOptions == nil { - appOptions = options.ApplicationDefaults - } + appOptions = options.ApplicationDefaults result := &App{ options: appOptions, applicationEventListeners: make(map[uint][]func()), @@ -61,7 +59,7 @@ type windowMessage struct { var windowMessageBuffer = make(chan *windowMessage) type App struct { - options *options.Application + options options.Application applicationEventListeners map[uint][]func() applicationEventListenersLock sync.RWMutex @@ -385,3 +383,8 @@ func (a *App) dispatchOnMainThread(fn func()) { // Call platform specific dispatch function a.impl.dispatchOnMainThread(id) } + +func (a *App) ApplicationShouldTerminateAfterLastWindowClosed() { + a.options.Mac.ApplicationShouldTerminateAfterLastWindowClosed = true + +} diff --git a/exp/pkg/application/application_darwin.go b/exp/pkg/application/application_darwin.go index 84b3c4433..12f739c87 100644 --- a/exp/pkg/application/application_darwin.go +++ b/exp/pkg/application/application_darwin.go @@ -54,6 +54,13 @@ static void init(void) { }]; } +static void setApplicationShouldTerminateAfterLastWindowClosed(bool shouldTerminate) { + // Get the NSApp delegate + AppDelegate *appDelegate = (AppDelegate*)[NSApp delegate]; + // Set the applicationShouldTerminateAfterLastWindowClosed boolean + appDelegate.shouldTerminateWhenLastWindowClosed = shouldTerminate; +} + static void setActivationPolicy(int policy) { [NSApp setActivationPolicy:policy]; } @@ -112,8 +119,6 @@ import ( "unsafe" "github.com/wailsapp/wails/exp/pkg/events" - - "github.com/wailsapp/wails/exp/pkg/options" ) type macosApp struct { @@ -154,9 +159,8 @@ func (m *macosApp) setApplicationMenu(menu *Menu) { func (m *macosApp) run() error { // Add a hook to the ApplicationDidFinishLaunching event m.parent.On(events.Mac.ApplicationDidFinishLaunching, func() { - if m.parent.options != nil && m.parent.options.Mac != nil { - C.setActivationPolicy(C.int(m.parent.options.Mac.ActivationPolicy)) - } + C.setApplicationShouldTerminateAfterLastWindowClosed(C.bool(m.parent.options.Mac.ApplicationShouldTerminateAfterLastWindowClosed)) + C.setActivationPolicy(C.int(m.parent.options.Mac.ActivationPolicy)) C.activateIgnoringOtherApps() }) // setup event listeners @@ -172,10 +176,6 @@ func (m *macosApp) destroy() { } func newPlatformApp(app *App) *macosApp { - appOptions := app.options - if appOptions == nil { - appOptions = options.ApplicationDefaults - } C.init() return &macosApp{ parent: app, diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index d765179c1..988dc0be3 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -53,6 +53,7 @@ type ( show() hide() getScreen() (*Screen, error) + setFrameless(bool) } ) @@ -553,3 +554,11 @@ func (w *Window) GetScreen() (*Screen, error) { } return w.impl.getScreen() } + +func (w *Window) SetFrameless(frameless bool) *Window { + w.options.Frameless = frameless + if w.impl != nil { + w.impl.setFrameless(frameless) + } + return w +} diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index e3cddf6c0..05ff4ddeb 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -67,21 +67,6 @@ void setInvisibleTitleBarHeight(void* window, unsigned int height) { delegate.invisibleTitleBarHeight = height; } -//// Make window toggle frameless -//void windowSetFrameless(void* window, bool frameless) { -// NSWindow* nsWindow = (NSWindow*)window; -// if (frameless) { -// [nsWindow setStyleMask:NSWindowStyleMaskBorderless]; -// } else { -// [nsWindow setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable]; -// } -//} - -void windowSetFrameless(void* window) { - NSWindow* nsWindow = (NSWindow*)window; - [nsWindow setStyleMask:NSWindowStyleMaskBorderless]; -} - // Make NSWindow transparent void windowSetTransparent(void* nsWindow) { // On main thread @@ -673,6 +658,20 @@ static void windowHide(void *window) { }); } +// Make the given window frameless +static void windowSetFrameless(void *window, bool frameless) { + dispatch_async(dispatch_get_main_queue(), ^{ + // get main window + NSWindow* nsWindow = (NSWindow*)window; + // set the window style to be frameless + if (frameless) { + [nsWindow setStyleMask:([nsWindow styleMask] | NSWindowStyleMaskFullSizeContentView)]; + } else { + [nsWindow setStyleMask:([nsWindow styleMask] & ~NSWindowStyleMaskFullSizeContentView)]; + } + }); +} + */ import "C" import ( @@ -691,6 +690,20 @@ type macosWindow struct { parent *Window } +func (w *macosWindow) setFrameless(frameless bool) { + C.windowSetFrameless(w.nsWindow, C.bool(frameless)) + if frameless { + C.windowSetTitleBarAppearsTransparent(w.nsWindow, C.bool(true)) + C.windowSetHideTitle(w.nsWindow, C.bool(true)) + } else { + macOptions := w.parent.options.Mac + appearsTransparent := macOptions.TitleBar.AppearsTransparent + hideTitle := macOptions.TitleBar.HideTitle + C.windowSetTitleBarAppearsTransparent(w.nsWindow, C.bool(appearsTransparent)) + C.windowSetHideTitle(w.nsWindow, C.bool(hideTitle)) + } +} + func (w *macosWindow) getScreen() (*Screen, error) { return getScreenForWindow(w) } @@ -912,6 +925,7 @@ func (w *macosWindow) run() { } globalApplication.dispatchOnMainThread(func() { w.nsWindow = C.windowNew(C.uint(w.parent.id), C.int(w.parent.options.Width), C.int(w.parent.options.Height)) + w.setFrameless(w.parent.options.Frameless) w.setTitle(w.parent.options.Title) w.setAlwaysOnTop(w.parent.options.AlwaysOnTop) w.setResizable(!w.parent.options.DisableResize) @@ -923,36 +937,33 @@ func (w *macosWindow) run() { } w.enableDevTools() w.setBackgroundColour(w.parent.options.BackgroundColour) - if w.parent.options.Mac != nil { - macOptions := w.parent.options.Mac - switch macOptions.Backdrop { - case options.MacBackdropTransparent: - C.windowSetTransparent(w.nsWindow) - C.webviewSetTransparent(w.nsWindow) - case options.MacBackdropTranslucent: - C.windowSetTranslucent(w.nsWindow) - C.webviewSetTransparent(w.nsWindow) - } - if macOptions.TitleBar != nil { - titleBarOptions := macOptions.TitleBar - C.windowSetTitleBarAppearsTransparent(w.nsWindow, C.bool(titleBarOptions.AppearsTransparent)) - C.windowSetHideTitleBar(w.nsWindow, C.bool(titleBarOptions.Hide)) - C.windowSetHideTitle(w.nsWindow, C.bool(titleBarOptions.HideTitle)) - C.windowSetFullSizeContent(w.nsWindow, C.bool(titleBarOptions.FullSizeContent)) - if titleBarOptions.UseToolbar { - C.windowSetUseToolbar(w.nsWindow, C.bool(titleBarOptions.UseToolbar), C.int(titleBarOptions.ToolbarStyle)) - } - C.windowSetHideToolbarSeparator(w.nsWindow, C.bool(titleBarOptions.HideToolbarSeparator)) - } + macOptions := w.parent.options.Mac + switch macOptions.Backdrop { + case options.MacBackdropTransparent: + C.windowSetTransparent(w.nsWindow) + C.webviewSetTransparent(w.nsWindow) + case options.MacBackdropTranslucent: + C.windowSetTranslucent(w.nsWindow) + C.webviewSetTransparent(w.nsWindow) + } - if macOptions.Appearance != "" { - C.windowSetAppearanceTypeByName(w.nsWindow, C.CString(string(macOptions.Appearance))) - } + titleBarOptions := macOptions.TitleBar + C.windowSetTitleBarAppearsTransparent(w.nsWindow, C.bool(titleBarOptions.AppearsTransparent)) + C.windowSetHideTitleBar(w.nsWindow, C.bool(titleBarOptions.Hide)) + C.windowSetHideTitle(w.nsWindow, C.bool(titleBarOptions.HideTitle)) + C.windowSetFullSizeContent(w.nsWindow, C.bool(titleBarOptions.FullSizeContent)) + if titleBarOptions.UseToolbar { + C.windowSetUseToolbar(w.nsWindow, C.bool(titleBarOptions.UseToolbar), C.int(titleBarOptions.ToolbarStyle)) + } + C.windowSetHideToolbarSeparator(w.nsWindow, C.bool(titleBarOptions.HideToolbarSeparator)) - if macOptions.InvisibleTitleBarHeight != 0 { - C.windowSetInvisibleTitleBar(w.nsWindow, C.uint(macOptions.InvisibleTitleBarHeight)) - } + if macOptions.Appearance != "" { + C.windowSetAppearanceTypeByName(w.nsWindow, C.CString(string(macOptions.Appearance))) + } + + if macOptions.InvisibleTitleBarHeight != 0 { + C.windowSetInvisibleTitleBar(w.nsWindow, C.uint(macOptions.InvisibleTitleBarHeight)) } switch w.parent.options.StartState { diff --git a/exp/pkg/options/application.go b/exp/pkg/options/application.go index d5226f6b5..d941c46ee 100644 --- a/exp/pkg/options/application.go +++ b/exp/pkg/options/application.go @@ -1,11 +1,11 @@ package options type Application struct { - Mac *Mac + Mac Mac } -var ApplicationDefaults = &Application{ - Mac: &Mac{ +var ApplicationDefaults = Application{ + Mac: Mac{ ActivationPolicy: ActivationPolicyRegular, }, } diff --git a/exp/pkg/options/mac.go b/exp/pkg/options/mac.go index 9851c925c..81ebf9efa 100644 --- a/exp/pkg/options/mac.go +++ b/exp/pkg/options/mac.go @@ -11,7 +11,8 @@ const ( type Mac struct { // ActivationPolicy is the activation policy for the application. Defaults to // applicationActivationPolicyRegular. - ActivationPolicy ActivationPolicy + ActivationPolicy ActivationPolicy + ApplicationShouldTerminateAfterLastWindowClosed bool } type MacBackdrop int @@ -40,7 +41,7 @@ const ( // MacWindow contains macOS specific options type MacWindow struct { Backdrop MacBackdrop - TitleBar *TitleBar + TitleBar TitleBar Appearance MacAppearanceType InvisibleTitleBarHeight int } @@ -57,7 +58,7 @@ type TitleBar struct { } // TitleBarDefault results in the default Mac TitleBar -var TitleBarDefault = &TitleBar{ +var TitleBarDefault = TitleBar{ AppearsTransparent: false, Hide: false, HideTitle: false, @@ -71,7 +72,7 @@ var TitleBarDefault = &TitleBar{ // TitleBarHidden results in a hidden title bar and a full size content window, // yet the title bar still has the standard window controls (“traffic lights”) // in the top left. -var TitleBarHidden = &TitleBar{ +var TitleBarHidden = TitleBar{ AppearsTransparent: true, Hide: false, HideTitle: true, @@ -82,7 +83,7 @@ var TitleBarHidden = &TitleBar{ // TitleBarHiddenInset results in a hidden title bar with an alternative look where // the traffic light buttons are slightly more inset from the window edge. -var TitleBarHiddenInset = &TitleBar{ +var TitleBarHiddenInset = TitleBar{ AppearsTransparent: true, Hide: false, HideTitle: true, @@ -93,7 +94,7 @@ var TitleBarHiddenInset = &TitleBar{ // TitleBarHiddenInsetUnified results in a hidden title bar with an alternative look where // the traffic light buttons are even more inset from the window edge. -var TitleBarHiddenInsetUnified = &TitleBar{ +var TitleBarHiddenInsetUnified = TitleBar{ AppearsTransparent: true, Hide: false, HideTitle: true, diff --git a/exp/pkg/options/window.go b/exp/pkg/options/window.go index de4f15603..47e8591c1 100644 --- a/exp/pkg/options/window.go +++ b/exp/pkg/options/window.go @@ -28,7 +28,7 @@ type Window struct { MaxWidth int MaxHeight int StartState WindowState - Mac *MacWindow + Mac MacWindow BackgroundColour *RGBA Assets Assets HTML string From cf5def05a6bebe690156a8bb56818afa12c9add1 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sat, 31 Dec 2022 10:38:36 +1100 Subject: [PATCH 62/85] Refactor application API to use options by default. Updated examples. --- exp/examples/clipboard/main.go | 12 +++-- exp/examples/dialogs/main.go | 13 +++-- exp/examples/kitchensink/main.go | 14 ++--- exp/examples/menu/main.go | 12 +++-- exp/examples/plain/main.go | 18 ++++--- exp/examples/systray/main.go | 21 ++++++-- exp/examples/window/main.go | 11 ++-- exp/pkg/application/application.go | 73 +++++++------------------- exp/pkg/application/dialogs_darwin.go | 4 +- exp/pkg/application/menuitem_darwin.go | 6 +-- exp/pkg/application/roles.go | 2 +- exp/pkg/options/application.go | 11 ++-- exp/pkg/options/mac.go | 5 +- 13 files changed, 102 insertions(+), 100 deletions(-) diff --git a/exp/examples/clipboard/main.go b/exp/examples/clipboard/main.go index 7d5c777e0..1526d7798 100644 --- a/exp/examples/clipboard/main.go +++ b/exp/examples/clipboard/main.go @@ -5,14 +5,20 @@ import ( "log" "time" + "github.com/wailsapp/wails/exp/pkg/options" + "github.com/wailsapp/wails/exp/pkg/application" ) func main() { - app := application.New() - app.SetName("Clipboard Demo") - app.SetDescription("A demo of the clipboard") + app := application.New(options.Application{ + Name: "Clipboard Demo", + Description: "A demo of the clipboard API", + Mac: options.Mac{ + ApplicationShouldTerminateAfterLastWindowClosed: true, + }, + }) // Create a custom menu menu := app.NewMenu() diff --git a/exp/examples/dialogs/main.go b/exp/examples/dialogs/main.go index 0354fee7a..92f695f40 100644 --- a/exp/examples/dialogs/main.go +++ b/exp/examples/dialogs/main.go @@ -7,15 +7,20 @@ import ( "runtime" "strings" + "github.com/wailsapp/wails/exp/pkg/options" + "github.com/wailsapp/wails/exp/pkg/application" ) func main() { - app := application.New() - app.SetName("Dialogs Demo") - app.SetDescription("A demo of the Wails dialogs") - + app := application.New(options.Application{ + Name: "Dialogs Demo", + Description: "A demo of the dialogs API", + Mac: options.Mac{ + ApplicationShouldTerminateAfterLastWindowClosed: true, + }, + }) // Create a custom menu menu := app.NewMenu() menu.AddRole(application.AppMenu) diff --git a/exp/examples/kitchensink/main.go b/exp/examples/kitchensink/main.go index a7138db78..415093a3f 100644 --- a/exp/examples/kitchensink/main.go +++ b/exp/examples/kitchensink/main.go @@ -12,9 +12,11 @@ import ( ) func main() { - app := application.NewWithOptions(&options.Application{ - Mac: &options.Mac{ - //ActivationPolicy: options.ActivationPolicyAccessory, + app := application.New(options.Application{ + Name: "Menu Demo", + Description: "A demo of the menu system", + Mac: options.Mac{ + ApplicationShouldTerminateAfterLastWindowClosed: true, }, }) /* @@ -121,7 +123,7 @@ func main() { Alpha: 30, }, StartState: options.WindowStateMaximised, - Mac: &options.MacWindow{ + Mac: options.MacWindow{ Backdrop: options.MacBackdropTranslucent, Appearance: options.NSAppearanceNameDarkAqua, }, @@ -189,7 +191,7 @@ func main() { Height: 768, AlwaysOnTop: false, URL: "https://google.com", - Mac: &options.MacWindow{ + Mac: options.MacWindow{ Backdrop: options.MacBackdropTranslucent, }, }) @@ -206,7 +208,7 @@ func main() { myWindow2Lock.RLock() myWindow.SetTitle("Wooooo") myWindow.SetAlwaysOnTop(true) - myWindow2.SetTitle("OMFG") + myWindow2.SetTitle("OMG") myWindow2.SetURL("https://wails.io") myWindow.SetMinSize(600, 600) myWindow.SetMaxSize(650, 650) diff --git a/exp/examples/menu/main.go b/exp/examples/menu/main.go index 6f3581113..83f71f578 100644 --- a/exp/examples/menu/main.go +++ b/exp/examples/menu/main.go @@ -4,14 +4,20 @@ import ( _ "embed" "log" + "github.com/wailsapp/wails/exp/pkg/options" + "github.com/wailsapp/wails/exp/pkg/application" ) func main() { - app := application.New() - app.SetName("Menu Demo") - app.SetDescription("A demo of the menu system") + app := application.New(options.Application{ + Name: "Menu Demo", + Description: "A demo of the menu system", + Mac: options.Mac{ + ApplicationShouldTerminateAfterLastWindowClosed: true, + }, + }) // Create a custom menu menu := app.NewMenu() diff --git a/exp/examples/plain/main.go b/exp/examples/plain/main.go index cdd59c2af..0b41d13a9 100644 --- a/exp/examples/plain/main.go +++ b/exp/examples/plain/main.go @@ -10,15 +10,19 @@ import ( ) func main() { - app := application.New() - + app := application.New(options.Application{ + Name: "Plain", + Description: "A demo of using raw HTML & CSS", + Mac: options.Mac{ + ApplicationShouldTerminateAfterLastWindowClosed: true, + }, + }) // Create window app.NewWindowWithOptions(&options.Window{ - Title: "Plain Bundle", - EnableDevTools: true, - HTML: `Plain Bundle

Plain Bundle

This is a plain bundle. It has no frontend code.

`, - CSS: `body { background-color: rgba(255, 255, 255, 0); } .main { color: white; margin: 20%; }`, - Mac: &options.MacWindow{ + Title: "Plain Bundle", + HTML: `Plain Bundle

Plain Bundle

This is a plain bundle. It has no frontend code.

`, + CSS: `body { background-color: rgba(255, 255, 255, 0); } .main { color: white; margin: 20%; }`, + Mac: options.MacWindow{ InvisibleTitleBarHeight: 50, Backdrop: options.MacBackdropTranslucent, TitleBar: options.TitleBarHiddenInset, diff --git a/exp/examples/systray/main.go b/exp/examples/systray/main.go index 5b746dc82..f037bbb6a 100644 --- a/exp/examples/systray/main.go +++ b/exp/examples/systray/main.go @@ -3,6 +3,7 @@ package main import ( _ "embed" "log" + "runtime" "github.com/wailsapp/wails/exp/pkg/options" @@ -10,17 +11,27 @@ import ( ) func main() { - app := application.New() - app.SetActivationPolicy(options.ActivationPolicyAccessory) + app := application.New(options.Application{ + Name: "Systray Demo", + Description: "A demo of the Systray API", + Mac: options.Mac{ + ActivationPolicy: options.ActivationPolicyAccessory, + }, + }) - systemTray := app.NewSystemTray().SetIcon(application.DefaultMacTemplateIcon) + systemTray := app.NewSystemTray() + if runtime.GOOS == "darwin" { + systemTray.SetIcon(application.DefaultMacTemplateIcon) + } myMenu := app.NewMenu() myMenu.Add("Hello World!").OnClick(func(ctx *application.Context) { - ctx.ClickedMenuItem().SetLabel("Clicked!") + app.NewInfoDialog().SetTitle("Hello World!").SetMessage("Hello World!").Show() }) subMenu := myMenu.AddSubmenu("Submenu") - subMenu.Add("Submenu Item") + subMenu.Add("Click me!").OnClick(func(ctx *application.Context) { + ctx.ClickedMenuItem().SetLabel("Clicked!") + }) myMenu.AddSeparator() myMenu.Add("Quit").OnClick(func(ctx *application.Context) { app.Quit() diff --git a/exp/examples/window/main.go b/exp/examples/window/main.go index 38bc80b94..df6e842e0 100644 --- a/exp/examples/window/main.go +++ b/exp/examples/window/main.go @@ -17,10 +17,13 @@ import ( ) func main() { - app := application.New() - app.SetName("Window Demo") - app.ApplicationShouldTerminateAfterLastWindowClosed() - app.SetDescription("A demo of the windowing capabilities") + app := application.New(options.Application{ + Name: "Window Demo", + Description: "A demo of the Window API", + Mac: options.Mac{ + ApplicationShouldTerminateAfterLastWindowClosed: true, + }, + }) app.On(events.Mac.ApplicationDidFinishLaunching, func() { log.Println("ApplicationDidFinishLaunching") }) diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index e670d391a..43fb2125b 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -16,28 +16,35 @@ func init() { runtime.LockOSThread() } -func New() *App { +func New(appOptions options.Application) *App { if globalApplication != nil { return globalApplication } - return NewWithOptions(options.ApplicationDefaults) -} -func NewWithOptions(appOptions options.Application) *App { - if globalApplication != nil { - return globalApplication - } - appOptions = options.ApplicationDefaults + mergeApplicationDefaults(&appOptions) + result := &App{ options: appOptions, applicationEventListeners: make(map[uint][]func()), systemTrays: make(map[uint]*SystemTray), - icon: DefaultApplicationIcon, } globalApplication = result return result } +func mergeApplicationDefaults(o *options.Application) { + if o.Name == "" { + o.Name = "My Wails Application" + } + if o.Description == "" { + o.Description = "An application written using Wails" + } + if o.Icon == nil { + o.Icon = DefaultApplicationIcon + } + +} + type platformApp interface { run() error destroy() @@ -89,10 +96,7 @@ type App struct { ApplicationMenu *Menu // About MessageDialog - name string - description string - icon []byte - clipboard *Clipboard + clipboard *Clipboard } func (a *App) getSystemTrayID() uint { @@ -202,9 +206,7 @@ func (a *App) Run() error { a.impl.setApplicationMenu(a.ApplicationMenu) // set the application icon - if a.icon != nil { - a.impl.setIcon(a.icon) - } + a.impl.setIcon(a.options.Icon) return a.impl.run() } @@ -288,47 +290,15 @@ func (a *App) Quit() { a.impl.destroy() } -func (a *App) SetActivationPolicy(accessory options.ActivationPolicy) { - a.options.Mac.ActivationPolicy = accessory -} - func (a *App) SetMenu(menu *Menu) { a.ApplicationMenu = menu if a.impl != nil { a.impl.setApplicationMenu(menu) } } - -func (a *App) SetName(name string) { - a.name = name -} - -func (a *App) Name() string { - return a.name -} - -func (a *App) SetIcon(icon []byte) { - a.icon = icon - if a.impl != nil { - a.impl.setIcon(icon) - } -} - -func (a *App) Icon() []byte { - return a.icon -} - -func (a *App) SetDescription(description string) { - a.description = description -} - -func (a *App) Description() string { - return a.description -} - func (a *App) ShowAboutDialog() { if a.impl != nil { - a.impl.showAboutDialog(a.name, a.description, a.icon) + a.impl.showAboutDialog(a.options.Name, a.options.Description, a.options.Icon) } } @@ -383,8 +353,3 @@ func (a *App) dispatchOnMainThread(fn func()) { // Call platform specific dispatch function a.impl.dispatchOnMainThread(id) } - -func (a *App) ApplicationShouldTerminateAfterLastWindowClosed() { - a.options.Mac.ApplicationShouldTerminateAfterLastWindowClosed = true - -} diff --git a/exp/pkg/application/dialogs_darwin.go b/exp/pkg/application/dialogs_darwin.go index b2818750a..717465095 100644 --- a/exp/pkg/application/dialogs_darwin.go +++ b/exp/pkg/application/dialogs_darwin.go @@ -339,8 +339,8 @@ func (m *macosDialog) show() { } else { // if it's an error, use the application icon if m.dialog.dialogType == ErrorDialog { - iconData = unsafe.Pointer(&globalApplication.icon[0]) - iconLength = C.int(len(globalApplication.icon)) + iconData = unsafe.Pointer(&globalApplication.options.Icon[0]) + iconLength = C.int(len(globalApplication.options.Icon)) } } diff --git a/exp/pkg/application/menuitem_darwin.go b/exp/pkg/application/menuitem_darwin.go index 9288aaa65..ce79ece3e 100644 --- a/exp/pkg/application/menuitem_darwin.go +++ b/exp/pkg/application/menuitem_darwin.go @@ -402,7 +402,7 @@ func newSpeechMenu() *MenuItem { } func newHideMenuItem() *MenuItem { - return newMenuItem("Hide " + globalApplication.Name()). + return newMenuItem("Hide " + globalApplication.options.Name). SetAccelerator("CmdOrCtrl+h"). OnClick(func(ctx *Context) { C.hideApplication() @@ -482,7 +482,7 @@ func newDeleteMenuItem() *MenuItem { } func newQuitMenuItem() *MenuItem { - return newMenuItem("Quit " + globalApplication.Name()). + return newMenuItem("Quit " + globalApplication.options.Name). SetAccelerator("CmdOrCtrl+q"). OnClick(func(ctx *Context) { globalApplication.Quit() @@ -498,7 +498,7 @@ func newSelectAllMenuItem() *MenuItem { } func newAboutMenuItem() *MenuItem { - return newMenuItem("About " + globalApplication.Name()). + return newMenuItem("About " + globalApplication.options.Name). OnClick(func(ctx *Context) { globalApplication.ShowAboutDialog() }) diff --git a/exp/pkg/application/roles.go b/exp/pkg/application/roles.go index e85844e24..0aec3bd48 100644 --- a/exp/pkg/application/roles.go +++ b/exp/pkg/application/roles.go @@ -98,7 +98,7 @@ func newAppMenu() *MenuItem { appMenu.AddRole(UnHide) appMenu.AddSeparator() appMenu.AddRole(Quit) - subMenu := newSubMenuItem(globalApplication.Name()) + subMenu := newSubMenuItem(globalApplication.options.Name) subMenu.submenu = appMenu return subMenu } diff --git a/exp/pkg/options/application.go b/exp/pkg/options/application.go index d941c46ee..2359ce2bb 100644 --- a/exp/pkg/options/application.go +++ b/exp/pkg/options/application.go @@ -1,11 +1,8 @@ package options type Application struct { - Mac Mac -} - -var ApplicationDefaults = Application{ - Mac: Mac{ - ActivationPolicy: ActivationPolicyRegular, - }, + Name string + Description string + Icon []byte + Mac Mac } diff --git a/exp/pkg/options/mac.go b/exp/pkg/options/mac.go index 81ebf9efa..ec5f2cc33 100644 --- a/exp/pkg/options/mac.go +++ b/exp/pkg/options/mac.go @@ -4,6 +4,8 @@ type ActivationPolicy int const ( ActivationPolicyRegular ActivationPolicy = iota + // ActivationPolicyAccessory is used for applications that do not have a main window, + // such as system tray applications or background applications. ActivationPolicyAccessory ActivationPolicyProhibited ) @@ -11,7 +13,8 @@ const ( type Mac struct { // ActivationPolicy is the activation policy for the application. Defaults to // applicationActivationPolicyRegular. - ActivationPolicy ActivationPolicy + ActivationPolicy ActivationPolicy + // If set to true, the application will terminate when the last window is closed. ApplicationShouldTerminateAfterLastWindowClosed bool } From be240795e257d91e89ea69cb4998a7c3e4e01ab3 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sat, 31 Dec 2022 11:01:24 +1100 Subject: [PATCH 63/85] Refactor assetserver into pkg --- v2/internal/app/app_dev.go | 3 ++- v2/internal/frontend/desktop/darwin/frontend.go | 3 ++- v2/internal/frontend/desktop/linux/frontend.go | 3 ++- v2/internal/frontend/desktop/linux/webkit2_36.go | 2 +- v2/internal/frontend/desktop/linux/webkit2_legacy.go | 2 +- v2/internal/frontend/desktop/linux/webkit2_responsewriter.go | 2 +- v2/internal/frontend/desktop/windows/frontend.go | 2 +- v2/internal/frontend/devserver/devserver.go | 3 ++- v2/{internal/frontend => pkg}/assetserver/assethandler.go | 0 v2/{internal/frontend => pkg}/assetserver/assetserver.go | 0 v2/{internal/frontend => pkg}/assetserver/assetserver_dev.go | 0 v2/{internal/frontend => pkg}/assetserver/common.go | 0 .../frontend => pkg}/assetserver/content_type_sniffer.go | 0 v2/{internal/frontend => pkg}/assetserver/defaultindex.html | 0 v2/{internal/frontend => pkg}/assetserver/fs.go | 0 v2/{internal/frontend => pkg}/assetserver/mimecache.go | 0 v2/{internal/frontend => pkg}/assetserver/mimecache_test.go | 0 v2/{internal/frontend => pkg}/assetserver/testdata/index.html | 0 v2/{internal/frontend => pkg}/assetserver/testdata/main.css | 0 v2/{internal/frontend => pkg}/assetserver/testdata/main.js | 0 .../frontend => pkg}/assetserver/testdata/subdir/index.html | 0 .../frontend => pkg}/assetserver/testdata/subdir/main.css | 0 .../frontend => pkg}/assetserver/testdata/subdir/main.js | 0 v2/{internal/frontend => pkg}/assetserver/testdata/testdata.go | 0 24 files changed, 12 insertions(+), 8 deletions(-) rename v2/{internal/frontend => pkg}/assetserver/assethandler.go (100%) rename v2/{internal/frontend => pkg}/assetserver/assetserver.go (100%) rename v2/{internal/frontend => pkg}/assetserver/assetserver_dev.go (100%) rename v2/{internal/frontend => pkg}/assetserver/common.go (100%) rename v2/{internal/frontend => pkg}/assetserver/content_type_sniffer.go (100%) rename v2/{internal/frontend => pkg}/assetserver/defaultindex.html (100%) rename v2/{internal/frontend => pkg}/assetserver/fs.go (100%) rename v2/{internal/frontend => pkg}/assetserver/mimecache.go (100%) rename v2/{internal/frontend => pkg}/assetserver/mimecache_test.go (100%) rename v2/{internal/frontend => pkg}/assetserver/testdata/index.html (100%) rename v2/{internal/frontend => pkg}/assetserver/testdata/main.css (100%) rename v2/{internal/frontend => pkg}/assetserver/testdata/main.js (100%) rename v2/{internal/frontend => pkg}/assetserver/testdata/subdir/index.html (100%) rename v2/{internal/frontend => pkg}/assetserver/testdata/subdir/main.css (100%) rename v2/{internal/frontend => pkg}/assetserver/testdata/subdir/main.js (100%) rename v2/{internal/frontend => pkg}/assetserver/testdata/testdata.go (100%) diff --git a/v2/internal/app/app_dev.go b/v2/internal/app/app_dev.go index 91a47fbf1..32c27fa2e 100644 --- a/v2/internal/app/app_dev.go +++ b/v2/internal/app/app_dev.go @@ -12,8 +12,9 @@ import ( "os" "path/filepath" + "github.com/wailsapp/wails/v2/pkg/assetserver" + "github.com/wailsapp/wails/v2/internal/binding" - "github.com/wailsapp/wails/v2/internal/frontend/assetserver" "github.com/wailsapp/wails/v2/internal/frontend/desktop" "github.com/wailsapp/wails/v2/internal/frontend/devserver" "github.com/wailsapp/wails/v2/internal/frontend/dispatcher" diff --git a/v2/internal/frontend/desktop/darwin/frontend.go b/v2/internal/frontend/desktop/darwin/frontend.go index 062c9307e..07437a541 100644 --- a/v2/internal/frontend/desktop/darwin/frontend.go +++ b/v2/internal/frontend/desktop/darwin/frontend.go @@ -23,9 +23,10 @@ import ( "net/url" "strconv" + "github.com/wailsapp/wails/v2/pkg/assetserver" + "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/runtime" "github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/pkg/options" diff --git a/v2/internal/frontend/desktop/linux/frontend.go b/v2/internal/frontend/desktop/linux/frontend.go index fc39cd836..3f4028414 100644 --- a/v2/internal/frontend/desktop/linux/frontend.go +++ b/v2/internal/frontend/desktop/linux/frontend.go @@ -88,9 +88,10 @@ import ( "text/template" "unsafe" + "github.com/wailsapp/wails/v2/pkg/assetserver" + "github.com/wailsapp/wails/v2/internal/binding" "github.com/wailsapp/wails/v2/internal/frontend" - "github.com/wailsapp/wails/v2/internal/frontend/assetserver" wailsruntime "github.com/wailsapp/wails/v2/internal/frontend/runtime" "github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/pkg/options" diff --git a/v2/internal/frontend/desktop/linux/webkit2_36.go b/v2/internal/frontend/desktop/linux/webkit2_36.go index a5669ba08..0c0c382e6 100644 --- a/v2/internal/frontend/desktop/linux/webkit2_36.go +++ b/v2/internal/frontend/desktop/linux/webkit2_36.go @@ -16,7 +16,7 @@ import ( "strings" "unsafe" - "github.com/wailsapp/wails/v2/internal/frontend/assetserver" + "github.com/wailsapp/wails/v2/pkg/assetserver" ) const webkit2MinMinorVersion = 36 diff --git a/v2/internal/frontend/desktop/linux/webkit2_legacy.go b/v2/internal/frontend/desktop/linux/webkit2_legacy.go index d3c1b581b..9d5158f4e 100644 --- a/v2/internal/frontend/desktop/linux/webkit2_legacy.go +++ b/v2/internal/frontend/desktop/linux/webkit2_legacy.go @@ -15,7 +15,7 @@ import ( "net/http" "unsafe" - "github.com/wailsapp/wails/v2/internal/frontend/assetserver" + "github.com/wailsapp/wails/v2/pkg/assetserver" ) const webkit2MinMinorVersion = 0 diff --git a/v2/internal/frontend/desktop/linux/webkit2_responsewriter.go b/v2/internal/frontend/desktop/linux/webkit2_responsewriter.go index 0f858b805..ca3fa65c7 100644 --- a/v2/internal/frontend/desktop/linux/webkit2_responsewriter.go +++ b/v2/internal/frontend/desktop/linux/webkit2_responsewriter.go @@ -21,7 +21,7 @@ import ( "syscall" "unsafe" - "github.com/wailsapp/wails/v2/internal/frontend/assetserver" + "github.com/wailsapp/wails/v2/pkg/assetserver" ) type webKitResponseWriter struct { diff --git a/v2/internal/frontend/desktop/windows/frontend.go b/v2/internal/frontend/desktop/windows/frontend.go index d60e33fc3..dbd97d38d 100644 --- a/v2/internal/frontend/desktop/windows/frontend.go +++ b/v2/internal/frontend/desktop/windows/frontend.go @@ -22,7 +22,6 @@ import ( "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" @@ -30,6 +29,7 @@ import ( wailsruntime "github.com/wailsapp/wails/v2/internal/frontend/runtime" "github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/internal/system/operatingsystem" + "github.com/wailsapp/wails/v2/pkg/assetserver" "github.com/wailsapp/wails/v2/pkg/options" "github.com/wailsapp/wails/v2/pkg/options/windows" ) diff --git a/v2/internal/frontend/devserver/devserver.go b/v2/internal/frontend/devserver/devserver.go index 7b5f50ce4..8d5003c60 100644 --- a/v2/internal/frontend/devserver/devserver.go +++ b/v2/internal/frontend/devserver/devserver.go @@ -18,12 +18,13 @@ import ( "sync" "time" + "github.com/wailsapp/wails/v2/pkg/assetserver" + "github.com/wailsapp/wails/v2/internal/frontend/runtime" "github.com/labstack/echo/v4" "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/logger" "github.com/wailsapp/wails/v2/internal/menumanager" "github.com/wailsapp/wails/v2/pkg/options" diff --git a/v2/internal/frontend/assetserver/assethandler.go b/v2/pkg/assetserver/assethandler.go similarity index 100% rename from v2/internal/frontend/assetserver/assethandler.go rename to v2/pkg/assetserver/assethandler.go diff --git a/v2/internal/frontend/assetserver/assetserver.go b/v2/pkg/assetserver/assetserver.go similarity index 100% rename from v2/internal/frontend/assetserver/assetserver.go rename to v2/pkg/assetserver/assetserver.go diff --git a/v2/internal/frontend/assetserver/assetserver_dev.go b/v2/pkg/assetserver/assetserver_dev.go similarity index 100% rename from v2/internal/frontend/assetserver/assetserver_dev.go rename to v2/pkg/assetserver/assetserver_dev.go diff --git a/v2/internal/frontend/assetserver/common.go b/v2/pkg/assetserver/common.go similarity index 100% rename from v2/internal/frontend/assetserver/common.go rename to v2/pkg/assetserver/common.go diff --git a/v2/internal/frontend/assetserver/content_type_sniffer.go b/v2/pkg/assetserver/content_type_sniffer.go similarity index 100% rename from v2/internal/frontend/assetserver/content_type_sniffer.go rename to v2/pkg/assetserver/content_type_sniffer.go diff --git a/v2/internal/frontend/assetserver/defaultindex.html b/v2/pkg/assetserver/defaultindex.html similarity index 100% rename from v2/internal/frontend/assetserver/defaultindex.html rename to v2/pkg/assetserver/defaultindex.html diff --git a/v2/internal/frontend/assetserver/fs.go b/v2/pkg/assetserver/fs.go similarity index 100% rename from v2/internal/frontend/assetserver/fs.go rename to v2/pkg/assetserver/fs.go diff --git a/v2/internal/frontend/assetserver/mimecache.go b/v2/pkg/assetserver/mimecache.go similarity index 100% rename from v2/internal/frontend/assetserver/mimecache.go rename to v2/pkg/assetserver/mimecache.go diff --git a/v2/internal/frontend/assetserver/mimecache_test.go b/v2/pkg/assetserver/mimecache_test.go similarity index 100% rename from v2/internal/frontend/assetserver/mimecache_test.go rename to v2/pkg/assetserver/mimecache_test.go diff --git a/v2/internal/frontend/assetserver/testdata/index.html b/v2/pkg/assetserver/testdata/index.html similarity index 100% rename from v2/internal/frontend/assetserver/testdata/index.html rename to v2/pkg/assetserver/testdata/index.html diff --git a/v2/internal/frontend/assetserver/testdata/main.css b/v2/pkg/assetserver/testdata/main.css similarity index 100% rename from v2/internal/frontend/assetserver/testdata/main.css rename to v2/pkg/assetserver/testdata/main.css diff --git a/v2/internal/frontend/assetserver/testdata/main.js b/v2/pkg/assetserver/testdata/main.js similarity index 100% rename from v2/internal/frontend/assetserver/testdata/main.js rename to v2/pkg/assetserver/testdata/main.js diff --git a/v2/internal/frontend/assetserver/testdata/subdir/index.html b/v2/pkg/assetserver/testdata/subdir/index.html similarity index 100% rename from v2/internal/frontend/assetserver/testdata/subdir/index.html rename to v2/pkg/assetserver/testdata/subdir/index.html diff --git a/v2/internal/frontend/assetserver/testdata/subdir/main.css b/v2/pkg/assetserver/testdata/subdir/main.css similarity index 100% rename from v2/internal/frontend/assetserver/testdata/subdir/main.css rename to v2/pkg/assetserver/testdata/subdir/main.css diff --git a/v2/internal/frontend/assetserver/testdata/subdir/main.js b/v2/pkg/assetserver/testdata/subdir/main.js similarity index 100% rename from v2/internal/frontend/assetserver/testdata/subdir/main.js rename to v2/pkg/assetserver/testdata/subdir/main.js diff --git a/v2/internal/frontend/assetserver/testdata/testdata.go b/v2/pkg/assetserver/testdata/testdata.go similarity index 100% rename from v2/internal/frontend/assetserver/testdata/testdata.go rename to v2/pkg/assetserver/testdata/testdata.go From bc7d8295ba691b923dbb50374eda6119472063ed Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Mon, 2 Jan 2023 05:48:52 +1100 Subject: [PATCH 64/85] Refactor window -> webviewwindow --- exp/examples/clipboard/main.go | 2 +- exp/examples/dialogs/main.go | 6 +- exp/examples/kitchensink/main.go | 6 +- exp/examples/menu/main.go | 8 +- exp/examples/plain/main.go | 2 +- exp/examples/window/main.go | 98 ++++++------ exp/pkg/application/application.go | 16 +- exp/pkg/application/application_darwin.go | 8 +- exp/pkg/application/dialogs.go | 8 +- exp/pkg/application/dialogs_darwin.go | 4 +- exp/pkg/application/roles.go | 2 +- exp/pkg/application/screen_darwin.go | 2 +- .../{window.go => webview_window.go} | 110 +++++++------- ...dow_darwin.go => webview_window_darwin.go} | 140 +++++++++--------- ...w_delegate.h => webview_window_delegate.h} | 8 +- ...w_delegate.m => webview_window_delegate.m} | 6 +- ...devtools.go => webview_window_devtools.go} | 4 +- exp/pkg/options/window.go | 4 +- v2/examples/systray/main.go | 5 +- 19 files changed, 220 insertions(+), 219 deletions(-) rename exp/pkg/application/{window.go => webview_window.go} (74%) rename exp/pkg/application/{window_darwin.go => webview_window_darwin.go} (86%) rename exp/pkg/application/{window_delegate.h => webview_window_delegate.h} (63%) rename exp/pkg/application/{window_delegate.m => webview_window_delegate.m} (99%) rename exp/pkg/application/{window_devtools.go => webview_window_devtools.go} (82%) diff --git a/exp/examples/clipboard/main.go b/exp/examples/clipboard/main.go index 1526d7798..28c0de15c 100644 --- a/exp/examples/clipboard/main.go +++ b/exp/examples/clipboard/main.go @@ -61,7 +61,7 @@ func main() { app.SetMenu(menu) - app.NewWindow() + app.NewWebviewWindow() err := app.Run() diff --git a/exp/examples/dialogs/main.go b/exp/examples/dialogs/main.go index 92f695f40..fe43d3a99 100644 --- a/exp/examples/dialogs/main.go +++ b/exp/examples/dialogs/main.go @@ -280,7 +280,7 @@ func main() { app.NewInfoDialog().SetMessage(result).Show() } }) - saveMenu.Add("Select File (Attach To Window)").OnClick(func(ctx *application.Context) { + saveMenu.Add("Select File (Attach To WebviewWindow)").OnClick(func(ctx *application.Context) { result, _ := app.NewSaveFileDialog(). AttachToWindow(app.CurrentWindow()). PromptForSingleSelection() @@ -324,8 +324,8 @@ func main() { app.SetMenu(menu) - app.NewWindow() - app.NewWindow() + app.NewWebviewWindow() + app.NewWebviewWindow() err := app.Run() diff --git a/exp/examples/kitchensink/main.go b/exp/examples/kitchensink/main.go index 415093a3f..53fa91eca 100644 --- a/exp/examples/kitchensink/main.go +++ b/exp/examples/kitchensink/main.go @@ -110,7 +110,7 @@ func main() { mySystray.SetMenu(myMenu) mySystray.SetIconPosition(application.NSImageLeading) - myWindow := app.NewWindowWithOptions(&options.Window{ + myWindow := app.NewWebviewWindowWithOptions(&options.WebviewWindow{ Title: "Kitchen Sink", Width: 600, Height: 400, @@ -183,9 +183,9 @@ func main() { println(myWindow.ID(), "WindowDidExitVersionBrowser") }) */ - var myWindow2 *application.Window + var myWindow2 *application.WebviewWindow var myWindow2Lock sync.RWMutex - myWindow2 = app.NewWindowWithOptions(&options.Window{ + myWindow2 = app.NewWebviewWindowWithOptions(&options.WebviewWindow{ Title: "#2", Width: 1024, Height: 768, diff --git a/exp/examples/menu/main.go b/exp/examples/menu/main.go index 83f71f578..d91705eb4 100644 --- a/exp/examples/menu/main.go +++ b/exp/examples/menu/main.go @@ -35,13 +35,13 @@ func main() { }) // You can control the current window from the menu - myMenu.Add("Lock Window Resize").OnClick(func(ctx *application.Context) { + myMenu.Add("Lock WebviewWindow Resize").OnClick(func(ctx *application.Context) { if app.CurrentWindow().Resizable() { app.CurrentWindow().SetResizable(false) - ctx.ClickedMenuItem().SetLabel("Unlock Window Resize") + ctx.ClickedMenuItem().SetLabel("Unlock WebviewWindow Resize") } else { app.CurrentWindow().SetResizable(true) - ctx.ClickedMenuItem().SetLabel("Lock Window Resize") + ctx.ClickedMenuItem().SetLabel("Lock WebviewWindow Resize") } }) @@ -87,7 +87,7 @@ func main() { app.SetMenu(menu) - app.NewWindow() + app.NewWebviewWindow() err := app.Run() diff --git a/exp/examples/plain/main.go b/exp/examples/plain/main.go index 0b41d13a9..0f7171083 100644 --- a/exp/examples/plain/main.go +++ b/exp/examples/plain/main.go @@ -18,7 +18,7 @@ func main() { }, }) // Create window - app.NewWindowWithOptions(&options.Window{ + app.NewWebviewWindowWithOptions(&options.WebviewWindow{ Title: "Plain Bundle", HTML: `Plain Bundle

Plain Bundle

This is a plain bundle. It has no frontend code.

`, CSS: `body { background-color: rgba(255, 255, 255, 0); } .main { color: white; margin: 20%; }`, diff --git a/exp/examples/window/main.go b/exp/examples/window/main.go index df6e842e0..6a9f1f9c8 100644 --- a/exp/examples/window/main.go +++ b/exp/examples/window/main.go @@ -18,8 +18,8 @@ import ( func main() { app := application.New(options.Application{ - Name: "Window Demo", - Description: "A demo of the Window API", + Name: "WebviewWindow Demo", + Description: "A demo of the WebviewWindow API", Mac: options.Mac{ ApplicationShouldTerminateAfterLastWindowClosed: true, }, @@ -28,11 +28,11 @@ func main() { log.Println("ApplicationDidFinishLaunching") }) - currentWindow := func(fn func(window *application.Window)) { + currentWindow := func(fn func(window *application.WebviewWindow)) { if app.CurrentWindow() != nil { fn(app.CurrentWindow()) } else { - println("Current Window is nil") + println("Current WebviewWindow is nil") } } @@ -45,21 +45,21 @@ func main() { // Let's make a "Demo" menu myMenu := menu.AddSubmenu("New") - myMenu.Add("New Window"). + myMenu.Add("New WebviewWindow"). SetAccelerator("CmdOrCtrl+N"). OnClick(func(ctx *application.Context) { - app.NewWindow(). - SetTitle("Window "+strconv.Itoa(windowCounter)). + app.NewWebviewWindow(). + SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). SetPosition(rand.Intn(1000), rand.Intn(800)). SetURL("https://wails.io"). Show() windowCounter++ }) - myMenu.Add("New Frameless Window"). + myMenu.Add("New Frameless WebviewWindow"). SetAccelerator("CmdOrCtrl+F"). OnClick(func(ctx *application.Context) { - app.NewWindow(). - SetTitle("Window "+strconv.Itoa(windowCounter)). + app.NewWebviewWindow(). + SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). SetPosition(rand.Intn(1000), rand.Intn(800)). SetURL("https://wails.io"). SetFrameless(true). @@ -67,45 +67,45 @@ func main() { windowCounter++ }) if runtime.GOOS == "darwin" { - myMenu.Add("New Window (TitleBarHiddenInset)"). + myMenu.Add("New WebviewWindow (TitleBarHiddenInset)"). OnClick(func(ctx *application.Context) { - app.NewWindowWithOptions(&options.Window{ + app.NewWebviewWindowWithOptions(&options.WebviewWindow{ Mac: options.MacWindow{ TitleBar: options.TitleBarHiddenInset, InvisibleTitleBarHeight: 25, }, }). - SetTitle("Window "+strconv.Itoa(windowCounter)). + SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). SetPosition(rand.Intn(1000), rand.Intn(800)). - SetHTML("

A TitleBarHiddenInset Window example

"). + SetHTML("

A TitleBarHiddenInset WebviewWindow example

"). Show() windowCounter++ }) - myMenu.Add("New Window (TitleBarHiddenInsetUnified)"). + myMenu.Add("New WebviewWindow (TitleBarHiddenInsetUnified)"). OnClick(func(ctx *application.Context) { - app.NewWindowWithOptions(&options.Window{ + app.NewWebviewWindowWithOptions(&options.WebviewWindow{ Mac: options.MacWindow{ TitleBar: options.TitleBarHiddenInsetUnified, InvisibleTitleBarHeight: 50, }, }). - SetTitle("Window "+strconv.Itoa(windowCounter)). + SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). SetPosition(rand.Intn(1000), rand.Intn(800)). - SetHTML("

A TitleBarHiddenInsetUnified Window example

"). + SetHTML("

A TitleBarHiddenInsetUnified WebviewWindow example

"). Show() windowCounter++ }) - myMenu.Add("New Window (TitleBarHidden)"). + myMenu.Add("New WebviewWindow (TitleBarHidden)"). OnClick(func(ctx *application.Context) { - app.NewWindowWithOptions(&options.Window{ + app.NewWebviewWindowWithOptions(&options.WebviewWindow{ Mac: options.MacWindow{ TitleBar: options.TitleBarHidden, InvisibleTitleBarHeight: 25, }, }). - SetTitle("Window "+strconv.Itoa(windowCounter)). + SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). SetPosition(rand.Intn(1000), rand.Intn(800)). - SetHTML("

A TitleBarHidden Window example

"). + SetHTML("

A TitleBarHidden WebviewWindow example

"). Show() windowCounter++ }) @@ -113,122 +113,122 @@ func main() { sizeMenu := menu.AddSubmenu("Size") sizeMenu.Add("Set Size (800,600)").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { + currentWindow(func(w *application.WebviewWindow) { w.SetSize(800, 600) }) }) sizeMenu.Add("Set Size (Random)").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { + currentWindow(func(w *application.WebviewWindow) { w.SetSize(rand.Intn(800)+200, rand.Intn(600)+200) }) }) sizeMenu.Add("Set Min Size (200,200)").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { + currentWindow(func(w *application.WebviewWindow) { w.SetMinSize(200, 200) }) }) sizeMenu.Add("Set Max Size (600,600)").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { + currentWindow(func(w *application.WebviewWindow) { w.SetFullscreenButtonEnabled(false) w.SetMaxSize(600, 600) }) }) - sizeMenu.Add("Get Current Window Size").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { + sizeMenu.Add("Get Current WebviewWindow Size").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { width, height := w.Size() - app.NewInfoDialog().SetTitle("Current Window Size").SetMessage("Width: " + strconv.Itoa(width) + " Height: " + strconv.Itoa(height)).Show() + app.NewInfoDialog().SetTitle("Current WebviewWindow Size").SetMessage("Width: " + strconv.Itoa(width) + " Height: " + strconv.Itoa(height)).Show() }) }) sizeMenu.Add("Reset Min Size").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { + currentWindow(func(w *application.WebviewWindow) { w.SetMinSize(0, 0) }) }) sizeMenu.Add("Reset Max Size").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { + currentWindow(func(w *application.WebviewWindow) { w.SetMaxSize(0, 0) w.SetFullscreenButtonEnabled(true) }) }) positionMenu := menu.AddSubmenu("Position") positionMenu.Add("Set Position (0,0)").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { + currentWindow(func(w *application.WebviewWindow) { w.SetPosition(0, 0) }) }) positionMenu.Add("Set Position (Random)").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { + currentWindow(func(w *application.WebviewWindow) { w.SetPosition(rand.Intn(1000), rand.Intn(800)) }) }) positionMenu.Add("Get Position").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { + currentWindow(func(w *application.WebviewWindow) { x, y := w.Position() - app.NewInfoDialog().SetTitle("Current Window Position").SetMessage("X: " + strconv.Itoa(x) + " Y: " + strconv.Itoa(y)).Show() + app.NewInfoDialog().SetTitle("Current WebviewWindow Position").SetMessage("X: " + strconv.Itoa(x) + " Y: " + strconv.Itoa(y)).Show() }) }) positionMenu.Add("Center").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { + currentWindow(func(w *application.WebviewWindow) { w.Center() }) }) stateMenu := menu.AddSubmenu("State") stateMenu.Add("Minimise (for 2 secs)").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { + currentWindow(func(w *application.WebviewWindow) { w.Minimise() time.Sleep(2 * time.Second) w.Restore() }) }) stateMenu.Add("Maximise").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { + currentWindow(func(w *application.WebviewWindow) { w.Maximise() }) }) stateMenu.Add("Fullscreen").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { + currentWindow(func(w *application.WebviewWindow) { w.Fullscreen() }) }) stateMenu.Add("UnFullscreen").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { + currentWindow(func(w *application.WebviewWindow) { w.UnFullscreen() }) }) stateMenu.Add("Restore").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { + currentWindow(func(w *application.WebviewWindow) { w.Restore() }) }) stateMenu.Add("Hide (for 2 seconds)").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { + currentWindow(func(w *application.WebviewWindow) { w.Hide() time.Sleep(2 * time.Second) w.Show() }) }) stateMenu.Add("Always on Top").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { + currentWindow(func(w *application.WebviewWindow) { w.SetAlwaysOnTop(true) }) }) stateMenu.Add("Not always on Top").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { + currentWindow(func(w *application.WebviewWindow) { w.SetAlwaysOnTop(false) }) }) stateMenu.Add("Google.com").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { + currentWindow(func(w *application.WebviewWindow) { w.SetURL("https://google.com") }) }) stateMenu.Add("wails.io").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { + currentWindow(func(w *application.WebviewWindow) { w.SetURL("https://wails.io") }) }) @@ -252,8 +252,8 @@ func main() { app.NewInfoDialog().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show() } }) - stateMenu.Add("Get Screen for Window").OnClick(func(ctx *application.Context) { - currentWindow(func(w *application.Window) { + stateMenu.Add("Get Screen for WebviewWindow").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { screen, err := w.GetScreen() if err != nil { app.NewErrorDialog().SetTitle("Error").SetMessage(err.Error()).Show() @@ -263,7 +263,7 @@ func main() { app.NewInfoDialog().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show() }) }) - app.NewWindow() + app.NewWebviewWindow() app.SetMenu(menu) err := app.Run() diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index 43fb2125b..ce7d0fc0f 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -71,7 +71,7 @@ type App struct { applicationEventListenersLock sync.RWMutex // Windows - windows map[uint]*Window + windows map[uint]*WebviewWindow windowsLock sync.Mutex windowAliases map[string]uint windowAliasesLock sync.Mutex @@ -114,11 +114,11 @@ func (a *App) On(eventType events.ApplicationEventType, callback func()) { a.impl.on(eventID) } } -func (a *App) NewWindow() *Window { - return a.NewWindowWithOptions(nil) +func (a *App) NewWebviewWindow() *WebviewWindow { + return a.NewWebviewWindowWithOptions(nil) } -func (a *App) NewWindowWithOptions(windowOptions *options.Window) *Window { +func (a *App) NewWebviewWindowWithOptions(windowOptions *options.WebviewWindow) *WebviewWindow { // Ensure we have sane defaults if windowOptions == nil { windowOptions = options.WindowDefaults @@ -127,7 +127,7 @@ func (a *App) NewWindowWithOptions(windowOptions *options.Window) *Window { newWindow := NewWindow(windowOptions) id := newWindow.id if a.windows == nil { - a.windows = make(map[uint]*Window) + a.windows = make(map[uint]*WebviewWindow) } a.windowsLock.Lock() a.windows[id] = newWindow @@ -229,7 +229,7 @@ func (a *App) handleWindowMessage(event *windowMessage) { window, ok := a.windows[event.windowId] a.windowsLock.Unlock() if !ok { - log.Printf("Window #%d not found", event.windowId) + log.Printf("WebviewWindow #%d not found", event.windowId) return } // Get callback from window @@ -242,7 +242,7 @@ func (a *App) handleWindowEvent(event *WindowEvent) { window, ok := a.windows[event.WindowID] a.windowsLock.Unlock() if !ok { - log.Printf("Window #%d not found", event.WindowID) + log.Printf("WebviewWindow #%d not found", event.WindowID) return } window.handleWindowEvent(event.EventID) @@ -257,7 +257,7 @@ func (a *App) handleMenuItemClicked(menuItemID uint) { menuItem.handleClick() } -func (a *App) CurrentWindow() *Window { +func (a *App) CurrentWindow() *WebviewWindow { if a.impl == nil { return nil } diff --git a/exp/pkg/application/application_darwin.go b/exp/pkg/application/application_darwin.go index 12f739c87..44861d935 100644 --- a/exp/pkg/application/application_darwin.go +++ b/exp/pkg/application/application_darwin.go @@ -9,7 +9,7 @@ package application #include "application.h" #include "app_delegate.h" -#include "window_delegate.h" +#include "webview_window_delegate.h" #include extern void registerListener(unsigned int event); @@ -28,7 +28,7 @@ static void init(void) { if (eventWindow == nil ) { return event; } - WindowDelegate* windowDelegate = (WindowDelegate*)[eventWindow delegate]; + WebviewWindowDelegate* windowDelegate = (WebviewWindowDelegate*)[eventWindow delegate]; if (windowDelegate == nil) { return event; } @@ -43,7 +43,7 @@ static void init(void) { if (eventWindow == nil ) { return event; } - WindowDelegate* windowDelegate = (WindowDelegate*)[eventWindow delegate]; + WebviewWindowDelegate* windowDelegate = (WebviewWindowDelegate*)[eventWindow delegate]; if (windowDelegate == nil) { return event; } @@ -100,7 +100,7 @@ static char* getAppName(void) { static unsigned int getCurrentWindowID(void) { NSWindow *window = [NSApp keyWindow]; // Get the window delegate - WindowDelegate *delegate = (WindowDelegate*)[window delegate]; + WebviewWindowDelegate *delegate = (WebviewWindowDelegate*)[window delegate]; return delegate.windowId; } diff --git a/exp/pkg/application/dialogs.go b/exp/pkg/application/dialogs.go index bad3e6d66..c6c03e7bd 100644 --- a/exp/pkg/application/dialogs.go +++ b/exp/pkg/application/dialogs.go @@ -158,7 +158,7 @@ type OpenFileDialog struct { message string buttonText string directory string - window *Window + window *WebviewWindow impl openFileDialogImpl } @@ -198,7 +198,7 @@ func (d *OpenFileDialog) TreatsFilePackagesAsDirectories(treatsFilePackagesAsDir return d } -func (d *OpenFileDialog) AttachToWindow(window *Window) *OpenFileDialog { +func (d *OpenFileDialog) AttachToWindow(window *WebviewWindow) *OpenFileDialog { d.window = window return d } @@ -295,7 +295,7 @@ type SaveFileDialog struct { filename string buttonText string - window *Window + window *WebviewWindow impl saveFileDialogImpl } @@ -329,7 +329,7 @@ func (d *SaveFileDialog) SetDirectory(directory string) *SaveFileDialog { return d } -func (d *SaveFileDialog) AttachToWindow(window *Window) *SaveFileDialog { +func (d *SaveFileDialog) AttachToWindow(window *WebviewWindow) *SaveFileDialog { d.window = window return d } diff --git a/exp/pkg/application/dialogs_darwin.go b/exp/pkg/application/dialogs_darwin.go index 717465095..640bf6bfb 100644 --- a/exp/pkg/application/dialogs_darwin.go +++ b/exp/pkg/application/dialogs_darwin.go @@ -400,7 +400,7 @@ func (m *macosOpenFileDialog) show() ([]string, error) { nsWindow := unsafe.Pointer(nil) if m.dialog.window != nil { // get NSWindow from window - nsWindow = m.dialog.window.impl.(*macosWindow).nsWindow + nsWindow = m.dialog.window.impl.(*macosWebviewWindow).nsWindow } // Massage filter patterns into macOS format @@ -484,7 +484,7 @@ func (m *macosSaveFileDialog) show() (string, error) { nsWindow := unsafe.Pointer(nil) if m.dialog.window != nil { // get NSWindow from window - nsWindow = m.dialog.window.impl.(*macosWindow).nsWindow + nsWindow = m.dialog.window.impl.(*macosWebviewWindow).nsWindow } C.showSaveFileDialog(C.uint(m.dialog.id), C.bool(m.dialog.canCreateDirectories), diff --git a/exp/pkg/application/roles.go b/exp/pkg/application/roles.go index 0aec3bd48..c16633327 100644 --- a/exp/pkg/application/roles.go +++ b/exp/pkg/application/roles.go @@ -132,7 +132,7 @@ func newWindowMenu() *MenuItem { menu := NewMenu() menu.AddRole(Minimize) menu.AddRole(Zoom) - subMenu := newSubMenuItem("Window") + subMenu := newSubMenuItem("WebviewWindow") subMenu.submenu = menu return subMenu } diff --git a/exp/pkg/application/screen_darwin.go b/exp/pkg/application/screen_darwin.go index 8ca6ca15b..d45753f7b 100644 --- a/exp/pkg/application/screen_darwin.go +++ b/exp/pkg/application/screen_darwin.go @@ -145,7 +145,7 @@ func getScreens() ([]*Screen, error) { return displays, nil } -func getScreenForWindow(window *macosWindow) (*Screen, error) { +func getScreenForWindow(window *macosWebviewWindow) (*Screen, error) { cScreen := C.getScreenForWindow(window.nsWindow) return cScreenToScreen(cScreen), nil } diff --git a/exp/pkg/application/window.go b/exp/pkg/application/webview_window.go similarity index 74% rename from exp/pkg/application/window.go rename to exp/pkg/application/webview_window.go index 988dc0be3..6e6849830 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/webview_window.go @@ -9,7 +9,7 @@ import ( ) type ( - windowImpl interface { + webviewWindowImpl interface { setTitle(title string) setSize(width, height int) setAlwaysOnTop(alwaysOnTop bool) @@ -57,9 +57,9 @@ type ( } ) -type Window struct { - options *options.Window - impl windowImpl +type WebviewWindow struct { + options *options.WebviewWindow + impl webviewWindowImpl implLock sync.RWMutex id uint @@ -77,21 +77,21 @@ func getWindowID() uint { return windowID } -func NewWindow(options *options.Window) *Window { +func NewWindow(options *options.WebviewWindow) *WebviewWindow { if options.Width == 0 { options.Width = 800 } if options.Height == 0 { options.Height = 600 } - return &Window{ + return &WebviewWindow{ id: getWindowID(), options: options, eventListeners: make(map[uint][]func()), } } -func (w *Window) SetTitle(title string) *Window { +func (w *WebviewWindow) SetTitle(title string) *WebviewWindow { w.implLock.RLock() defer w.implLock.RUnlock() w.options.Title = title @@ -101,7 +101,7 @@ func (w *Window) SetTitle(title string) *Window { return w } -func (w *Window) SetSize(width, height int) *Window { +func (w *WebviewWindow) SetSize(width, height int) *WebviewWindow { // Don't set size if fullscreen if w.IsFullscreen() { return w @@ -141,7 +141,7 @@ func (w *Window) SetSize(width, height int) *Window { return w } -func (w *Window) run() { +func (w *WebviewWindow) run() { if w.impl != nil { return } @@ -151,7 +151,7 @@ func (w *Window) run() { w.impl.run() } -func (w *Window) SetAlwaysOnTop(b bool) *Window { +func (w *WebviewWindow) SetAlwaysOnTop(b bool) *WebviewWindow { w.options.AlwaysOnTop = b if w.impl == nil { w.impl.setAlwaysOnTop(b) @@ -159,7 +159,7 @@ func (w *Window) SetAlwaysOnTop(b bool) *Window { return w } -func (w *Window) Show() *Window { +func (w *WebviewWindow) Show() *WebviewWindow { if w.impl == nil { w.run() return w @@ -167,7 +167,7 @@ func (w *Window) Show() *Window { w.impl.show() return w } -func (w *Window) Hide() *Window { +func (w *WebviewWindow) Hide() *WebviewWindow { w.options.Hidden = true if w.impl != nil { w.impl.hide() @@ -175,7 +175,7 @@ func (w *Window) Hide() *Window { return w } -func (w *Window) SetURL(s string) *Window { +func (w *WebviewWindow) SetURL(s string) *WebviewWindow { w.options.URL = s if w.impl != nil { w.impl.setURL(s) @@ -183,7 +183,7 @@ func (w *Window) SetURL(s string) *Window { return w } -func (w *Window) SetResizable(b bool) *Window { +func (w *WebviewWindow) SetResizable(b bool) *WebviewWindow { w.options.DisableResize = !b if w.impl != nil { w.impl.setResizable(b) @@ -191,11 +191,11 @@ func (w *Window) SetResizable(b bool) *Window { return w } -func (w *Window) Resizable() bool { +func (w *WebviewWindow) Resizable() bool { return !w.options.DisableResize } -func (w *Window) SetMinSize(minWidth, minHeight int) *Window { +func (w *WebviewWindow) SetMinSize(minWidth, minHeight int) *WebviewWindow { w.options.MinWidth = minWidth w.options.MinHeight = minHeight @@ -222,7 +222,7 @@ func (w *Window) SetMinSize(minWidth, minHeight int) *Window { return w } -func (w *Window) SetMaxSize(maxWidth, maxHeight int) *Window { +func (w *WebviewWindow) SetMaxSize(maxWidth, maxHeight int) *WebviewWindow { w.options.MaxWidth = maxWidth w.options.MaxHeight = maxHeight @@ -249,14 +249,14 @@ func (w *Window) SetMaxSize(maxWidth, maxHeight int) *Window { return w } -func (w *Window) ExecJS(js string) { +func (w *WebviewWindow) ExecJS(js string) { if w.impl == nil { return } w.impl.execJS(js) } -func (w *Window) Fullscreen() *Window { +func (w *WebviewWindow) Fullscreen() *WebviewWindow { if w.impl == nil { w.options.StartState = options.WindowStateFullscreen return w @@ -268,7 +268,7 @@ func (w *Window) Fullscreen() *Window { return w } -func (w *Window) SetFullscreenButtonEnabled(enabled bool) *Window { +func (w *WebviewWindow) SetFullscreenButtonEnabled(enabled bool) *WebviewWindow { w.options.FullscreenButtonEnabled = enabled if w.impl != nil { w.impl.setFullscreenButtonEnabled(enabled) @@ -277,7 +277,7 @@ func (w *Window) SetFullscreenButtonEnabled(enabled bool) *Window { } // IsMinimised returns true if the window is minimised -func (w *Window) IsMinimised() bool { +func (w *WebviewWindow) IsMinimised() bool { if w.impl == nil { return false } @@ -285,7 +285,7 @@ func (w *Window) IsMinimised() bool { } // IsMaximised returns true if the window is maximised -func (w *Window) IsMaximised() bool { +func (w *WebviewWindow) IsMaximised() bool { if w.impl == nil { return false } @@ -293,7 +293,7 @@ func (w *Window) IsMaximised() bool { } // Size returns the size of the window -func (w *Window) Size() (width int, height int) { +func (w *WebviewWindow) Size() (width int, height int) { if w.impl == nil { return 0, 0 } @@ -301,7 +301,7 @@ func (w *Window) Size() (width int, height int) { } // IsFullscreen returns true if the window is fullscreen -func (w *Window) IsFullscreen() bool { +func (w *WebviewWindow) IsFullscreen() bool { w.implLock.RLock() defer w.implLock.RUnlock() if w.impl == nil { @@ -310,7 +310,7 @@ func (w *Window) IsFullscreen() bool { return w.impl.isFullscreen() } -func (w *Window) SetBackgroundColour(colour *options.RGBA) *Window { +func (w *WebviewWindow) SetBackgroundColour(colour *options.RGBA) *WebviewWindow { w.options.BackgroundColour = colour if w.impl != nil { w.impl.setBackgroundColour(colour) @@ -318,7 +318,7 @@ func (w *Window) SetBackgroundColour(colour *options.RGBA) *Window { return w } -func (w *Window) handleMessage(message string) { +func (w *WebviewWindow) handleMessage(message string) { fmt.Printf("[window %d] %s", w.id, message) // Check for special messages if message == "test" { @@ -326,14 +326,14 @@ func (w *Window) handleMessage(message string) { } } -func (w *Window) Center() { +func (w *WebviewWindow) Center() { if w.impl == nil { return } w.impl.center() } -func (w *Window) On(eventType events.WindowEventType, callback func()) { +func (w *WebviewWindow) On(eventType events.WindowEventType, callback func()) { eventID := uint(eventType) w.eventListenersLock.Lock() defer w.eventListenersLock.Unlock() @@ -343,7 +343,7 @@ func (w *Window) On(eventType events.WindowEventType, callback func()) { } } -func (w *Window) handleWindowEvent(id uint) { +func (w *WebviewWindow) handleWindowEvent(id uint) { w.eventListenersLock.RLock() for _, callback := range w.eventListeners[id] { go callback() @@ -351,21 +351,21 @@ func (w *Window) handleWindowEvent(id uint) { w.eventListenersLock.RUnlock() } -func (w *Window) Width() int { +func (w *WebviewWindow) Width() int { if w.impl == nil { return 0 } return w.impl.width() } -func (w *Window) Height() int { +func (w *WebviewWindow) Height() int { if w.impl == nil { return 0 } return w.impl.height() } -func (w *Window) Position() (int, int) { +func (w *WebviewWindow) Position() (int, int) { w.implLock.RLock() defer w.implLock.RUnlock() if w.impl == nil { @@ -374,28 +374,28 @@ func (w *Window) Position() (int, int) { return w.impl.position() } -func (w *Window) Destroy() { +func (w *WebviewWindow) Destroy() { if w.impl == nil { return } w.impl.destroy() } -func (w *Window) Reload() { +func (w *WebviewWindow) Reload() { if w.impl == nil { return } w.impl.reload() } -func (w *Window) ForceReload() { +func (w *WebviewWindow) ForceReload() { if w.impl == nil { return } w.impl.forceReload() } -func (w *Window) ToggleFullscreen() { +func (w *WebviewWindow) ToggleFullscreen() { if w.impl == nil { return } @@ -406,14 +406,14 @@ func (w *Window) ToggleFullscreen() { } } -func (w *Window) ToggleDevTools() { +func (w *WebviewWindow) ToggleDevTools() { if w.impl == nil { return } w.impl.toggleDevTools() } -func (w *Window) ResetZoom() *Window { +func (w *WebviewWindow) ResetZoom() *WebviewWindow { if w.impl != nil { w.impl.resetZoom() } @@ -421,42 +421,42 @@ func (w *Window) ResetZoom() *Window { } -func (w *Window) ZoomIn() { +func (w *WebviewWindow) ZoomIn() { if w.impl == nil { return } w.impl.zoomIn() } -func (w *Window) ZoomOut() { +func (w *WebviewWindow) ZoomOut() { if w.impl == nil { return } w.impl.zoomOut() } -func (w *Window) Close() { +func (w *WebviewWindow) Close() { if w.impl == nil { return } w.impl.close() } -func (w *Window) Minimize() { +func (w *WebviewWindow) Minimize() { if w.impl == nil { return } w.impl.minimize() } -func (w *Window) Zoom() { +func (w *WebviewWindow) Zoom() { if w.impl == nil { return } w.impl.zoom() } -func (w *Window) SetHTML(html string) *Window { +func (w *WebviewWindow) SetHTML(html string) *WebviewWindow { w.options.HTML = html if w.impl != nil { w.impl.setHTML(html) @@ -464,7 +464,7 @@ func (w *Window) SetHTML(html string) *Window { return w } -func (w *Window) SetPosition(x, y int) *Window { +func (w *WebviewWindow) SetPosition(x, y int) *WebviewWindow { w.options.X = x w.options.Y = y if w.impl != nil { @@ -473,7 +473,7 @@ func (w *Window) SetPosition(x, y int) *Window { return w } -func (w *Window) Minimise() *Window { +func (w *WebviewWindow) Minimise() *WebviewWindow { if w.impl == nil { w.options.StartState = options.WindowStateMinimised return w @@ -484,7 +484,7 @@ func (w *Window) Minimise() *Window { return w } -func (w *Window) Maximise() *Window { +func (w *WebviewWindow) Maximise() *WebviewWindow { if w.impl == nil { w.options.StartState = options.WindowStateMaximised return w @@ -496,14 +496,14 @@ func (w *Window) Maximise() *Window { return w } -func (w *Window) UnMinimise() { +func (w *WebviewWindow) UnMinimise() { if w.impl == nil { return } w.impl.unminimise() } -func (w *Window) UnMaximise() { +func (w *WebviewWindow) UnMaximise() { if w.impl == nil { return } @@ -511,7 +511,7 @@ func (w *Window) UnMaximise() { w.impl.unmaximise() } -func (w *Window) UnFullscreen() { +func (w *WebviewWindow) UnFullscreen() { if w.impl == nil { return } @@ -519,7 +519,7 @@ func (w *Window) UnFullscreen() { w.impl.unfullscreen() } -func (w *Window) Restore() { +func (w *WebviewWindow) Restore() { if w.impl == nil { return } @@ -532,7 +532,7 @@ func (w *Window) Restore() { } } -func (w *Window) disableSizeConstraints() { +func (w *WebviewWindow) disableSizeConstraints() { if w.impl == nil { return } @@ -540,7 +540,7 @@ func (w *Window) disableSizeConstraints() { w.impl.setMaxSize(0, 0) } -func (w *Window) enableSizeConstraints() { +func (w *WebviewWindow) enableSizeConstraints() { if w.impl == nil { return } @@ -548,14 +548,14 @@ func (w *Window) enableSizeConstraints() { w.SetMaxSize(w.options.MaxWidth, w.options.MaxHeight) } -func (w *Window) GetScreen() (*Screen, error) { +func (w *WebviewWindow) GetScreen() (*Screen, error) { if w.impl == nil { return nil, nil } return w.impl.getScreen() } -func (w *Window) SetFrameless(frameless bool) *Window { +func (w *WebviewWindow) SetFrameless(frameless bool) *WebviewWindow { w.options.Frameless = frameless if w.impl != nil { w.impl.setFrameless(frameless) diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/webview_window_darwin.go similarity index 86% rename from exp/pkg/application/window_darwin.go rename to exp/pkg/application/webview_window_darwin.go index 05ff4ddeb..b2a153e84 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/webview_window_darwin.go @@ -7,7 +7,7 @@ package application #cgo LDFLAGS: -framework Cocoa -framework WebKit #include "application.h" -#include "window_delegate.h" +#include "webview_window_delegate.h" #include #include "Cocoa/Cocoa.h" #import @@ -23,7 +23,7 @@ void* windowNew(unsigned int id, int width, int height) { defer:NO]; // Create delegate - WindowDelegate* delegate = [[WindowDelegate alloc] init]; + WebviewWindowDelegate* delegate = [[WebviewWindowDelegate alloc] init]; // Set delegate [window setDelegate:delegate]; delegate.windowId = id; @@ -62,7 +62,7 @@ void* windowNew(unsigned int id, int width, int height) { void setInvisibleTitleBarHeight(void* window, unsigned int height) { NSWindow* nsWindow = (NSWindow*)window; // Get delegate - WindowDelegate* delegate = (WindowDelegate*)[nsWindow delegate]; + WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[nsWindow delegate]; // Set height delegate.invisibleTitleBarHeight = height; } @@ -82,7 +82,7 @@ void windowSetInvisibleTitleBar(void* nsWindow, unsigned int height) { dispatch_async(dispatch_get_main_queue(), ^{ NSWindow* window = (NSWindow*)nsWindow; // Get delegate - WindowDelegate* delegate = (WindowDelegate*)[window delegate]; + WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[window delegate]; // Set height delegate.invisibleTitleBarHeight = height; }); @@ -124,7 +124,7 @@ void navigationLoadURL(void* nsWindow, char* url) { dispatch_async(dispatch_get_main_queue(), ^{ NSURL* nsURL = [NSURL URLWithString:[NSString stringWithUTF8String:url]]; NSURLRequest* request = [NSURLRequest requestWithURL:nsURL]; - [[(WindowDelegate*)[(NSWindow*)nsWindow delegate] webView] loadRequest:request]; + [[(WebviewWindowDelegate*)[(NSWindow*)nsWindow delegate] webView] loadRequest:request]; free(url); }); } @@ -173,7 +173,7 @@ void windowEnableDevTools(void* nsWindow) { // Enable devtools on main thread dispatch_async(dispatch_get_main_queue(), ^{ // Get window delegate - WindowDelegate* delegate = (WindowDelegate*)[(NSWindow*)nsWindow delegate]; + WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(NSWindow*)nsWindow delegate]; // Enable devtools in webview [delegate.webView.configuration.preferences setValue:@YES forKey:@"developerExtrasEnabled"]; }); @@ -184,7 +184,7 @@ void windowResetZoom(void* nsWindow) { // Reset zoom on main thread dispatch_async(dispatch_get_main_queue(), ^{ // Get window delegate - WindowDelegate* delegate = (WindowDelegate*)[(NSWindow*)nsWindow delegate]; + WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(NSWindow*)nsWindow delegate]; // Reset zoom [delegate.webView setMagnification:1.0]; }); @@ -195,7 +195,7 @@ void windowZoomIn(void* nsWindow) { // Zoom in on main thread dispatch_async(dispatch_get_main_queue(), ^{ // Get window delegate - WindowDelegate* delegate = (WindowDelegate*)[(NSWindow*)nsWindow delegate]; + WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(NSWindow*)nsWindow delegate]; // Zoom in [delegate.webView setMagnification:delegate.webView.magnification + 0.05]; }); @@ -206,7 +206,7 @@ void windowZoomOut(void* nsWindow) { // Zoom out on main thread dispatch_async(dispatch_get_main_queue(), ^{ // Get window delegate - WindowDelegate* delegate = (WindowDelegate*)[(NSWindow*)nsWindow delegate]; + WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(NSWindow*)nsWindow delegate]; // Zoom out if( delegate.webView.magnification > 1.05 ) { [delegate.webView setMagnification:delegate.webView.magnification - 0.05]; @@ -228,7 +228,7 @@ void windowSetPosition(void* nsWindow, int x, int y) { void windowExecJS(void* nsWindow, const char* js) { // Execute JS on main thread dispatch_async(dispatch_get_main_queue(), ^{ - WindowDelegate* delegate = (WindowDelegate*)[(NSWindow*)nsWindow delegate]; + WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(NSWindow*)nsWindow delegate]; [delegate.webView evaluateJavaScript:[NSString stringWithUTF8String:js] completionHandler:nil]; free((void*)js); }); @@ -243,7 +243,7 @@ void windowSetTranslucent(void* nsWindow) { NSWindow* window = (NSWindow*)nsWindow; // Get window delegate - WindowDelegate* delegate = (WindowDelegate*)[(NSWindow*)nsWindow delegate]; + WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(NSWindow*)nsWindow delegate]; id contentView = [window contentView]; NSVisualEffectView *effectView = [NSVisualEffectView alloc]; @@ -261,7 +261,7 @@ void webviewSetTransparent(void* nsWindow) { // Set webview transparent on main thread dispatch_async(dispatch_get_main_queue(), ^{ // Get window delegate - WindowDelegate* delegate = (WindowDelegate*)[(NSWindow*)nsWindow delegate]; + WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(NSWindow*)nsWindow delegate]; // Set webview background transparent [delegate.webView setValue:@NO forKey:@"drawsBackground"]; }); @@ -272,7 +272,7 @@ void webviewSetBackgroundColour(void* nsWindow, int r, int g, int b, int alpha) // Set webview background color on main thread dispatch_async(dispatch_get_main_queue(), ^{ // Get window delegate - WindowDelegate* delegate = (WindowDelegate*)[(NSWindow*)nsWindow delegate]; + WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(NSWindow*)nsWindow delegate]; // Set webview background color [delegate.webView setValue:[NSColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:alpha/255.0] forKey:@"backgroundColor"]; }); @@ -566,7 +566,7 @@ static void windowRenderHTML(void *window, const char *html) { // get main window NSWindow* nsWindow = (NSWindow*)window; // get window delegate - WindowDelegate* windowDelegate = (WindowDelegate*)[nsWindow delegate]; + WebviewWindowDelegate* windowDelegate = (WebviewWindowDelegate*)[nsWindow delegate]; // render html [(WKWebView*)windowDelegate.webView loadHTMLString:[NSString stringWithUTF8String:html] baseURL:nil]; }); @@ -577,7 +577,7 @@ static void windowInjectCSS(void *window, const char *css) { // get main window NSWindow* nsWindow = (NSWindow*)window; // get window delegate - WindowDelegate* windowDelegate = (WindowDelegate*)[nsWindow delegate]; + WebviewWindowDelegate* windowDelegate = (WebviewWindowDelegate*)[nsWindow delegate]; // inject css [(WKWebView*)windowDelegate.webView evaluateJavaScript:[NSString stringWithFormat:@"(function() { var style = document.createElement('style'); style.appendChild(document.createTextNode('%@')); document.head.appendChild(style); })();", [NSString stringWithUTF8String:css]] completionHandler:nil]; free((void*)css); @@ -685,12 +685,12 @@ import ( var showDevTools = func(window unsafe.Pointer) {} -type macosWindow struct { +type macosWebviewWindow struct { nsWindow unsafe.Pointer - parent *Window + parent *WebviewWindow } -func (w *macosWindow) setFrameless(frameless bool) { +func (w *macosWebviewWindow) setFrameless(frameless bool) { C.windowSetFrameless(w.nsWindow, C.bool(frameless)) if frameless { C.windowSetTitleBarAppearsTransparent(w.nsWindow, C.bool(true)) @@ -704,119 +704,119 @@ func (w *macosWindow) setFrameless(frameless bool) { } } -func (w *macosWindow) getScreen() (*Screen, error) { +func (w *macosWebviewWindow) getScreen() (*Screen, error) { return getScreenForWindow(w) } -func (w *macosWindow) show() { +func (w *macosWebviewWindow) show() { C.windowShow(w.nsWindow) } -func (w *macosWindow) hide() { +func (w *macosWebviewWindow) hide() { C.windowHide(w.nsWindow) } -func (w *macosWindow) setFullscreenButtonEnabled(enabled bool) { +func (w *macosWebviewWindow) setFullscreenButtonEnabled(enabled bool) { C.setFullscreenButtonEnabled(w.nsWindow, C.bool(enabled)) } -func (w *macosWindow) disableSizeConstraints() { +func (w *macosWebviewWindow) disableSizeConstraints() { C.windowDisableSizeConstraints(w.nsWindow) } -func (w *macosWindow) unfullscreen() { +func (w *macosWebviewWindow) unfullscreen() { C.windowUnFullscreen(w.nsWindow) } -func (w *macosWindow) fullscreen() { +func (w *macosWebviewWindow) fullscreen() { C.windowFullscreen(w.nsWindow) } -func (w *macosWindow) unminimise() { +func (w *macosWebviewWindow) unminimise() { C.windowUnminimise(w.nsWindow) } -func (w *macosWindow) unmaximise() { +func (w *macosWebviewWindow) unmaximise() { C.windowUnmaximise(w.nsWindow) } -func (w *macosWindow) maximise() { +func (w *macosWebviewWindow) maximise() { C.windowMaximise(w.nsWindow) } -func (w *macosWindow) minimise() { +func (w *macosWebviewWindow) minimise() { C.windowMinimise(w.nsWindow) } -func (w *macosWindow) on(eventID uint) { +func (w *macosWebviewWindow) on(eventID uint) { C.registerListener(C.uint(eventID)) } -func (w *macosWindow) zoom() { +func (w *macosWebviewWindow) zoom() { C.windowZoom(w.nsWindow) } -func (w *macosWindow) minimize() { +func (w *macosWebviewWindow) minimize() { C.windowMiniaturize(w.nsWindow) } -func (w *macosWindow) windowZoom() { +func (w *macosWebviewWindow) windowZoom() { C.windowZoom(w.nsWindow) } -func (w *macosWindow) close() { +func (w *macosWebviewWindow) close() { C.windowClose(w.nsWindow) } -func (w *macosWindow) zoomIn() { +func (w *macosWebviewWindow) zoomIn() { C.windowZoomIn(w.nsWindow) } -func (w *macosWindow) zoomOut() { +func (w *macosWebviewWindow) zoomOut() { C.windowZoomOut(w.nsWindow) } -func (w *macosWindow) resetZoom() { +func (w *macosWebviewWindow) resetZoom() { C.windowResetZoom(w.nsWindow) } -func (w *macosWindow) toggleDevTools() { +func (w *macosWebviewWindow) toggleDevTools() { showDevTools(w.nsWindow) } -func (w *macosWindow) reload() { +func (w *macosWebviewWindow) reload() { //TODO: Implement - println("reload called on Window", w.parent.id) + println("reload called on WebviewWindow", w.parent.id) } -func (w *macosWindow) forceReload() { +func (w *macosWebviewWindow) forceReload() { //TODO: Implement - println("forceReload called on Window", w.parent.id) + println("forceReload called on WebviewWindow", w.parent.id) } -func (w *macosWindow) center() { +func (w *macosWebviewWindow) center() { C.windowCenter(w.nsWindow) } -func (w *macosWindow) isMinimised() bool { +func (w *macosWebviewWindow) isMinimised() bool { return w.syncMainThreadReturningBool(func() bool { return bool(C.windowIsMinimised(w.nsWindow)) }) } -func (w *macosWindow) isMaximised() bool { +func (w *macosWebviewWindow) isMaximised() bool { return w.syncMainThreadReturningBool(func() bool { return bool(C.windowIsMaximised(w.nsWindow)) }) } -func (w *macosWindow) isFullscreen() bool { +func (w *macosWebviewWindow) isFullscreen() bool { return w.syncMainThreadReturningBool(func() bool { return bool(C.windowIsFullscreen(w.nsWindow)) }) } -func (w *macosWindow) syncMainThreadReturningBool(fn func() bool) bool { +func (w *macosWebviewWindow) syncMainThreadReturningBool(fn func() bool) bool { var wg sync.WaitGroup wg.Add(1) var result bool @@ -828,59 +828,59 @@ func (w *macosWindow) syncMainThreadReturningBool(fn func() bool) bool { return result } -func (w *macosWindow) restore() { +func (w *macosWebviewWindow) restore() { // restore window to normal size C.windowRestore(w.nsWindow) } -func (w *macosWindow) restoreWindow() { +func (w *macosWebviewWindow) restoreWindow() { C.windowRestore(w.nsWindow) } -func (w *macosWindow) execJS(js string) { - println("execJS called on Window", w.parent.id) +func (w *macosWebviewWindow) execJS(js string) { + println("execJS called on WebviewWindow", w.parent.id) C.windowExecJS(w.nsWindow, C.CString(js)) } -func (w *macosWindow) setURL(url string) { +func (w *macosWebviewWindow) setURL(url string) { C.navigationLoadURL(w.nsWindow, C.CString(url)) } -func (w *macosWindow) setAlwaysOnTop(alwaysOnTop bool) { +func (w *macosWebviewWindow) setAlwaysOnTop(alwaysOnTop bool) { C.windowSetAlwaysOnTop(w.nsWindow, C.bool(alwaysOnTop)) } -func newWindowImpl(parent *Window) *macosWindow { - result := &macosWindow{ +func newWindowImpl(parent *WebviewWindow) *macosWebviewWindow { + result := &macosWebviewWindow{ parent: parent, } return result } -func (w *macosWindow) setTitle(title string) { +func (w *macosWebviewWindow) setTitle(title string) { cTitle := C.CString(title) C.windowSetTitle(w.nsWindow, cTitle) } -func (w *macosWindow) setSize(width, height int) { +func (w *macosWebviewWindow) setSize(width, height int) { C.windowSetSize(w.nsWindow, C.int(width), C.int(height)) } -func (w *macosWindow) setMinSize(width, height int) { +func (w *macosWebviewWindow) setMinSize(width, height int) { C.windowSetMinSize(w.nsWindow, C.int(width), C.int(height)) } -func (w *macosWindow) setMaxSize(width, height int) { +func (w *macosWebviewWindow) setMaxSize(width, height int) { C.windowSetMaxSize(w.nsWindow, C.int(width), C.int(height)) } -func (w *macosWindow) setResizable(resizable bool) { +func (w *macosWebviewWindow) setResizable(resizable bool) { C.windowSetResizable(w.nsWindow, C.bool(resizable)) } -func (w *macosWindow) enableDevTools() { +func (w *macosWebviewWindow) enableDevTools() { C.windowEnableDevTools(w.nsWindow) } -func (w *macosWindow) size() (int, int) { +func (w *macosWebviewWindow) size() (int, int) { var width, height C.int var wg sync.WaitGroup wg.Add(1) @@ -892,11 +892,11 @@ func (w *macosWindow) size() (int, int) { return int(width), int(height) } -func (w *macosWindow) setPosition(x, y int) { +func (w *macosWebviewWindow) setPosition(x, y int) { C.windowSetPosition(w.nsWindow, C.int(x), C.int(y)) } -func (w *macosWindow) width() int { +func (w *macosWebviewWindow) width() int { var width C.int var wg sync.WaitGroup wg.Add(1) @@ -907,7 +907,7 @@ func (w *macosWindow) width() int { wg.Wait() return int(width) } -func (w *macosWindow) height() int { +func (w *macosWebviewWindow) height() int { var height C.int var wg sync.WaitGroup wg.Add(1) @@ -919,7 +919,7 @@ func (w *macosWindow) height() int { return int(height) } -func (w *macosWindow) run() { +func (w *macosWebviewWindow) run() { for eventId := range w.parent.eventListeners { w.on(eventId) } @@ -998,14 +998,14 @@ func (w *macosWindow) run() { }) } -func (w *macosWindow) setBackgroundColour(colour *options.RGBA) { +func (w *macosWebviewWindow) setBackgroundColour(colour *options.RGBA) { if colour == nil { return } C.windowSetBackgroundColour(w.nsWindow, C.int(colour.Red), C.int(colour.Green), C.int(colour.Blue), C.int(colour.Alpha)) } -func (w *macosWindow) position() (int, int) { +func (w *macosWebviewWindow) position() (int, int) { var x, y C.int var wg sync.WaitGroup wg.Add(1) @@ -1017,11 +1017,11 @@ func (w *macosWindow) position() (int, int) { return int(x), int(y) } -func (w *macosWindow) destroy() { +func (w *macosWebviewWindow) destroy() { C.windowDestroy(w.nsWindow) } -func (w *macosWindow) setHTML(html string) { +func (w *macosWebviewWindow) setHTML(html string) { // Convert HTML to C string cHTML := C.CString(html) // Render HTML diff --git a/exp/pkg/application/window_delegate.h b/exp/pkg/application/webview_window_delegate.h similarity index 63% rename from exp/pkg/application/window_delegate.h rename to exp/pkg/application/webview_window_delegate.h index 71baebef9..f0546116e 100644 --- a/exp/pkg/application/window_delegate.h +++ b/exp/pkg/application/webview_window_delegate.h @@ -1,12 +1,12 @@ //go:build darwin -#ifndef WindowDelegate_h -#define WindowDelegate_h +#ifndef WebviewWindowDelegate_h +#define WebviewWindowDelegate_h #import #import -@interface WindowDelegate : NSObject +@interface WebviewWindowDelegate : NSObject @property bool hideOnClose; @property (retain) WKWebView* webView; @@ -20,4 +20,4 @@ @end -#endif /* WindowDelegate_h */ +#endif /* WebviewWindowDelegate_h */ diff --git a/exp/pkg/application/window_delegate.m b/exp/pkg/application/webview_window_delegate.m similarity index 99% rename from exp/pkg/application/window_delegate.m rename to exp/pkg/application/webview_window_delegate.m index e9be47f51..bf5040fa8 100644 --- a/exp/pkg/application/window_delegate.m +++ b/exp/pkg/application/webview_window_delegate.m @@ -2,13 +2,13 @@ #import #import -#import "window_delegate.h" +#import "webview_window_delegate.h" #import "../events/events.h" extern void processMessage(unsigned int, const char*); extern bool hasListeners(unsigned int); -@implementation WindowDelegate +@implementation WebviewWindowDelegate - (BOOL)windowShouldClose:(NSWindow *)sender { if( self.hideOnClose ) { @@ -39,7 +39,7 @@ extern bool hasListeners(unsigned int); - (void)handleLeftMouseDown:(NSEvent *)event { self.leftMouseEvent = event; NSWindow *window = [event window]; - WindowDelegate* delegate = (WindowDelegate*)[window delegate]; + WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[window delegate]; if( self.invisibleTitleBarHeight > 0 ) { NSPoint location = [event locationInWindow]; NSRect frame = [window frame]; diff --git a/exp/pkg/application/window_devtools.go b/exp/pkg/application/webview_window_devtools.go similarity index 82% rename from exp/pkg/application/window_devtools.go rename to exp/pkg/application/webview_window_devtools.go index d73e0c3b3..f1121384b 100644 --- a/exp/pkg/application/window_devtools.go +++ b/exp/pkg/application/webview_window_devtools.go @@ -8,7 +8,7 @@ package application #import -#include "window_delegate.h" +#include "webview_window_delegate.h" @interface _WKInspector : NSObject - (void)show; @@ -21,7 +21,7 @@ package application void showDevTools(void *window) { // Get the window delegate - WindowDelegate* delegate = (WindowDelegate*)[(NSWindow*)window delegate]; + WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(NSWindow*)window delegate]; dispatch_async(dispatch_get_main_queue(), ^{ [delegate.webView._inspector show]; }); diff --git a/exp/pkg/options/window.go b/exp/pkg/options/window.go index 47e8591c1..e1ef9f558 100644 --- a/exp/pkg/options/window.go +++ b/exp/pkg/options/window.go @@ -14,7 +14,7 @@ const ( WindowStateFullscreen ) -type Window struct { +type WebviewWindow struct { // Alias is a human-readable name for the window. This can be used to reference the window in the frontend. Alias string Title string @@ -40,7 +40,7 @@ type Window struct { Hidden bool } -var WindowDefaults = &Window{ +var WindowDefaults = &WebviewWindow{ Title: "", Width: 800, Height: 600, diff --git a/v2/examples/systray/main.go b/v2/examples/systray/main.go index d675ec4d1..f55ff91ec 100644 --- a/v2/examples/systray/main.go +++ b/v2/examples/systray/main.go @@ -4,12 +4,13 @@ import ( "context" "embed" "fmt" + "time" + "github.com/wailsapp/wails/v2/pkg/application" "github.com/wailsapp/wails/v2/pkg/menu" "github.com/wailsapp/wails/v2/pkg/options" "github.com/wailsapp/wails/v2/pkg/options/windows" "github.com/wailsapp/wails/v2/pkg/runtime" - "time" ) //go:embed all:frontend/dist @@ -52,7 +53,7 @@ func main() { // create windows programmatically and be able to show/hide // them from the systray with something like: // - // myWindow := mainApp.NewWindow(...) + // myWindow := mainApp.NewWebviewWindow(...) // mainApp.NewSystemTray(&options.SystemTray{ // OnLeftClick: func() { // myWindow.SetVisibility(!myWindow.IsVisible()) From f4044ebcd9fbf98166d209c3ab45b14fa90ae208 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Mon, 2 Jan 2023 08:23:29 +1100 Subject: [PATCH 65/85] Add icon tool --- exp/go.mod | 4 ++ exp/go.sum | 24 ++++++++ exp/internal/commands/icon.go | 113 ++++++++++++++++++++++++++++++++-- 3 files changed, 137 insertions(+), 4 deletions(-) diff --git a/exp/go.mod b/exp/go.mod index caef91ba5..436147e58 100644 --- a/exp/go.mod +++ b/exp/go.mod @@ -4,7 +4,9 @@ go 1.19 require ( github.com/go-task/task/v3 v3.19.0 + github.com/jackmordaunt/icns/v2 v2.2.1 github.com/leaanthony/clir v1.3.0 + github.com/leaanthony/winicon v1.0.0 ) require ( @@ -15,9 +17,11 @@ require ( github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-zglob v0.0.4 // indirect github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect + github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect github.com/radovskyb/watcher v1.0.7 // indirect github.com/sajari/fuzzy v1.0.0 // indirect golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9 // indirect + golang.org/x/image v0.0.0-20200430140353-33d19683fad8 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect diff --git a/exp/go.sum b/exp/go.sum index 309dfc7f6..d82507a7f 100644 --- a/exp/go.sum +++ b/exp/go.sum @@ -10,12 +10,18 @@ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg78 github.com/go-task/task/v3 v3.19.0 h1:jS1s2fHoSgYySw+kHEtbSxS6emE620unBsDDcNqdRbc= github.com/go-task/task/v3 v3.19.0/go.mod h1:AjwL1xWWs8EwSZ0enL496mwqSTeIgXbPOXi+5of3MR4= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/jackmordaunt/icns/v2 v2.2.1 h1:MGklwYP2yohKn2Bw7XxlF69LZe98S1vUfl5OvAulPwg= +github.com/jackmordaunt/icns/v2 v2.2.1/go.mod h1:6aYIB9eSzyfHHMKqDf17Xrs1zetQPReAkiUSHzdw4cI= github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= github.com/leaanthony/clir v1.3.0 h1:L9nPDWrmc/qU9UWZZvRaFajWYuO0np9V5p+5gxyYno0= github.com/leaanthony/clir v1.3.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= +github.com/leaanthony/winicon v1.0.0 h1:ZNt5U5dY71oEoKZ97UVwJRT4e+5xo5o/ieKuHuk8NqQ= +github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU= github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= @@ -25,6 +31,10 @@ github.com/mattn/go-zglob v0.0.4 h1:LQi2iOm0/fGgu80AioIJ/1j9w9Oh+9DZ39J4VAGzHQM= github.com/mattn/go-zglob v0.0.4/go.mod h1:MxxjyoXXnMxfIpxTK2GAkw1w8glPsQILx3N5wrKakiY= github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/radovskyb/watcher v1.0.7 h1:AYePLih6dpmS32vlHfhCeli8127LzkIgwJGcwwe8tUE= @@ -32,13 +42,23 @@ github.com/radovskyb/watcher v1.0.7/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= github.com/sajari/fuzzy v1.0.0 h1:+FmwVvJErsd0d0hAPlj4CxqxUtQY/fOoY0DwX4ykpRY= github.com/sajari/fuzzy v1.0.0/go.mod h1:OjYR6KxoWOe9+dOlXeiCJd4dIbED4Oo8wpS89o0pwOo= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9 h1:RjggHMcaTVp0LOVZcW0bo8alwHrOaCrGUDgfWUHhnN4= golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -46,6 +66,10 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9w golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/exp/internal/commands/icon.go b/exp/internal/commands/icon.go index b77027f73..f4e6480e1 100644 --- a/exp/internal/commands/icon.go +++ b/exp/internal/commands/icon.go @@ -1,12 +1,32 @@ package commands -import "fmt" +import ( + "bytes" + "fmt" + "image" + "os" + "strconv" + "strings" + + "github.com/jackmordaunt/icns/v2" + + "github.com/leaanthony/winicon" +) type IconOptions struct { - Input string + Input string `description:"The input image file"` + Sizes string `description:"The sizes to generate in .ico file (comma separated)"` - WindowsFilename string - MacFilename string + WindowsFilename string `description:"The output filename for the Windows icon"` + MacFilename string `description:"The output filename for the Mac icon bundle"` +} + +func (i *IconOptions) Default() *IconOptions { + return &IconOptions{ + Sizes: "256,128,64,48,32,16", + MacFilename: "icons.icns", + WindowsFilename: "icons.ico", + } } func Icon(options *IconOptions) error { @@ -14,5 +34,90 @@ func Icon(options *IconOptions) error { return fmt.Errorf("input is required") } + if options.WindowsFilename == "" && options.MacFilename == "" { + return fmt.Errorf("at least one output filename is required") + } + + // Parse sizes + sizes, err := parseSizes(options.Sizes) + if err != nil { + return err + } + + iconData, err := os.ReadFile(options.Input) + if err != nil { + return err + } + + if options.WindowsFilename != "" { + err := generateWindowsIcon(iconData, sizes, options) + if err != nil { + return err + } + } + + if options.MacFilename != "" { + err := generateMacIcon(iconData, options) + if err != nil { + return err + } + } + + return nil +} + +func parseSizes(sizes string) ([]int, error) { + // split the input string by comma and confirm that each one is an integer + parsedSizes := strings.Split(sizes, ",") + result := make([]int, len(parsedSizes)) + for i, size := range parsedSizes { + s, err := strconv.Atoi(size) + if err != nil { + return nil, err + } + if s == 0 { + continue + } + result[i] = s + } + + // put all integers in a slice and return + return result, nil +} + +func generateMacIcon(iconData []byte, options *IconOptions) error { + + srcImg, _, err := image.Decode(bytes.NewBuffer(iconData)) + if err != nil { + return err + } + + dest, err := os.Create(options.MacFilename) + if err != nil { + return err + + } + defer func() { + err = dest.Close() + if err == nil { + return + } + }() + return icns.Encode(dest, srcImg) +} + +func generateWindowsIcon(iconData []byte, sizes []int, options *IconOptions) error { + + var output bytes.Buffer + + err := winicon.GenerateIcon(bytes.NewBuffer(iconData), &output, sizes) + if err != nil { + return err + } + + err = os.WriteFile(options.WindowsFilename, output.Bytes(), 0644) + if err != nil { + return err + } return nil } From e5da0eb5f8aea2399659445cadd57fd4bee12863 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Mon, 2 Jan 2023 21:23:44 +1100 Subject: [PATCH 66/85] Add icon generation Add syso generation Add tests --- exp/cmd/wails/README.md | 56 ++++ exp/cmd/wails/main.go | 6 +- exp/go.mod | 7 +- exp/go.sum | 16 +- exp/internal/commands/examples/appicon.png | Bin 0 -> 132625 bytes exp/internal/commands/examples/examples.go | 15 + exp/internal/commands/examples/icon.ico | Bin 0 -> 21017 bytes exp/internal/commands/examples/info.json | 15 + .../commands/examples/wails.exe.manifest | 15 + exp/internal/commands/icon.go | 29 +- exp/internal/commands/icon_test.go | 285 ++++++++++++++++++ exp/internal/commands/syso.go | 125 ++++++++ exp/internal/commands/syso_test.go | 189 ++++++++++++ 13 files changed, 742 insertions(+), 16 deletions(-) create mode 100644 exp/cmd/wails/README.md create mode 100644 exp/internal/commands/examples/appicon.png create mode 100644 exp/internal/commands/examples/examples.go create mode 100644 exp/internal/commands/examples/icon.ico create mode 100644 exp/internal/commands/examples/info.json create mode 100644 exp/internal/commands/examples/wails.exe.manifest create mode 100644 exp/internal/commands/icon_test.go create mode 100644 exp/internal/commands/syso.go create mode 100644 exp/internal/commands/syso_test.go diff --git a/exp/cmd/wails/README.md b/exp/cmd/wails/README.md new file mode 100644 index 000000000..cb1b97df5 --- /dev/null +++ b/exp/cmd/wails/README.md @@ -0,0 +1,56 @@ +# The Wails CLI + +The Wails CLI is a command line tool that allows you to create, build and run Wails applications. +There are a number of commands related to tooling, such as icon generation and asset bundling. + +## Commands + +### icon + +The `icon` command generates icons for your project. It takes a single argument which is the path to the icon file. + +| Flag | Type | Description | Default | +|--------------------|--------|------------------------------------------------------|-----------------------| +| `-example` | bool | Generates example icon file (appicon.png) | | +| `-input` | string | The input image file | | +| `-sizes` | string | The sizes to generate in .ico file (comma separated) | "256,128,64,48,32,16" | +| `-windowsFilename` | string | The output filename for the Windows icon | icons.ico | +| `-macFilename` | string | The output filename for the Mac icon bundle | icons.icns | + +```bash +wails icon -input myicon.png -sizes "32,64,128" -windowsFilename myicon.ico -macFilename myicon.icns +``` + +This will generate icons for mac and windows and save them in the current directory as `myicon.ico` +and `myicons.icns`. + +### syso + +The `syso` command generates a Windows resource file (aka `.syso`). + +```bash +wails syso +``` + +| Flag | Type | Description | Default | +|-------------|--------|--------------------------------------------|------------------| +| `-example` | bool | Generates example manifest & info files | | +| `-manifest` | string | The manifest file | | +| `-info` | string | The info.json file | | +| `-icon` | string | The icon file | | +| `-out` | string | The output filename for the syso file | `wails.exe.syso` | +| `-arch` | string | The target architecture (amd64,arm64,386) | `runtime.GOOS` | + +If `-example` is provided, the command will generate example manifest and info files +in the current directory and exit. + +If `-manifest` is provided, the command will use the provided manifest file to generate +the syso file. + +If `-info` is provided, the command will use the provided info.json file to set the version +information in the syso file. + +NOTE: We use [winres](https://github.com/tc-hib/winres) to generate the syso file. Please +refer to the winres documentation for more information. + +NOTE: Whilst the tool will work for 32-bit Windows, it is not supported. Please use 64-bit. \ No newline at end of file diff --git a/exp/cmd/wails/main.go b/exp/cmd/wails/main.go index 453f62255..b870c8203 100644 --- a/exp/cmd/wails/main.go +++ b/exp/cmd/wails/main.go @@ -12,9 +12,9 @@ func main() { app := clir.NewCli("wails", "The Wails CLI", "v3") app.NewSubCommandFunction("init", "Initialise a new project", commands.Init) app.NewSubCommandFunction("build", "Build the project", commands.Build) - tool := app.NewSubCommand("tool", "Various build tools") - tool.NewSubCommandFunction("icon", "Generate icons", commands.Icon) - + generate := app.NewSubCommand("generate", "Generation tools") + generate.NewSubCommandFunction("icon", "Generate icons", commands.GenerateIcon) + generate.NewSubCommandFunction("syso", "Generate Windows .syso file", commands.GenerateSyso) err := app.Run() if err != nil { log.Fatalln(err) diff --git a/exp/go.mod b/exp/go.mod index 436147e58..f8401aead 100644 --- a/exp/go.mod +++ b/exp/go.mod @@ -7,24 +7,27 @@ require ( github.com/jackmordaunt/icns/v2 v2.2.1 github.com/leaanthony/clir v1.3.0 github.com/leaanthony/winicon v1.0.0 + github.com/tc-hib/winres v0.1.6 ) require ( github.com/fatih/color v1.13.0 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect github.com/joho/godotenv v1.4.0 // indirect - github.com/mattn/go-colorable v0.1.9 // indirect + github.com/mattn/go-colorable v0.1.11 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-zglob v0.0.4 // indirect github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect + github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/radovskyb/watcher v1.0.7 // indirect github.com/sajari/fuzzy v1.0.0 // indirect golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9 // indirect - golang.org/x/image v0.0.0-20200430140353-33d19683fad8 // indirect + golang.org/x/image v0.0.0-20201208152932-35266b937fa6 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect + gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/yaml.v3 v3.0.1 // indirect mvdan.cc/sh/v3 v3.6.0-0.dev.0.20220704111049-a6e3029cd899 // indirect ) diff --git a/exp/go.sum b/exp/go.sum index d82507a7f..872708ee1 100644 --- a/exp/go.sum +++ b/exp/go.sum @@ -16,14 +16,17 @@ github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= github.com/leaanthony/clir v1.3.0 h1:L9nPDWrmc/qU9UWZZvRaFajWYuO0np9V5p+5gxyYno0= github.com/leaanthony/clir v1.3.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= github.com/leaanthony/winicon v1.0.0 h1:ZNt5U5dY71oEoKZ97UVwJRT4e+5xo5o/ieKuHuk8NqQ= github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU= -github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs= +github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= @@ -33,6 +36,8 @@ github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4 github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -48,12 +53,15 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/tc-hib/winres v0.1.6 h1:qgsYHze+BxQPEYilxIz/KCQGaClvI2+yLBAZs+3+0B8= +github.com/tc-hib/winres v0.1.6/go.mod h1:pe6dOR40VOrGz8PkzreVKNvEKnlE8t4yR8A8naL+t7A= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9 h1:RjggHMcaTVp0LOVZcW0bo8alwHrOaCrGUDgfWUHhnN4= golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= -golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw= golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20201208152932-35266b937fa6 h1:nfeHNc1nAqecKCy2FCy4HY+soOOe5sDLJ/gZLbx6GYI= +golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -62,6 +70,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= @@ -71,7 +80,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/exp/internal/commands/examples/appicon.png b/exp/internal/commands/examples/appicon.png new file mode 100644 index 0000000000000000000000000000000000000000..63617fe4f746b8a878bd5f44725f4f317b9d9850 GIT binary patch literal 132625 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 z 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 DB$9&s literal 0 HcmV?d00001 diff --git a/exp/internal/commands/examples/examples.go b/exp/internal/commands/examples/examples.go new file mode 100644 index 000000000..01b1b9a2c --- /dev/null +++ b/exp/internal/commands/examples/examples.go @@ -0,0 +1,15 @@ +package examples + +import _ "embed" + +//go:embed info.json +var Info []byte + +//go:embed wails.exe.manifest +var Manifest []byte + +//go:embed appicon.png +var AppIcon []byte + +//go:embed icon.ico +var IconIco []byte diff --git a/exp/internal/commands/examples/icon.ico b/exp/internal/commands/examples/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..f33479841c61728c8b5ee076ed13771c68e48b40 GIT binary patch literal 21017 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 + + + + + + + + + + true/pm + permonitorv2,permonitor + + + \ No newline at end of file diff --git a/exp/internal/commands/icon.go b/exp/internal/commands/icon.go index f4e6480e1..a7a3f5dc9 100644 --- a/exp/internal/commands/icon.go +++ b/exp/internal/commands/icon.go @@ -9,14 +9,14 @@ import ( "strings" "github.com/jackmordaunt/icns/v2" - "github.com/leaanthony/winicon" + "github.com/wailsapp/wails/exp/internal/commands/examples" ) type IconOptions struct { - Input string `description:"The input image file"` - Sizes string `description:"The sizes to generate in .ico file (comma separated)"` - + Example bool `description:"Generate example icon file (appicon.png) in the current directory"` + Input string `description:"The input image file"` + Sizes string `description:"The sizes to generate in .ico file (comma separated)"` WindowsFilename string `description:"The output filename for the Windows icon"` MacFilename string `description:"The output filename for the Mac icon bundle"` } @@ -29,7 +29,12 @@ func (i *IconOptions) Default() *IconOptions { } } -func Icon(options *IconOptions) error { +func GenerateIcon(options *IconOptions) error { + + if options.Example { + return generateExampleIcon() + } + if options.Input == "" { return fmt.Errorf("input is required") } @@ -39,9 +44,13 @@ func Icon(options *IconOptions) error { } // Parse sizes - sizes, err := parseSizes(options.Sizes) - if err != nil { - return err + var sizes = []int{256, 128, 64, 48, 32, 16} + var err error + if options.Sizes != "" { + sizes, err = parseSizes(options.Sizes) + if err != nil { + return err + } } iconData, err := os.ReadFile(options.Input) @@ -66,6 +75,10 @@ func Icon(options *IconOptions) error { return nil } +func generateExampleIcon() error { + return os.WriteFile("appicon.png", []byte(examples.AppIcon), 0644) +} + func parseSizes(sizes string) ([]int, error) { // split the input string by comma and confirm that each one is an integer parsedSizes := strings.Split(sizes, ",") diff --git a/exp/internal/commands/icon_test.go b/exp/internal/commands/icon_test.go new file mode 100644 index 000000000..4a911bfc2 --- /dev/null +++ b/exp/internal/commands/icon_test.go @@ -0,0 +1,285 @@ +package commands + +import ( + "fmt" + "os" + "path/filepath" + "runtime" + "testing" +) + +func TestGenerateIcon(t *testing.T) { + tests := []struct { + name string + setup func() *IconOptions + wantErr bool + test func() error + }{ + { + name: "should generate an icon when using the `example` flag", + setup: func() *IconOptions { + return &IconOptions{ + Example: true, + } + }, + wantErr: false, + test: func() error { + // the file `appicon.png` should be created in the current directory + // check for the existence of the file + f, err := os.Stat("appicon.png") + if err != nil { + return err + } + defer func() { + err := os.Remove("appicon.png") + if err != nil { + panic(err) + } + }() + if f.IsDir() { + return fmt.Errorf("appicon.png is a directory") + } + if f.Size() == 0 { + return fmt.Errorf("appicon.png is empty") + } + return nil + }, + }, + { + name: "should generate a .ico file when using the `input` flag and `windowsfilena me` flag", + setup: func() *IconOptions { + // Get the directory of this file + _, thisFile, _, _ := runtime.Caller(1) + localDir := filepath.Dir(thisFile) + // Get the path to the example icon + exampleIcon := filepath.Join(localDir, "examples", "appicon.png") + return &IconOptions{ + Input: exampleIcon, + WindowsFilename: "appicon.ico", + } + }, + wantErr: false, + test: func() error { + // the file `appicon.ico` should be created in the current directory + // check for the existence of the file + f, err := os.Stat("appicon.ico") + if err != nil { + return err + } + defer func() { + // Remove the file + err = os.Remove("appicon.ico") + if err != nil { + return + } + }() + if f.IsDir() { + return fmt.Errorf("appicon.ico is a directory") + } + if f.Size() == 0 { + return fmt.Errorf("appicon.ico is empty") + } + // Remove the file + err = os.Remove("appicon.ico") + if err != nil { + return err + } + return nil + }, + }, + { + name: "should generate a .icns file when using the `input` flag and `macfilename` flag", + setup: func() *IconOptions { + // Get the directory of this file + _, thisFile, _, _ := runtime.Caller(1) + localDir := filepath.Dir(thisFile) + // Get the path to the example icon + exampleIcon := filepath.Join(localDir, "examples", "appicon.png") + return &IconOptions{ + Input: exampleIcon, + MacFilename: "appicon.icns", + } + }, + wantErr: false, + test: func() error { + // the file `appicon.icns` should be created in the current directory + // check for the existence of the file + f, err := os.Stat("appicon.icns") + if err != nil { + return err + } + defer func() { + // Remove the file + err = os.Remove("appicon.icns") + if err != nil { + panic(err) + } + }() + if f.IsDir() { + return fmt.Errorf("appicon.icns is a directory") + } + if f.Size() == 0 { + return fmt.Errorf("appicon.icns is empty") + } + // Remove the file + + return nil + }, + }, + { + name: "should generate a small .ico file when using the `input` flag and `sizes` flag", + setup: func() *IconOptions { + // Get the directory of this file + _, thisFile, _, _ := runtime.Caller(1) + localDir := filepath.Dir(thisFile) + // Get the path to the example icon + exampleIcon := filepath.Join(localDir, "examples", "appicon.png") + return &IconOptions{ + Input: exampleIcon, + Sizes: "16", + WindowsFilename: "appicon.ico", + } + }, + wantErr: false, + test: func() error { + // the file `appicon.ico` should be created in the current directory + // check for the existence of the file + f, err := os.Stat("appicon.ico") + if err != nil { + return err + } + defer func() { + err := os.Remove("appicon.ico") + if err != nil { + panic(err) + } + }() + // The size of the file should be 571 bytes + if f.Size() != 571 { + return fmt.Errorf("appicon.ico is not the correct size. Got %d", f.Size()) + } + if f.IsDir() { + return fmt.Errorf("appicon.ico is a directory") + } + if f.Size() == 0 { + return fmt.Errorf("appicon.ico is empty") + } + return nil + }, + }, + { + name: "should error if no input file is provided", + setup: func() *IconOptions { + return &IconOptions{} + }, + wantErr: true, + }, + { + name: "should error if neither mac or windows filename is provided", + setup: func() *IconOptions { + // Get the directory of this file + _, thisFile, _, _ := runtime.Caller(1) + localDir := filepath.Dir(thisFile) + // Get the path to the example icon + exampleIcon := filepath.Join(localDir, "examples", "appicon.png") + return &IconOptions{ + Input: exampleIcon, + } + }, + wantErr: true, + }, + { + name: "should error if bad sizes provided", + setup: func() *IconOptions { + // Get the directory of this file + _, thisFile, _, _ := runtime.Caller(1) + localDir := filepath.Dir(thisFile) + // Get the path to the example icon + exampleIcon := filepath.Join(localDir, "examples", "appicon.png") + return &IconOptions{ + Input: exampleIcon, + WindowsFilename: "appicon.ico", + Sizes: "bad", + } + }, + wantErr: true, + }, + { + name: "should ignore 0 size", + setup: func() *IconOptions { + // Get the directory of this file + _, thisFile, _, _ := runtime.Caller(1) + localDir := filepath.Dir(thisFile) + // Get the path to the example icon + exampleIcon := filepath.Join(localDir, "examples", "appicon.png") + return &IconOptions{ + Input: exampleIcon, + WindowsFilename: "appicon.ico", + Sizes: "0,16", + } + }, + wantErr: false, + test: func() error { + // Test the file exists and has 571 bytes + f, err := os.Stat("appicon.ico") + if err != nil { + return err + } + defer func() { + err := os.Remove("appicon.ico") + if err != nil { + panic(err) + } + }() + if f.Size() != 571 { + return fmt.Errorf("appicon.ico is not the correct size. Got %d", f.Size()) + } + if f.IsDir() { + return fmt.Errorf("appicon.ico is a directory") + } + if f.Size() == 0 { + return fmt.Errorf("appicon.ico is empty") + } + return nil + }, + }, + { + name: "should error if the input file does not exist", + setup: func() *IconOptions { + return &IconOptions{ + Input: "doesnotexist.png", + WindowsFilename: "appicon.ico", + } + }, + wantErr: true, + }, + { + name: "should error if the input file is not a png", + setup: func() *IconOptions { + // Get the directory of this file + _, thisFile, _, _ := runtime.Caller(1) + return &IconOptions{ + Input: thisFile, + WindowsFilename: "appicon.ico", + } + }, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + options := tt.setup() + err := GenerateIcon(options) + if (err != nil) != tt.wantErr { + t.Errorf("GenerateIcon() error = %v, wantErr %v", err, tt.wantErr) + return + } + if tt.test != nil { + if err := tt.test(); err != nil { + t.Errorf("GenerateIcon() test error = %v", err) + } + } + }) + } +} diff --git a/exp/internal/commands/syso.go b/exp/internal/commands/syso.go new file mode 100644 index 000000000..858367873 --- /dev/null +++ b/exp/internal/commands/syso.go @@ -0,0 +1,125 @@ +package commands + +import ( + "fmt" + "os" + "runtime" + + "github.com/tc-hib/winres" + "github.com/tc-hib/winres/version" + "github.com/wailsapp/wails/exp/internal/commands/examples" +) + +type SysoOptions struct { + Example bool `description:"Generate example manifest & info files"` + Manifest string `description:"The manifest file"` + Info string `description:"The info.json file"` + Icon string `description:"The icon file"` + Out string `description:"The output filename for the syso file"` + Arch string `description:"The target architecture"` +} + +func (i *SysoOptions) Default() *SysoOptions { + return &SysoOptions{ + Arch: runtime.GOOS, + Out: "wails-res.syso", + } +} + +func GenerateSyso(options *SysoOptions) error { + + // Generate example files? + if options.Example { + return generateExampleSyso() + } + + if options.Manifest == "" { + return fmt.Errorf("manifest is required") + } + if options.Icon == "" { + return fmt.Errorf("icon is required") + } + + rs := winres.ResourceSet{} + + // Process Icon + iconFile, err := os.Open(options.Icon) + if err != nil { + return err + } + defer iconFile.Close() + ico, err := winres.LoadICO(iconFile) + if err != nil { + return fmt.Errorf("couldn't load icon '%s': %v", options.Icon, err) + } + err = rs.SetIcon(winres.RT_ICON, ico) + if err != nil { + return err + } + + // Process Manifest + manifestData, err := os.ReadFile(options.Manifest) + if err != nil { + return err + } + + xmlData, err := winres.AppManifestFromXML(manifestData) + if err != nil { + return err + } + rs.SetManifest(xmlData) + + if options.Info != "" { + infoData, err := os.ReadFile(options.Info) + if err != nil { + return err + } + if len(infoData) != 0 { + var v version.Info + if err := v.UnmarshalJSON(infoData); err != nil { + return err + } + rs.SetVersionInfo(v) + } + } + + targetFile := options.Out + if targetFile == "" { + targetFile = "wails-res.syso" + } + fout, err := os.Create(targetFile) + if err != nil { + return err + } + defer fout.Close() + + archs := map[string]winres.Arch{ + "amd64": winres.ArchAMD64, + "arm64": winres.ArchARM64, + "386": winres.ArchI386, + } + targetArch, supported := archs[options.Arch] + if !supported { + return fmt.Errorf("arch '%s' not supported", options.Arch) + } + + err = rs.WriteObject(fout, targetArch) + if err != nil { + return err + } + return nil +} + +func generateExampleSyso() error { + // Generate example info.json + err := os.WriteFile("info.json", examples.Info, 0644) + if err != nil { + return err + } + // Generate example manifest + err = os.WriteFile("wails.exe.manifest", examples.Manifest, 0644) + if err != nil { + return err + } + return nil +} diff --git a/exp/internal/commands/syso_test.go b/exp/internal/commands/syso_test.go new file mode 100644 index 000000000..a1e18e3dc --- /dev/null +++ b/exp/internal/commands/syso_test.go @@ -0,0 +1,189 @@ +package commands + +import ( + "fmt" + "os" + "path/filepath" + "runtime" + "testing" +) + +func TestGenerateSyso(t *testing.T) { + tests := []struct { + name string + setup func() *SysoOptions + wantErr bool + test func() error + }{ + { + name: "should generate example info and manifest files when using the `example` flag", + setup: func() *SysoOptions { + return &SysoOptions{ + Example: true, + } + }, + wantErr: false, + test: func() error { + // the file `info.json` should be created in the current directory + // check for the existence of the file + f, err := os.Stat("info.json") + if err != nil { + return err + } + m, err := os.Stat("wails.exe.manifest") + if err != nil { + return err + } + defer func() { + err := os.Remove("info.json") + err2 := os.Remove("wails.exe.manifest") + if err != nil { + panic(err) + } + if err2 != nil { + panic(err2) + } + }() + if f.IsDir() { + return fmt.Errorf("info.json is a directory") + } + if f.Size() == 0 { + return fmt.Errorf("info.json is empty") + } + if m.IsDir() { + return fmt.Errorf("wails.exe.manifest is a directory") + } + if m.Size() == 0 { + return fmt.Errorf("wails.exe.manifest is empty") + } + return nil + }, + }, + { + name: "should error if manifest filename is not provided", + setup: func() *SysoOptions { + return &SysoOptions{ + Manifest: "", + } + }, + wantErr: true, + }, + { + name: "should error if icon filename is not provided", + setup: func() *SysoOptions { + return &SysoOptions{ + Manifest: "test.manifest", + Icon: "", + } + }, + wantErr: true, + }, + { + name: "should error if icon filename does not exist", + setup: func() *SysoOptions { + return &SysoOptions{ + Manifest: "test.manifest", + Icon: "icon.ico", + } + }, + wantErr: true, + }, + { + name: "should error if icon is wrong format", + setup: func() *SysoOptions { + _, thisFile, _, _ := runtime.Caller(1) + return &SysoOptions{ + Manifest: "test.manifest", + Icon: thisFile, + } + }, + wantErr: true, + }, + { + name: "should error if manifest filename does not exist", + setup: func() *SysoOptions { + // Get the directory of this file + _, thisFile, _, _ := runtime.Caller(1) + localDir := filepath.Dir(thisFile) + // Get the path to the example icon + exampleIcon := filepath.Join(localDir, "examples", "icon.ico") + return &SysoOptions{ + Manifest: "test.manifest", + Icon: exampleIcon, + } + }, + wantErr: true, + }, + { + name: "should error if manifest is wrong format", + setup: func() *SysoOptions { + // Get the directory of this file + _, thisFile, _, _ := runtime.Caller(1) + localDir := filepath.Dir(thisFile) + // Get the path to the example icon + exampleIcon := filepath.Join(localDir, "examples", "icon.ico") + return &SysoOptions{ + Manifest: exampleIcon, + Icon: exampleIcon, + } + }, + wantErr: true, + }, + { + name: "should error if info file does not exist", + setup: func() *SysoOptions { + // Get the directory of this file + _, thisFile, _, _ := runtime.Caller(1) + localDir := filepath.Dir(thisFile) + // Get the path to the example icon + exampleIcon := filepath.Join(localDir, "examples", "icon.ico") + // Get the path to the example manifest + exampleManifest := filepath.Join(localDir, "examples", "wails.exe.manifest") + return &SysoOptions{ + Manifest: exampleManifest, + Icon: exampleIcon, + Info: "doesnotexist.json", + } + }, + wantErr: true, + }, + { + name: "should error if info file is wrong format", + setup: func() *SysoOptions { + // Get the directory of this file + _, thisFile, _, _ := runtime.Caller(1) + localDir := filepath.Dir(thisFile) + // Get the path to the example icon + exampleIcon := filepath.Join(localDir, "examples", "icon.ico") + // Get the path to the example manifest + exampleManifest := filepath.Join(localDir, "examples", "wails.exe.manifest") + return &SysoOptions{ + Manifest: exampleManifest, + Icon: exampleIcon, + Info: thisFile, + } + }, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + options := tt.setup() + err := GenerateSyso(options) + if (err != nil) != tt.wantErr { + t.Errorf("GenerateSyso() error = %v, wantErr %v", err, tt.wantErr) + return + } + if (err != nil) && tt.wantErr { + println(err.Error()) + return + } + if tt.test != nil { + if err := tt.test(); err != nil { + t.Errorf("GenerateSyso() test error = %v", err) + } + } + }) + } +} From 746b4dfc04800c958ec09cd5c37c2a82de70dfb0 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Tue, 3 Jan 2023 05:43:56 +1100 Subject: [PATCH 67/85] Fix sizes bug Remove redundant menu package --- exp/internal/commands/icon.go | 6 +++--- exp/pkg/menu/menu.go | 22 ---------------------- 2 files changed, 3 insertions(+), 25 deletions(-) delete mode 100644 exp/pkg/menu/menu.go diff --git a/exp/internal/commands/icon.go b/exp/internal/commands/icon.go index a7a3f5dc9..adaee64d0 100644 --- a/exp/internal/commands/icon.go +++ b/exp/internal/commands/icon.go @@ -82,8 +82,8 @@ func generateExampleIcon() error { func parseSizes(sizes string) ([]int, error) { // split the input string by comma and confirm that each one is an integer parsedSizes := strings.Split(sizes, ",") - result := make([]int, len(parsedSizes)) - for i, size := range parsedSizes { + var result []int + for _, size := range parsedSizes { s, err := strconv.Atoi(size) if err != nil { return nil, err @@ -91,7 +91,7 @@ func parseSizes(sizes string) ([]int, error) { if s == 0 { continue } - result[i] = s + result = append(result, s) } // put all integers in a slice and return diff --git a/exp/pkg/menu/menu.go b/exp/pkg/menu/menu.go deleted file mode 100644 index 1e2c71cf5..000000000 --- a/exp/pkg/menu/menu.go +++ /dev/null @@ -1,22 +0,0 @@ -package menu - -type Menu struct { - Items []*Item -} - -func (m *Menu) Label(label string) *Item { - return &Item{ - Label: label, - } -} - -type CallbackContext struct { - MenuItem *Item -} - -type Item struct { - Label string - Disabled bool - Click func(*CallbackContext) - ID uint -} From 174a31b49aab5aa0ab9c9be7f14d2b22f0ae20ab Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 4 Jan 2023 20:01:13 +1100 Subject: [PATCH 68/85] Add `run` command for running tasks in a `Taskfile.yml` Add `generate` command for generating assets Add build example --- exp/cmd/wails/README.md | 35 ++- exp/cmd/wails/main.go | 6 +- exp/examples/build/README.md | 15 + exp/examples/build/Taskfile.yml | 31 ++ exp/examples/build/build/Info.dev.plist | 35 +++ exp/examples/build/build/Info.plist | 27 ++ .../build/build}/appicon.png | Bin exp/examples/build/build/icons.icns | Bin 0 -> 356592 bytes exp/examples/build/build/icons.ico | Bin 0 -> 21677 bytes .../build/build}/info.json | 0 .../build/build}/wails.exe.manifest | 0 .../build/buildtest.app/Contents/Info.plist | 27 ++ .../Contents/Resources/icons.icns | Bin 0 -> 356592 bytes exp/examples/build/main.go | 275 ++++++++++++++++++ exp/go.mod | 12 +- exp/go.sum | 30 +- exp/internal/commands/build_test.go | 30 -- exp/internal/commands/defaults.go | 61 ++++ exp/internal/commands/defaults/Info.dev.plist | 32 ++ exp/internal/commands/defaults/Info.plist | 27 ++ exp/internal/commands/defaults/appicon.png | Bin 0 -> 132625 bytes exp/internal/commands/defaults/icons.icns | Bin 0 -> 356592 bytes .../{examples/icon.ico => defaults/icons.ico} | Bin exp/internal/commands/defaults/info.json | 15 + .../commands/defaults/wails.exe.manifest | 15 + exp/internal/commands/examples/examples.go | 15 - exp/internal/commands/{icon.go => icons.go} | 15 +- .../commands/{icon_test.go => icons_test.go} | 44 +-- exp/internal/commands/{build.go => run.go} | 11 +- exp/internal/commands/run_test.go | 38 +++ exp/internal/commands/syso.go | 10 +- 31 files changed, 693 insertions(+), 113 deletions(-) create mode 100644 exp/examples/build/README.md create mode 100644 exp/examples/build/Taskfile.yml create mode 100644 exp/examples/build/build/Info.dev.plist create mode 100644 exp/examples/build/build/Info.plist rename exp/{internal/commands/examples => examples/build/build}/appicon.png (100%) create mode 100644 exp/examples/build/build/icons.icns create mode 100644 exp/examples/build/build/icons.ico rename exp/{internal/commands/examples => examples/build/build}/info.json (100%) rename exp/{internal/commands/examples => examples/build/build}/wails.exe.manifest (100%) create mode 100644 exp/examples/build/buildtest.app/Contents/Info.plist create mode 100644 exp/examples/build/buildtest.app/Contents/Resources/icons.icns create mode 100755 exp/examples/build/main.go delete mode 100644 exp/internal/commands/build_test.go create mode 100644 exp/internal/commands/defaults.go create mode 100644 exp/internal/commands/defaults/Info.dev.plist create mode 100644 exp/internal/commands/defaults/Info.plist create mode 100644 exp/internal/commands/defaults/appicon.png create mode 100644 exp/internal/commands/defaults/icons.icns rename exp/internal/commands/{examples/icon.ico => defaults/icons.ico} (100%) create mode 100644 exp/internal/commands/defaults/info.json create mode 100644 exp/internal/commands/defaults/wails.exe.manifest delete mode 100644 exp/internal/commands/examples/examples.go rename exp/internal/commands/{icon.go => icons.go} (87%) rename exp/internal/commands/{icon_test.go => icons_test.go} (90%) rename exp/internal/commands/{build.go => run.go} (54%) create mode 100644 exp/internal/commands/run_test.go diff --git a/exp/cmd/wails/README.md b/exp/cmd/wails/README.md index cb1b97df5..6d005d023 100644 --- a/exp/cmd/wails/README.md +++ b/exp/cmd/wails/README.md @@ -5,9 +5,25 @@ There are a number of commands related to tooling, such as icon generation and a ## Commands -### icon +### run -The `icon` command generates icons for your project. It takes a single argument which is the path to the icon file. +The run command is for running tasks defined in `Taskfile.yml`. + +| Flag | Type | Description | Default | +|--------------------|--------|------------------------------------------------------|-----------------------| +| `-t` | string | The name of the task to run | | + +### generate + +The `generate` command is used to generate resources and assets for your Wails project. +It can be used to generate many things including: + - application icons, + - resource files for Windows applications + - Info.plist files for macOS deployments + +#### icon + +The `icon` command generates icons for your project. | Flag | Type | Description | Default | |--------------------|--------|------------------------------------------------------|-----------------------| @@ -18,18 +34,18 @@ The `icon` command generates icons for your project. It takes a single argument | `-macFilename` | string | The output filename for the Mac icon bundle | icons.icns | ```bash -wails icon -input myicon.png -sizes "32,64,128" -windowsFilename myicon.ico -macFilename myicon.icns +wails generate icon -input myicon.png -sizes "32,64,128" -windowsFilename myicon.ico -macFilename myicon.icns ``` This will generate icons for mac and windows and save them in the current directory as `myicon.ico` and `myicons.icns`. -### syso +#### syso The `syso` command generates a Windows resource file (aka `.syso`). ```bash -wails syso +wails generate syso ``` | Flag | Type | Description | Default | @@ -53,4 +69,11 @@ information in the syso file. NOTE: We use [winres](https://github.com/tc-hib/winres) to generate the syso file. Please refer to the winres documentation for more information. -NOTE: Whilst the tool will work for 32-bit Windows, it is not supported. Please use 64-bit. \ No newline at end of file +NOTE: Whilst the tool will work for 32-bit Windows, it is not supported. Please use 64-bit. + +#### defaults + +```bash +wails icon -input myicon.png -sizes "32,64,128" -windowsFilename myicon.ico -macFilename myicon.icns +``` +This will generate all the default assets and resources in the current directory. I \ No newline at end of file diff --git a/exp/cmd/wails/main.go b/exp/cmd/wails/main.go index b870c8203..88d9d1ce6 100644 --- a/exp/cmd/wails/main.go +++ b/exp/cmd/wails/main.go @@ -8,12 +8,12 @@ import ( ) func main() { - app := clir.NewCli("wails", "The Wails CLI", "v3") app.NewSubCommandFunction("init", "Initialise a new project", commands.Init) - app.NewSubCommandFunction("build", "Build the project", commands.Build) + app.NewSubCommandFunction("run", "Run a task", commands.Run) generate := app.NewSubCommand("generate", "Generation tools") - generate.NewSubCommandFunction("icon", "Generate icons", commands.GenerateIcon) + generate.NewSubCommandFunction("defaults", "Generate default build assets", commands.Defaults) + generate.NewSubCommandFunction("icons", "Generate icons", commands.GenerateIcons) generate.NewSubCommandFunction("syso", "Generate Windows .syso file", commands.GenerateSyso) err := app.Run() if err != nil { diff --git a/exp/examples/build/README.md b/exp/examples/build/README.md new file mode 100644 index 000000000..bb2b1761e --- /dev/null +++ b/exp/examples/build/README.md @@ -0,0 +1,15 @@ +# Build + +Wails has adopted [Taskfile](https://taskfile.dev) as its build tool. This is optional +and any build tool can be used. However, Taskfile is a great tool, and we recommend it. + +The Wails CLI has built-in integration with Taskfile so the standalone version is not a +requirement. + +## Building + +To build the example, run: + +```bash +wails run -t build +``` diff --git a/exp/examples/build/Taskfile.yml b/exp/examples/build/Taskfile.yml new file mode 100644 index 000000000..dfb9020b7 --- /dev/null +++ b/exp/examples/build/Taskfile.yml @@ -0,0 +1,31 @@ +version: '3' + +tasks: + build: + cmds: + - go build -gcflags=all="-N -l" -o bin/testapp main.go + vars: + BIN_NAME: $NAME + env: + CGO_CFLAGS: "-mmacosx-version-min=10.13" + CGO_LDFLAGS: "-mmacosx-version-min=10.13" + + generate-icons: + dir: build + cmds: + # Generates both .ico and .icns files + - wails generate icon -input appicon.png + + build-prod: + cmds: + - go build -tags production -ldflags="-w -s" -o bin/testapp + + package-darwin: + deps: + - build-prod + - generate-icons + cmds: + - mkdir -p buildtest.app/Contents/{MacOS,Resources} + - cp build/icons.icns buildtest.app/Contents/Resources + - cp bin/testapp buildtest.app/Contents/MacOS + - cp build/Info.plist buildtest.app/Contents \ No newline at end of file diff --git a/exp/examples/build/build/Info.dev.plist b/exp/examples/build/build/Info.dev.plist new file mode 100644 index 000000000..d6d28b179 --- /dev/null +++ b/exp/examples/build/build/Info.dev.plist @@ -0,0 +1,35 @@ + + + + CFBundlePackageType + APPL + CFBundleName + My App + CFBundleExecutable + app + CFBundleIdentifier + com.wails.app + CFBundleVersion + v1.0.0 + CFBundleGetInfoString + The ultimate thing + CFBundleShortVersionString + v1 + CFBundleIconFile + icons + LSMinimumSystemVersion + 10.13.0 + NSHighResolutionCapable + true + NSHumanReadableCopyright + (c) Me + NSAppTransportSecurity + + NSAllowsLocalNetworking + + + + + + + \ No newline at end of file diff --git a/exp/examples/build/build/Info.plist b/exp/examples/build/build/Info.plist new file mode 100644 index 000000000..7f03f54e9 --- /dev/null +++ b/exp/examples/build/build/Info.plist @@ -0,0 +1,27 @@ + + + + CFBundlePackageType + APPL + CFBundleName + My App + CFBundleExecutable + app + CFBundleIdentifier + com.wails.app + CFBundleVersion + v1.0.0 + CFBundleGetInfoString + The ultimate thing + CFBundleShortVersionString + v1 + CFBundleIconFile + icons + LSMinimumSystemVersion + 10.13.0 + NSHighResolutionCapable + true + NSHumanReadableCopyright + (c) Me + + \ No newline at end of file diff --git a/exp/internal/commands/examples/appicon.png b/exp/examples/build/build/appicon.png similarity index 100% rename from exp/internal/commands/examples/appicon.png rename to exp/examples/build/build/appicon.png diff --git a/exp/examples/build/build/icons.icns b/exp/examples/build/build/icons.icns new file mode 100644 index 0000000000000000000000000000000000000000..1b5bd4c86c4533471d6044c5edc0c8c86b87e612 GIT binary patch literal 356592 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

^Lg7K@^M66wF^U#m6$MQA`NxZ%~uf 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 KmPKi1yf9{GFYLn7<2oM4U2n2V6yF2qb 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 ou5=8}@A^#05^yFjv{|%CV0m?W0y8r+H literal 0 HcmV?d00001 diff --git a/exp/internal/commands/examples/info.json b/exp/examples/build/build/info.json similarity index 100% rename from exp/internal/commands/examples/info.json rename to exp/examples/build/build/info.json diff --git a/exp/internal/commands/examples/wails.exe.manifest b/exp/examples/build/build/wails.exe.manifest similarity index 100% rename from exp/internal/commands/examples/wails.exe.manifest rename to exp/examples/build/build/wails.exe.manifest diff --git a/exp/examples/build/buildtest.app/Contents/Info.plist b/exp/examples/build/buildtest.app/Contents/Info.plist new file mode 100644 index 000000000..7f03f54e9 --- /dev/null +++ b/exp/examples/build/buildtest.app/Contents/Info.plist @@ -0,0 +1,27 @@ + + + + CFBundlePackageType + APPL + CFBundleName + My App + CFBundleExecutable + app + CFBundleIdentifier + com.wails.app + CFBundleVersion + v1.0.0 + CFBundleGetInfoString + The ultimate thing + CFBundleShortVersionString + v1 + CFBundleIconFile + icons + LSMinimumSystemVersion + 10.13.0 + NSHighResolutionCapable + true + NSHumanReadableCopyright + (c) Me + + \ No newline at end of file diff --git a/exp/examples/build/buildtest.app/Contents/Resources/icons.icns b/exp/examples/build/buildtest.app/Contents/Resources/icons.icns new file mode 100644 index 0000000000000000000000000000000000000000..1b5bd4c86c4533471d6044c5edc0c8c86b87e612 GIT binary patch literal 356592 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

^Lg7K@^M66wF^U#m6$MQA`NxZ%~uf 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 KmPKi1yf9{GFYLn7<

A TitleBarHiddenInset WebviewWindow example

"). + Show() + windowCounter++ + }) + myMenu.Add("New WebviewWindow (TitleBarHiddenInsetUnified)"). + OnClick(func(ctx *application.Context) { + app.NewWebviewWindowWithOptions(&options.WebviewWindow{ + Mac: options.MacWindow{ + TitleBar: options.TitleBarHiddenInsetUnified, + InvisibleTitleBarHeight: 50, + }, + }). + SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). + SetPosition(rand.Intn(1000), rand.Intn(800)). + SetHTML("

A TitleBarHiddenInsetUnified WebviewWindow example

"). + Show() + windowCounter++ + }) + myMenu.Add("New WebviewWindow (TitleBarHidden)"). + OnClick(func(ctx *application.Context) { + app.NewWebviewWindowWithOptions(&options.WebviewWindow{ + Mac: options.MacWindow{ + TitleBar: options.TitleBarHidden, + InvisibleTitleBarHeight: 25, + }, + }). + SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). + SetPosition(rand.Intn(1000), rand.Intn(800)). + SetHTML("

A TitleBarHidden WebviewWindow example

"). + Show() + windowCounter++ + }) + } + + sizeMenu := menu.AddSubmenu("Size") + sizeMenu.Add("Set Size (800,600)").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + w.SetSize(800, 600) + }) + }) + + sizeMenu.Add("Set Size (Random)").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + w.SetSize(rand.Intn(800)+200, rand.Intn(600)+200) + }) + }) + sizeMenu.Add("Set Min Size (200,200)").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + w.SetMinSize(200, 200) + }) + }) + sizeMenu.Add("Set Max Size (600,600)").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + w.SetFullscreenButtonEnabled(false) + w.SetMaxSize(600, 600) + }) + }) + sizeMenu.Add("Get Current WebviewWindow Size").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + width, height := w.Size() + app.NewInfoDialog().SetTitle("Current WebviewWindow Size").SetMessage("Width: " + strconv.Itoa(width) + " Height: " + strconv.Itoa(height)).Show() + }) + }) + + sizeMenu.Add("Reset Min Size").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + w.SetMinSize(0, 0) + }) + }) + + sizeMenu.Add("Reset Max Size").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + w.SetMaxSize(0, 0) + w.SetFullscreenButtonEnabled(true) + }) + }) + positionMenu := menu.AddSubmenu("Position") + positionMenu.Add("Set Position (0,0)").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + w.SetPosition(0, 0) + }) + }) + positionMenu.Add("Set Position (Random)").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + w.SetPosition(rand.Intn(1000), rand.Intn(800)) + }) + }) + + positionMenu.Add("Get Position").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + x, y := w.Position() + app.NewInfoDialog().SetTitle("Current WebviewWindow Position").SetMessage("X: " + strconv.Itoa(x) + " Y: " + strconv.Itoa(y)).Show() + }) + }) + + positionMenu.Add("Center").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + w.Center() + }) + }) + stateMenu := menu.AddSubmenu("State") + stateMenu.Add("Minimise (for 2 secs)").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + w.Minimise() + time.Sleep(2 * time.Second) + w.Restore() + }) + }) + stateMenu.Add("Maximise").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + w.Maximise() + }) + }) + stateMenu.Add("Fullscreen").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + w.Fullscreen() + }) + }) + stateMenu.Add("UnFullscreen").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + w.UnFullscreen() + }) + }) + stateMenu.Add("Restore").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + w.Restore() + }) + }) + stateMenu.Add("Hide (for 2 seconds)").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + w.Hide() + time.Sleep(2 * time.Second) + w.Show() + }) + }) + stateMenu.Add("Always on Top").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + w.SetAlwaysOnTop(true) + }) + }) + stateMenu.Add("Not always on Top").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + w.SetAlwaysOnTop(false) + }) + }) + stateMenu.Add("Google.com").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + w.SetURL("https://google.com") + }) + }) + stateMenu.Add("wails.io").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + w.SetURL("https://wails.io") + }) + }) + stateMenu.Add("Get Primary Screen").OnClick(func(ctx *application.Context) { + screen, err := app.GetPrimaryScreen() + if err != nil { + app.NewErrorDialog().SetTitle("Error").SetMessage(err.Error()).Show() + return + } + msg := fmt.Sprintf("Screen: %+v", screen) + app.NewInfoDialog().SetTitle("Primary Screen").SetMessage(msg).Show() + }) + stateMenu.Add("Get Screens").OnClick(func(ctx *application.Context) { + screens, err := app.GetScreens() + if err != nil { + app.NewErrorDialog().SetTitle("Error").SetMessage(err.Error()).Show() + return + } + for _, screen := range screens { + msg := fmt.Sprintf("Screen: %+v", screen) + app.NewInfoDialog().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show() + } + }) + stateMenu.Add("Get Screen for WebviewWindow").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + screen, err := w.GetScreen() + if err != nil { + app.NewErrorDialog().SetTitle("Error").SetMessage(err.Error()).Show() + return + } + msg := fmt.Sprintf("Screen: %+v", screen) + app.NewInfoDialog().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show() + }) + }) + app.NewWebviewWindow() + + app.SetMenu(menu) + err := app.Run() + + if err != nil { + log.Fatal(err) + } + +} diff --git a/exp/go.mod b/exp/go.mod index f8401aead..8cbac8f59 100644 --- a/exp/go.mod +++ b/exp/go.mod @@ -3,7 +3,7 @@ module github.com/wailsapp/wails/exp go 1.19 require ( - github.com/go-task/task/v3 v3.19.0 + github.com/go-task/task/v3 v3.19.1 github.com/jackmordaunt/icns/v2 v2.2.1 github.com/leaanthony/clir v1.3.0 github.com/leaanthony/winicon v1.0.0 @@ -24,10 +24,12 @@ require ( github.com/sajari/fuzzy v1.0.0 // indirect golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9 // indirect golang.org/x/image v0.0.0-20201208152932-35266b937fa6 // indirect - golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect - golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect + golang.org/x/sync v0.1.0 // indirect + golang.org/x/sys v0.3.0 // indirect + golang.org/x/term v0.3.0 // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - mvdan.cc/sh/v3 v3.6.0-0.dev.0.20220704111049-a6e3029cd899 // indirect + mvdan.cc/sh/v3 v3.6.0 // indirect ) + +replace github.com/go-task/task/v3 v3.19.1 => github.com/wailsapp/task/v3 v3.19.1 diff --git a/exp/go.sum b/exp/go.sum index 872708ee1..b3f3eb5e6 100644 --- a/exp/go.sum +++ b/exp/go.sum @@ -1,21 +1,19 @@ -github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss= +github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/go-task/task/v3 v3.19.0 h1:jS1s2fHoSgYySw+kHEtbSxS6emE620unBsDDcNqdRbc= -github.com/go-task/task/v3 v3.19.0/go.mod h1:AjwL1xWWs8EwSZ0enL496mwqSTeIgXbPOXi+5of3MR4= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/jackmordaunt/icns/v2 v2.2.1 h1:MGklwYP2yohKn2Bw7XxlF69LZe98S1vUfl5OvAulPwg= github.com/jackmordaunt/icns/v2 v2.2.1/go.mod h1:6aYIB9eSzyfHHMKqDf17Xrs1zetQPReAkiUSHzdw4cI= github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -44,7 +42,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/radovskyb/watcher v1.0.7 h1:AYePLih6dpmS32vlHfhCeli8127LzkIgwJGcwwe8tUE= github.com/radovskyb/watcher v1.0.7/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm+ZuvsUYIg= -github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/sajari/fuzzy v1.0.0 h1:+FmwVvJErsd0d0hAPlj4CxqxUtQY/fOoY0DwX4ykpRY= github.com/sajari/fuzzy v1.0.0/go.mod h1:OjYR6KxoWOe9+dOlXeiCJd4dIbED4Oo8wpS89o0pwOo= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= @@ -55,6 +53,8 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/tc-hib/winres v0.1.6 h1:qgsYHze+BxQPEYilxIz/KCQGaClvI2+yLBAZs+3+0B8= github.com/tc-hib/winres v0.1.6/go.mod h1:pe6dOR40VOrGz8PkzreVKNvEKnlE8t4yR8A8naL+t7A= +github.com/wailsapp/task/v3 v3.19.1 h1:syDKYaPBXgrXKKSJVEWcOEoSFtZzpvxqlHf90YRukRc= +github.com/wailsapp/task/v3 v3.19.1/go.mod h1:y7rWakbLR5gFElGgo6rA2dyr6vU/zNIDVfn3S4Of6OI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9 h1:RjggHMcaTVp0LOVZcW0bo8alwHrOaCrGUDgfWUHhnN4= @@ -63,18 +63,18 @@ golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+o golang.org/x/image v0.0.0-20201208152932-35266b937fa6 h1:nfeHNc1nAqecKCy2FCy4HY+soOOe5sDLJ/gZLbx6GYI= golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -85,5 +85,5 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -mvdan.cc/sh/v3 v3.6.0-0.dev.0.20220704111049-a6e3029cd899 h1:nwm4t5PtLlFd/H342GP50CtYf7vyMCOZkPx3g9shO0c= -mvdan.cc/sh/v3 v3.6.0-0.dev.0.20220704111049-a6e3029cd899/go.mod h1:1JcoyAKm1lZw/2bZje/iYKWicU/KMd0rsyJeKHnsK4E= +mvdan.cc/sh/v3 v3.6.0 h1:gtva4EXJ0dFNvl5bHjcUEvws+KRcDslT8VKheTYkbGU= +mvdan.cc/sh/v3 v3.6.0/go.mod h1:U4mhtBLZ32iWhif5/lD+ygy1zrgaQhUu+XFy7C8+TTA= diff --git a/exp/internal/commands/build_test.go b/exp/internal/commands/build_test.go deleted file mode 100644 index 669d99ae3..000000000 --- a/exp/internal/commands/build_test.go +++ /dev/null @@ -1,30 +0,0 @@ -package commands - -import "testing" - -func TestBuild(t *testing.T) { - type args struct { - options *BuildOptions - } - tests := []struct { - name string - args args - wantErr bool - }{ - // TODO: Add test cases. - { - name: "TestBuild", - args: args{ - options: &BuildOptions{}, - }, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := Build(tt.args.options); (err != nil) != tt.wantErr { - t.Errorf("Build() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} diff --git a/exp/internal/commands/defaults.go b/exp/internal/commands/defaults.go new file mode 100644 index 000000000..0d7b6d0db --- /dev/null +++ b/exp/internal/commands/defaults.go @@ -0,0 +1,61 @@ +package commands + +import ( + _ "embed" + "os" +) + +//go:embed defaults/info.json +var Info []byte + +//go:embed defaults/wails.exe.manifest +var Manifest []byte + +//go:embed defaults/appicon.png +var AppIcon []byte + +//go:embed defaults/icons.ico +var IconsIco []byte + +//go:embed defaults/Info.plist +var InfoPlist []byte + +//go:embed defaults/Info.dev.plist +var InfoDevPlist []byte + +//go:embed defaults/icons.icns +var IconsIcns []byte + +var AllAssets = map[string][]byte{ + "info.json": Info, + "wails.exe.manifest": Manifest, + "appicon.png": AppIcon, + "icons.ico": IconsIco, + "Info.plist": InfoPlist, + "Info.dev.plist": InfoDevPlist, + "icons.icns": IconsIcns, +} + +type DefaultsOptions struct { + Dir string `description:"The directory to generate the files into"` +} + +func Defaults(options *DefaultsOptions) error { + dir := options.Dir + if dir == "" { + dir = "." + } + for filename, data := range AllAssets { + // If file exists, skip it + if _, err := os.Stat(dir + "/" + filename); err == nil { + println("Skipping " + filename) + continue + } + err := os.WriteFile(dir+"/"+filename, data, 0644) + if err != nil { + return err + } + println("Generated " + filename) + } + return nil +} diff --git a/exp/internal/commands/defaults/Info.dev.plist b/exp/internal/commands/defaults/Info.dev.plist new file mode 100644 index 000000000..02e7358ee --- /dev/null +++ b/exp/internal/commands/defaults/Info.dev.plist @@ -0,0 +1,32 @@ + + + + CFBundlePackageType + APPL + CFBundleName + {{.Info.ProductName}} + CFBundleExecutable + {{.Name}} + CFBundleIdentifier + com.wails.{{.Name}} + CFBundleVersion + {{.Info.ProductVersion}} + CFBundleGetInfoString + {{.Info.Comments}} + CFBundleShortVersionString + {{.Info.ProductVersion}} + CFBundleIconFile + iconfile + LSMinimumSystemVersion + 10.13.0 + NSHighResolutionCapable + true + NSHumanReadableCopyright + {{.Info.Copyright}} + NSAppTransportSecurity + + NSAllowsLocalNetworking + + + + \ No newline at end of file diff --git a/exp/internal/commands/defaults/Info.plist b/exp/internal/commands/defaults/Info.plist new file mode 100644 index 000000000..e7819a7e8 --- /dev/null +++ b/exp/internal/commands/defaults/Info.plist @@ -0,0 +1,27 @@ + + + + CFBundlePackageType + APPL + CFBundleName + {{.Info.ProductName}} + CFBundleExecutable + {{.Name}} + CFBundleIdentifier + com.wails.{{.Name}} + CFBundleVersion + {{.Info.ProductVersion}} + CFBundleGetInfoString + {{.Info.Comments}} + CFBundleShortVersionString + {{.Info.ProductVersion}} + CFBundleIconFile + iconfile + LSMinimumSystemVersion + 10.13.0 + NSHighResolutionCapable + true + NSHumanReadableCopyright + {{.Info.Copyright}} + + \ No newline at end of file diff --git a/exp/internal/commands/defaults/appicon.png b/exp/internal/commands/defaults/appicon.png new file mode 100644 index 0000000000000000000000000000000000000000..63617fe4f746b8a878bd5f44725f4f317b9d9850 GIT binary patch literal 132625 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
Z$JW0DOlL20V{t8MUf8#bsNs5Czy`1 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 z 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 DB$9&s literal 0 HcmV?d00001 diff --git a/exp/internal/commands/defaults/icons.icns b/exp/internal/commands/defaults/icons.icns new file mode 100644 index 0000000000000000000000000000000000000000..1b5bd4c86c4533471d6044c5edc0c8c86b87e612 GIT binary patch literal 356592 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

^Lg7K@^M66wF^U#m6$MQA`NxZ%~uf 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 KmPKi1yf9{GFYLn7< + + + + + + + + + + true/pm + permonitorv2,permonitor + + + \ No newline at end of file diff --git a/exp/internal/commands/examples/examples.go b/exp/internal/commands/examples/examples.go deleted file mode 100644 index 01b1b9a2c..000000000 --- a/exp/internal/commands/examples/examples.go +++ /dev/null @@ -1,15 +0,0 @@ -package examples - -import _ "embed" - -//go:embed info.json -var Info []byte - -//go:embed wails.exe.manifest -var Manifest []byte - -//go:embed appicon.png -var AppIcon []byte - -//go:embed icon.ico -var IconIco []byte diff --git a/exp/internal/commands/icon.go b/exp/internal/commands/icons.go similarity index 87% rename from exp/internal/commands/icon.go rename to exp/internal/commands/icons.go index adaee64d0..dde3b8bfe 100644 --- a/exp/internal/commands/icon.go +++ b/exp/internal/commands/icons.go @@ -10,10 +10,9 @@ import ( "github.com/jackmordaunt/icns/v2" "github.com/leaanthony/winicon" - "github.com/wailsapp/wails/exp/internal/commands/examples" ) -type IconOptions struct { +type IconsOptions struct { Example bool `description:"Generate example icon file (appicon.png) in the current directory"` Input string `description:"The input image file"` Sizes string `description:"The sizes to generate in .ico file (comma separated)"` @@ -21,15 +20,15 @@ type IconOptions struct { MacFilename string `description:"The output filename for the Mac icon bundle"` } -func (i *IconOptions) Default() *IconOptions { - return &IconOptions{ +func (i *IconsOptions) Default() *IconsOptions { + return &IconsOptions{ Sizes: "256,128,64,48,32,16", MacFilename: "icons.icns", WindowsFilename: "icons.ico", } } -func GenerateIcon(options *IconOptions) error { +func GenerateIcons(options *IconsOptions) error { if options.Example { return generateExampleIcon() @@ -76,7 +75,7 @@ func GenerateIcon(options *IconOptions) error { } func generateExampleIcon() error { - return os.WriteFile("appicon.png", []byte(examples.AppIcon), 0644) + return os.WriteFile("appicon.png", []byte(AppIcon), 0644) } func parseSizes(sizes string) ([]int, error) { @@ -98,7 +97,7 @@ func parseSizes(sizes string) ([]int, error) { return result, nil } -func generateMacIcon(iconData []byte, options *IconOptions) error { +func generateMacIcon(iconData []byte, options *IconsOptions) error { srcImg, _, err := image.Decode(bytes.NewBuffer(iconData)) if err != nil { @@ -119,7 +118,7 @@ func generateMacIcon(iconData []byte, options *IconOptions) error { return icns.Encode(dest, srcImg) } -func generateWindowsIcon(iconData []byte, sizes []int, options *IconOptions) error { +func generateWindowsIcon(iconData []byte, sizes []int, options *IconsOptions) error { var output bytes.Buffer diff --git a/exp/internal/commands/icon_test.go b/exp/internal/commands/icons_test.go similarity index 90% rename from exp/internal/commands/icon_test.go rename to exp/internal/commands/icons_test.go index 4a911bfc2..a41e1bd6c 100644 --- a/exp/internal/commands/icon_test.go +++ b/exp/internal/commands/icons_test.go @@ -11,14 +11,14 @@ import ( func TestGenerateIcon(t *testing.T) { tests := []struct { name string - setup func() *IconOptions + setup func() *IconsOptions wantErr bool test func() error }{ { name: "should generate an icon when using the `example` flag", - setup: func() *IconOptions { - return &IconOptions{ + setup: func() *IconsOptions { + return &IconsOptions{ Example: true, } }, @@ -47,13 +47,13 @@ func TestGenerateIcon(t *testing.T) { }, { name: "should generate a .ico file when using the `input` flag and `windowsfilena me` flag", - setup: func() *IconOptions { + setup: func() *IconsOptions { // Get the directory of this file _, thisFile, _, _ := runtime.Caller(1) localDir := filepath.Dir(thisFile) // Get the path to the example icon exampleIcon := filepath.Join(localDir, "examples", "appicon.png") - return &IconOptions{ + return &IconsOptions{ Input: exampleIcon, WindowsFilename: "appicon.ico", } @@ -89,13 +89,13 @@ func TestGenerateIcon(t *testing.T) { }, { name: "should generate a .icns file when using the `input` flag and `macfilename` flag", - setup: func() *IconOptions { + setup: func() *IconsOptions { // Get the directory of this file _, thisFile, _, _ := runtime.Caller(1) localDir := filepath.Dir(thisFile) // Get the path to the example icon exampleIcon := filepath.Join(localDir, "examples", "appicon.png") - return &IconOptions{ + return &IconsOptions{ Input: exampleIcon, MacFilename: "appicon.icns", } @@ -128,13 +128,13 @@ func TestGenerateIcon(t *testing.T) { }, { name: "should generate a small .ico file when using the `input` flag and `sizes` flag", - setup: func() *IconOptions { + setup: func() *IconsOptions { // Get the directory of this file _, thisFile, _, _ := runtime.Caller(1) localDir := filepath.Dir(thisFile) // Get the path to the example icon exampleIcon := filepath.Join(localDir, "examples", "appicon.png") - return &IconOptions{ + return &IconsOptions{ Input: exampleIcon, Sizes: "16", WindowsFilename: "appicon.ico", @@ -169,20 +169,20 @@ func TestGenerateIcon(t *testing.T) { }, { name: "should error if no input file is provided", - setup: func() *IconOptions { - return &IconOptions{} + setup: func() *IconsOptions { + return &IconsOptions{} }, wantErr: true, }, { name: "should error if neither mac or windows filename is provided", - setup: func() *IconOptions { + setup: func() *IconsOptions { // Get the directory of this file _, thisFile, _, _ := runtime.Caller(1) localDir := filepath.Dir(thisFile) // Get the path to the example icon exampleIcon := filepath.Join(localDir, "examples", "appicon.png") - return &IconOptions{ + return &IconsOptions{ Input: exampleIcon, } }, @@ -190,13 +190,13 @@ func TestGenerateIcon(t *testing.T) { }, { name: "should error if bad sizes provided", - setup: func() *IconOptions { + setup: func() *IconsOptions { // Get the directory of this file _, thisFile, _, _ := runtime.Caller(1) localDir := filepath.Dir(thisFile) // Get the path to the example icon exampleIcon := filepath.Join(localDir, "examples", "appicon.png") - return &IconOptions{ + return &IconsOptions{ Input: exampleIcon, WindowsFilename: "appicon.ico", Sizes: "bad", @@ -206,13 +206,13 @@ func TestGenerateIcon(t *testing.T) { }, { name: "should ignore 0 size", - setup: func() *IconOptions { + setup: func() *IconsOptions { // Get the directory of this file _, thisFile, _, _ := runtime.Caller(1) localDir := filepath.Dir(thisFile) // Get the path to the example icon exampleIcon := filepath.Join(localDir, "examples", "appicon.png") - return &IconOptions{ + return &IconsOptions{ Input: exampleIcon, WindowsFilename: "appicon.ico", Sizes: "0,16", @@ -245,8 +245,8 @@ func TestGenerateIcon(t *testing.T) { }, { name: "should error if the input file does not exist", - setup: func() *IconOptions { - return &IconOptions{ + setup: func() *IconsOptions { + return &IconsOptions{ Input: "doesnotexist.png", WindowsFilename: "appicon.ico", } @@ -255,10 +255,10 @@ func TestGenerateIcon(t *testing.T) { }, { name: "should error if the input file is not a png", - setup: func() *IconOptions { + setup: func() *IconsOptions { // Get the directory of this file _, thisFile, _, _ := runtime.Caller(1) - return &IconOptions{ + return &IconsOptions{ Input: thisFile, WindowsFilename: "appicon.ico", } @@ -270,7 +270,7 @@ func TestGenerateIcon(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { options := tt.setup() - err := GenerateIcon(options) + err := GenerateIcons(options) if (err != nil) != tt.wantErr { t.Errorf("GenerateIcon() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/exp/internal/commands/build.go b/exp/internal/commands/run.go similarity index 54% rename from exp/internal/commands/build.go rename to exp/internal/commands/run.go index ef610ec27..7db761ddf 100644 --- a/exp/internal/commands/build.go +++ b/exp/internal/commands/run.go @@ -2,22 +2,27 @@ package commands import ( "context" + "fmt" "github.com/go-task/task/v3" "github.com/go-task/task/v3/taskfile" ) -type BuildOptions struct { +type RunOptions struct { + Task string `name:"t" description:"The name of the task to run"` } -func Build(options *BuildOptions) error { +func Run(options *RunOptions) error { + if options.Task == "" { + return fmt.Errorf("task name is required") + } e := task.Executor{} err := e.Setup() if err != nil { return err } build := taskfile.Call{ - Task: "build", + Task: options.Task, Vars: nil, } return e.Run(context.Background(), build) diff --git a/exp/internal/commands/run_test.go b/exp/internal/commands/run_test.go new file mode 100644 index 000000000..57226bca3 --- /dev/null +++ b/exp/internal/commands/run_test.go @@ -0,0 +1,38 @@ +package commands + +import "testing" + +func TestBuild(t *testing.T) { + type args struct { + options *RunOptions + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "should error if task name not provided", + args: args{ + options: &RunOptions{}, + }, + wantErr: true, + }, + { + name: "should work if task name provided", + args: args{ + options: &RunOptions{ + Task: "build", + }, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := Run(tt.args.options); (err != nil) != tt.wantErr { + t.Errorf("Run() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/exp/internal/commands/syso.go b/exp/internal/commands/syso.go index 858367873..70821789f 100644 --- a/exp/internal/commands/syso.go +++ b/exp/internal/commands/syso.go @@ -7,7 +7,6 @@ import ( "github.com/tc-hib/winres" "github.com/tc-hib/winres/version" - "github.com/wailsapp/wails/exp/internal/commands/examples" ) type SysoOptions struct { @@ -21,8 +20,7 @@ type SysoOptions struct { func (i *SysoOptions) Default() *SysoOptions { return &SysoOptions{ - Arch: runtime.GOOS, - Out: "wails-res.syso", + Arch: runtime.GOARCH, } } @@ -85,7 +83,7 @@ func GenerateSyso(options *SysoOptions) error { targetFile := options.Out if targetFile == "" { - targetFile = "wails-res.syso" + targetFile = "rsrc_windows_" + options.Arch + ".syso" } fout, err := os.Create(targetFile) if err != nil { @@ -112,12 +110,12 @@ func GenerateSyso(options *SysoOptions) error { func generateExampleSyso() error { // Generate example info.json - err := os.WriteFile("info.json", examples.Info, 0644) + err := os.WriteFile("info.json", Info, 0644) if err != nil { return err } // Generate example manifest - err = os.WriteFile("wails.exe.manifest", examples.Manifest, 0644) + err = os.WriteFile("wails.exe.manifest", Manifest, 0644) if err != nil { return err } From b5127d95ff104946b125855762204f58d0f0d260 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 4 Jan 2023 20:12:28 +1100 Subject: [PATCH 69/85] Add EnableFraudulentWebsiteWarnings feature Co-authored-by: stffabi --- exp/pkg/application/webview_window_darwin.go | 8 ++-- exp/pkg/options/window.go | 45 ++++++++++---------- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/exp/pkg/application/webview_window_darwin.go b/exp/pkg/application/webview_window_darwin.go index b2a153e84..5fd193d38 100644 --- a/exp/pkg/application/webview_window_darwin.go +++ b/exp/pkg/application/webview_window_darwin.go @@ -16,7 +16,7 @@ package application extern void registerListener(unsigned int event); // Create a new Window -void* windowNew(unsigned int id, int width, int height) { +void* windowNew(unsigned int id, int width, int height, bool fraudulentWebsiteWarningEnabled) { NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, width-1, height-1) styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable backing:NSBackingStoreBuffered @@ -38,6 +38,9 @@ void* windowNew(unsigned int id, int width, int height) { WKWebViewConfiguration* config = [[WKWebViewConfiguration alloc] init]; config.suppressesIncrementalRendering = true; config.applicationNameForUserAgent = @"wails.io"; + if (@available(macOS 10.15, *)) { + config.preferences.fraudulentWebsiteWarningEnabled = fraudulentWebsiteWarningEnabled; + } // Setup user content controller WKUserContentController* userContentController = [WKUserContentController new]; @@ -838,7 +841,6 @@ func (w *macosWebviewWindow) restoreWindow() { } func (w *macosWebviewWindow) execJS(js string) { - println("execJS called on WebviewWindow", w.parent.id) C.windowExecJS(w.nsWindow, C.CString(js)) } @@ -924,7 +926,7 @@ func (w *macosWebviewWindow) run() { w.on(eventId) } globalApplication.dispatchOnMainThread(func() { - w.nsWindow = C.windowNew(C.uint(w.parent.id), C.int(w.parent.options.Width), C.int(w.parent.options.Height)) + w.nsWindow = C.windowNew(C.uint(w.parent.id), C.int(w.parent.options.Width), C.int(w.parent.options.Height), C.bool(w.parent.options.EnableFraudulentWebsiteWarnings)) w.setFrameless(w.parent.options.Frameless) w.setTitle(w.parent.options.Title) w.setAlwaysOnTop(w.parent.options.AlwaysOnTop) diff --git a/exp/pkg/options/window.go b/exp/pkg/options/window.go index e1ef9f558..195168f47 100644 --- a/exp/pkg/options/window.go +++ b/exp/pkg/options/window.go @@ -16,28 +16,29 @@ const ( type WebviewWindow struct { // Alias is a human-readable name for the window. This can be used to reference the window in the frontend. - Alias string - Title string - Width, Height int - AlwaysOnTop bool - URL string - DisableResize bool - Frameless bool - MinWidth int - MinHeight int - MaxWidth int - MaxHeight int - StartState WindowState - Mac MacWindow - BackgroundColour *RGBA - Assets Assets - HTML string - JS string - CSS string - X int - Y int - FullscreenButtonEnabled bool - Hidden bool + Alias string + Title string + Width, Height int + AlwaysOnTop bool + URL string + DisableResize bool + Frameless bool + MinWidth int + MinHeight int + MaxWidth int + MaxHeight int + StartState WindowState + Mac MacWindow + BackgroundColour *RGBA + Assets Assets + HTML string + JS string + CSS string + X int + Y int + FullscreenButtonEnabled bool + Hidden bool + EnableFraudulentWebsiteWarnings bool } var WindowDefaults = &WebviewWindow{ From d1e2ee452f1e00e5d7fe3fedfb5c2f95c9cfd70e Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Thu, 5 Jan 2023 15:02:08 +1100 Subject: [PATCH 70/85] Integrate Task --- exp/cmd/wails/main.go | 11 +++- exp/examples/build/Taskfile.yml | 4 ++ exp/go.mod | 10 +++ exp/go.sum | 66 +++++++++++++++++++ exp/internal/commands/run.go | 29 -------- exp/internal/commands/task.go | 63 ++++++++++++++++++ .../commands/{run_test.go => task_test.go} | 10 +-- 7 files changed, 156 insertions(+), 37 deletions(-) delete mode 100644 exp/internal/commands/run.go create mode 100644 exp/internal/commands/task.go rename exp/internal/commands/{run_test.go => task_test.go} (74%) diff --git a/exp/cmd/wails/main.go b/exp/cmd/wails/main.go index 88d9d1ce6..939ced765 100644 --- a/exp/cmd/wails/main.go +++ b/exp/cmd/wails/main.go @@ -1,7 +1,9 @@ package main import ( - "log" + "os" + + "github.com/pterm/pterm" "github.com/leaanthony/clir" "github.com/wailsapp/wails/exp/internal/commands" @@ -10,13 +12,16 @@ import ( func main() { app := clir.NewCli("wails", "The Wails CLI", "v3") app.NewSubCommandFunction("init", "Initialise a new project", commands.Init) - app.NewSubCommandFunction("run", "Run a task", commands.Run) + task := app.NewSubCommand("task", "Run and list tasks") + task.NewSubCommandFunction("run", "Run a task", commands.RunTask) + task.NewSubCommandFunction("list", "List tasks", commands.ListTasks) generate := app.NewSubCommand("generate", "Generation tools") generate.NewSubCommandFunction("defaults", "Generate default build assets", commands.Defaults) generate.NewSubCommandFunction("icons", "Generate icons", commands.GenerateIcons) generate.NewSubCommandFunction("syso", "Generate Windows .syso file", commands.GenerateSyso) err := app.Run() if err != nil { - log.Fatalln(err) + pterm.Error.Println(err) + os.Exit(1) } } diff --git a/exp/examples/build/Taskfile.yml b/exp/examples/build/Taskfile.yml index dfb9020b7..316d18473 100644 --- a/exp/examples/build/Taskfile.yml +++ b/exp/examples/build/Taskfile.yml @@ -2,6 +2,7 @@ version: '3' tasks: build: + summary: Builds the application cmds: - go build -gcflags=all="-N -l" -o bin/testapp main.go vars: @@ -11,16 +12,19 @@ tasks: CGO_LDFLAGS: "-mmacosx-version-min=10.13" generate-icons: + summary: Generates Windows `.ico` and Mac `.icns` files from an image dir: build cmds: # Generates both .ico and .icns files - wails generate icon -input appicon.png build-prod: + summary: Creates a production build of the application cmds: - go build -tags production -ldflags="-w -s" -o bin/testapp package-darwin: + summary: Packages a production build of the application into a `.app` deps: - build-prod - generate-icons diff --git a/exp/go.mod b/exp/go.mod index 8cbac8f59..fb6083c8a 100644 --- a/exp/go.mod +++ b/exp/go.mod @@ -7,26 +7,36 @@ require ( github.com/jackmordaunt/icns/v2 v2.2.1 github.com/leaanthony/clir v1.3.0 github.com/leaanthony/winicon v1.0.0 + github.com/pterm/pterm v0.12.51 github.com/tc-hib/winres v0.1.6 ) require ( + atomicgo.dev/cursor v0.1.1 // indirect + atomicgo.dev/keyboard v0.2.8 // indirect + github.com/containerd/console v1.0.3 // indirect github.com/fatih/color v1.13.0 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect + github.com/gookit/color v1.5.2 // indirect github.com/joho/godotenv v1.4.0 // indirect + github.com/lithammer/fuzzysearch v1.1.5 // indirect github.com/mattn/go-colorable v0.1.11 // indirect github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mattn/go-runewidth v0.0.14 // indirect github.com/mattn/go-zglob v0.0.4 // indirect github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/radovskyb/watcher v1.0.7 // indirect + github.com/rivo/uniseg v0.2.0 // indirect github.com/sajari/fuzzy v1.0.0 // indirect + github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9 // indirect golang.org/x/image v0.0.0-20201208152932-35266b937fa6 // indirect golang.org/x/sync v0.1.0 // indirect golang.org/x/sys v0.3.0 // indirect golang.org/x/term v0.3.0 // indirect + golang.org/x/text v0.4.0 // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/yaml.v3 v3.0.1 // indirect mvdan.cc/sh/v3 v3.6.0 // indirect diff --git a/exp/go.sum b/exp/go.sum index b3f3eb5e6..4a415d043 100644 --- a/exp/go.sum +++ b/exp/go.sum @@ -1,3 +1,19 @@ +atomicgo.dev/assert v0.0.2 h1:FiKeMiZSgRrZsPo9qn/7vmr7mCsh5SZyXY4YGYiYwrg= +atomicgo.dev/cursor v0.1.1 h1:0t9sxQomCTRh5ug+hAMCs59x/UmC9QL6Ci5uosINKD4= +atomicgo.dev/cursor v0.1.1/go.mod h1:Lr4ZJB3U7DfPPOkbH7/6TOtJ4vFGHlgj1nc+n900IpU= +atomicgo.dev/keyboard v0.2.8 h1:Di09BitwZgdTV1hPyX/b9Cqxi8HVuJQwWivnZUEqlj4= +atomicgo.dev/keyboard v0.2.8/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ= +github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs= +github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8= +github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII= +github.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSrDrXDpX2bG66k= +github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzXjB69adAhzZkI= +github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/2oUqKc6bF2c= +github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE= +github.com/MarvinJWendt/testza v0.5.1 h1:a9Fqx6vQrHQ4CyiaLhktfTTelwGotmFWy8MNhyaohw8= +github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= +github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= +github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -8,11 +24,20 @@ github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0X github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= +github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= +github.com/gookit/color v1.5.2 h1:uLnfXcaFjlrDnQDT+NCBcfhrXqYTx/rcCa6xn01Y8yI= +github.com/gookit/color v1.5.2/go.mod h1:w8h4bGiHeeBpvQVePTutdbERIUf3oJE5lZ8HM0UgXyg= github.com/jackmordaunt/icns/v2 v2.2.1 h1:MGklwYP2yohKn2Bw7XxlF69LZe98S1vUfl5OvAulPwg= github.com/jackmordaunt/icns/v2 v2.2.1/go.mod h1:6aYIB9eSzyfHHMKqDf17Xrs1zetQPReAkiUSHzdw4cI= github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= +github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= +github.com/klauspost/cpuid/v2 v2.2.0 h1:4ZexSFt8agMNzNisrsilL6RClWDC5YJnLHNIfTy4iuc= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -22,12 +47,17 @@ github.com/leaanthony/clir v1.3.0 h1:L9nPDWrmc/qU9UWZZvRaFajWYuO0np9V5p+5gxyYno0 github.com/leaanthony/clir v1.3.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= github.com/leaanthony/winicon v1.0.0 h1:ZNt5U5dY71oEoKZ97UVwJRT4e+5xo5o/ieKuHuk8NqQ= github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU= +github.com/lithammer/fuzzysearch v1.1.5 h1:Ag7aKU08wp0R9QCfF4GoGST9HbmAIeLP7xwMrOBEp1c= +github.com/lithammer/fuzzysearch v1.1.5/go.mod h1:1R1LRNk7yKid1BaQkmuLQaHruxcC4HmAH30Dh61Ih1Q= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-zglob v0.0.4 h1:LQi2iOm0/fGgu80AioIJ/1j9w9Oh+9DZ39J4VAGzHQM= github.com/mattn/go-zglob v0.0.4/go.mod h1:MxxjyoXXnMxfIpxTK2GAkw1w8glPsQILx3N5wrKakiY= github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= @@ -40,21 +70,41 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI= +github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg= +github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE= +github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEejaWgXU= +github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE= +github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8= +github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s= +github.com/pterm/pterm v0.12.51 h1:iwhNG1FhQMgks+5kVyr/ClRk3WJCuL907nJN7RqmEpw= +github.com/pterm/pterm v0.12.51/go.mod h1:79BLm4vos2z+eOoHnDG7ZWuYtLaSStyaspKjGmSoxc4= github.com/radovskyb/watcher v1.0.7 h1:AYePLih6dpmS32vlHfhCeli8127LzkIgwJGcwwe8tUE= github.com/radovskyb/watcher v1.0.7/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm+ZuvsUYIg= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/sajari/fuzzy v1.0.0 h1:+FmwVvJErsd0d0hAPlj4CxqxUtQY/fOoY0DwX4ykpRY= github.com/sajari/fuzzy v1.0.0/go.mod h1:OjYR6KxoWOe9+dOlXeiCJd4dIbED4Oo8wpS89o0pwOo= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/tc-hib/winres v0.1.6 h1:qgsYHze+BxQPEYilxIz/KCQGaClvI2+yLBAZs+3+0B8= github.com/tc-hib/winres v0.1.6/go.mod h1:pe6dOR40VOrGz8PkzreVKNvEKnlE8t4yR8A8naL+t7A= github.com/wailsapp/task/v3 v3.19.1 h1:syDKYaPBXgrXKKSJVEWcOEoSFtZzpvxqlHf90YRukRc= github.com/wailsapp/task/v3 v3.19.1/go.mod h1:y7rWakbLR5gFElGgo6rA2dyr6vU/zNIDVfn3S4Of6OI= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9 h1:RjggHMcaTVp0LOVZcW0bo8alwHrOaCrGUDgfWUHhnN4= @@ -69,20 +119,36 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= mvdan.cc/sh/v3 v3.6.0 h1:gtva4EXJ0dFNvl5bHjcUEvws+KRcDslT8VKheTYkbGU= diff --git a/exp/internal/commands/run.go b/exp/internal/commands/run.go deleted file mode 100644 index 7db761ddf..000000000 --- a/exp/internal/commands/run.go +++ /dev/null @@ -1,29 +0,0 @@ -package commands - -import ( - "context" - "fmt" - - "github.com/go-task/task/v3" - "github.com/go-task/task/v3/taskfile" -) - -type RunOptions struct { - Task string `name:"t" description:"The name of the task to run"` -} - -func Run(options *RunOptions) error { - if options.Task == "" { - return fmt.Errorf("task name is required") - } - e := task.Executor{} - err := e.Setup() - if err != nil { - return err - } - build := taskfile.Call{ - Task: options.Task, - Vars: nil, - } - return e.Run(context.Background(), build) -} diff --git a/exp/internal/commands/task.go b/exp/internal/commands/task.go new file mode 100644 index 000000000..67c4f9fa3 --- /dev/null +++ b/exp/internal/commands/task.go @@ -0,0 +1,63 @@ +package commands + +import ( + "context" + "fmt" + + "github.com/pterm/pterm" + + "github.com/go-task/task/v3" + "github.com/go-task/task/v3/taskfile" +) + +type RunTaskOptions struct { + Name string `name:"n" description:"The name of the task to run"` +} + +func RunTask(options *RunTaskOptions) error { + if options.Name == "" { + return fmt.Errorf("name of task required") + } + + e := task.Executor{} + err := e.Setup() + if err != nil { + return err + } + build := taskfile.Call{ + Task: options.Name, + Vars: nil, + } + return e.Run(context.Background(), build) +} + +type ListTaskOptions struct { +} + +func ListTasks(options *ListTaskOptions) error { + e := task.Executor{} + if err := e.Setup(); err != nil { + return err + } + tasks := e.GetTaskList() + if len(tasks) == 0 { + return fmt.Errorf("no tasks found. Ensure there is a `Taskfile.yml` in your project. You can generate a default takfile by running `wails generate defaults`") + } + tableData := [][]string{ + {"Task", "Summary"}, + } + println() + + for _, thisTask := range tasks { + var thisRow = make([]string, 2) + thisRow[0] = thisTask.Task + thisRow[1] = thisTask.Summary + tableData = append(tableData, thisRow) + } + err := pterm.DefaultTable.WithHasHeader(true).WithHeaderRowSeparator("-").WithData(tableData).Render() + if err != nil { + return err + } + println() + return nil +} diff --git a/exp/internal/commands/run_test.go b/exp/internal/commands/task_test.go similarity index 74% rename from exp/internal/commands/run_test.go rename to exp/internal/commands/task_test.go index 57226bca3..df365c99c 100644 --- a/exp/internal/commands/run_test.go +++ b/exp/internal/commands/task_test.go @@ -4,7 +4,7 @@ import "testing" func TestBuild(t *testing.T) { type args struct { - options *RunOptions + options *RunTaskOptions } tests := []struct { name string @@ -14,15 +14,15 @@ func TestBuild(t *testing.T) { { name: "should error if task name not provided", args: args{ - options: &RunOptions{}, + options: &RunTaskOptions{}, }, wantErr: true, }, { name: "should work if task name provided", args: args{ - options: &RunOptions{ - Task: "build", + options: &RunTaskOptions{ + Name: "build", }, }, wantErr: true, @@ -30,7 +30,7 @@ func TestBuild(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := Run(tt.args.options); (err != nil) != tt.wantErr { + if err := RunTask(tt.args.options); (err != nil) != tt.wantErr { t.Errorf("Run() error = %v, wantErr %v", err, tt.wantErr) } }) From 54805d99a0d105ee39cbbc87de9afc7f78c283cb Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Fri, 6 Jan 2023 20:19:20 +1100 Subject: [PATCH 71/85] Remove `New` from Dialog methods --- exp/examples/build/main.go | 16 ++--- exp/examples/clipboard/main.go | 12 ++-- exp/examples/dialogs/main.go | 108 ++++++++++++++--------------- exp/examples/systray/main.go | 2 +- exp/examples/window/main.go | 16 ++--- exp/pkg/application/application.go | 14 ++-- 6 files changed, 84 insertions(+), 84 deletions(-) diff --git a/exp/examples/build/main.go b/exp/examples/build/main.go index 6a9f1f9c8..269d324c0 100755 --- a/exp/examples/build/main.go +++ b/exp/examples/build/main.go @@ -137,7 +137,7 @@ func main() { sizeMenu.Add("Get Current WebviewWindow Size").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.WebviewWindow) { width, height := w.Size() - app.NewInfoDialog().SetTitle("Current WebviewWindow Size").SetMessage("Width: " + strconv.Itoa(width) + " Height: " + strconv.Itoa(height)).Show() + app.InfoDialog().SetTitle("Current WebviewWindow Size").SetMessage("Width: " + strconv.Itoa(width) + " Height: " + strconv.Itoa(height)).Show() }) }) @@ -168,7 +168,7 @@ func main() { positionMenu.Add("Get Position").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.WebviewWindow) { x, y := w.Position() - app.NewInfoDialog().SetTitle("Current WebviewWindow Position").SetMessage("X: " + strconv.Itoa(x) + " Y: " + strconv.Itoa(y)).Show() + app.InfoDialog().SetTitle("Current WebviewWindow Position").SetMessage("X: " + strconv.Itoa(x) + " Y: " + strconv.Itoa(y)).Show() }) }) @@ -235,32 +235,32 @@ func main() { stateMenu.Add("Get Primary Screen").OnClick(func(ctx *application.Context) { screen, err := app.GetPrimaryScreen() if err != nil { - app.NewErrorDialog().SetTitle("Error").SetMessage(err.Error()).Show() + app.ErrorDialog().SetTitle("Error").SetMessage(err.Error()).Show() return } msg := fmt.Sprintf("Screen: %+v", screen) - app.NewInfoDialog().SetTitle("Primary Screen").SetMessage(msg).Show() + app.InfoDialog().SetTitle("Primary Screen").SetMessage(msg).Show() }) stateMenu.Add("Get Screens").OnClick(func(ctx *application.Context) { screens, err := app.GetScreens() if err != nil { - app.NewErrorDialog().SetTitle("Error").SetMessage(err.Error()).Show() + app.ErrorDialog().SetTitle("Error").SetMessage(err.Error()).Show() return } for _, screen := range screens { msg := fmt.Sprintf("Screen: %+v", screen) - app.NewInfoDialog().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show() + app.InfoDialog().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show() } }) stateMenu.Add("Get Screen for WebviewWindow").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.WebviewWindow) { screen, err := w.GetScreen() if err != nil { - app.NewErrorDialog().SetTitle("Error").SetMessage(err.Error()).Show() + app.ErrorDialog().SetTitle("Error").SetMessage(err.Error()).Show() return } msg := fmt.Sprintf("Screen: %+v", screen) - app.NewInfoDialog().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show() + app.InfoDialog().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show() }) }) app.NewWebviewWindow() diff --git a/exp/examples/clipboard/main.go b/exp/examples/clipboard/main.go index 28c0de15c..e0afcb856 100644 --- a/exp/examples/clipboard/main.go +++ b/exp/examples/clipboard/main.go @@ -28,34 +28,34 @@ func main() { setClipboardMenu.Add("Set Text 'Hello'").OnClick(func(ctx *application.Context) { success := app.Clipboard().SetText("Hello") if !success { - app.NewInfoDialog().SetMessage("Failed to set clipboard text").Show() + app.InfoDialog().SetMessage("Failed to set clipboard text").Show() } }) setClipboardMenu.Add("Set Text 'World'").OnClick(func(ctx *application.Context) { success := app.Clipboard().SetText("World") if !success { - app.NewInfoDialog().SetMessage("Failed to set clipboard text").Show() + app.InfoDialog().SetMessage("Failed to set clipboard text").Show() } }) setClipboardMenu.Add("Set Text (current time)").OnClick(func(ctx *application.Context) { success := app.Clipboard().SetText(time.Now().String()) if !success { - app.NewInfoDialog().SetMessage("Failed to set clipboard text").Show() + app.InfoDialog().SetMessage("Failed to set clipboard text").Show() } }) getClipboardMenu := menu.AddSubmenu("Get Clipboard") getClipboardMenu.Add("Get Text").OnClick(func(ctx *application.Context) { result := app.Clipboard().Text() - app.NewInfoDialog().SetMessage("Got:\n\n" + result).Show() + app.InfoDialog().SetMessage("Got:\n\n" + result).Show() }) clearClipboardMenu := menu.AddSubmenu("Clear Clipboard") clearClipboardMenu.Add("Clear Text").OnClick(func(ctx *application.Context) { success := app.Clipboard().SetText("") if success { - app.NewInfoDialog().SetMessage("Clipboard text cleared").Show() + app.InfoDialog().SetMessage("Clipboard text cleared").Show() } else { - app.NewInfoDialog().SetMessage("Clipboard text not cleared").Show() + app.InfoDialog().SetMessage("Clipboard text not cleared").Show() } }) diff --git a/exp/examples/dialogs/main.go b/exp/examples/dialogs/main.go index fe43d3a99..eaf8aae58 100644 --- a/exp/examples/dialogs/main.go +++ b/exp/examples/dialogs/main.go @@ -28,23 +28,23 @@ func main() { // Let's make a "Demo" menu infoMenu := menu.AddSubmenu("Info") infoMenu.Add("Info").OnClick(func(ctx *application.Context) { - dialog := app.NewInfoDialog() + dialog := app.InfoDialog() dialog.SetTitle("Custom Title") dialog.SetMessage("This is a custom message") dialog.Show() }) infoMenu.Add("Info (Title only)").OnClick(func(ctx *application.Context) { - dialog := app.NewInfoDialog() + dialog := app.InfoDialog() dialog.SetTitle("Custom Title") dialog.Show() }) infoMenu.Add("Info (Message only)").OnClick(func(ctx *application.Context) { - dialog := app.NewInfoDialog() + dialog := app.InfoDialog() dialog.SetMessage("This is a custom message") dialog.Show() }) infoMenu.Add("Info (Custom Icon)").OnClick(func(ctx *application.Context) { - dialog := app.NewInfoDialog() + dialog := app.InfoDialog() dialog.SetTitle("Custom Icon Example") dialog.SetMessage("Using a custom icon") dialog.SetIcon(application.DefaultApplicationIcon) @@ -53,14 +53,14 @@ func main() { questionMenu := menu.AddSubmenu("Question") questionMenu.Add("Question (No default)").OnClick(func(ctx *application.Context) { - dialog := app.NewQuestionDialog() + dialog := app.QuestionDialog() dialog.SetMessage("No default button") dialog.AddButton("Yes") dialog.AddButton("No") dialog.Show() }) questionMenu.Add("Question (With Default)").OnClick(func(ctx *application.Context) { - dialog := app.NewQuestionDialog() + dialog := app.QuestionDialog() dialog.SetTitle("Quit") dialog.SetMessage("You have unsaved work. Are you sure you want to quit?") dialog.AddButton("Yes").OnClick(func() { @@ -71,12 +71,12 @@ func main() { dialog.Show() }) questionMenu.Add("Question (With Cancel)").OnClick(func(ctx *application.Context) { - dialog := app.NewQuestionDialog(). + dialog := app.QuestionDialog(). SetTitle("Update"). SetMessage("The cancel button is selected when pressing escape") download := dialog.AddButton("📥 Download") download.OnClick(func() { - app.NewInfoDialog().SetMessage("Downloading...").Show() + app.InfoDialog().SetMessage("Downloading...").Show() }) no := dialog.AddButton("Cancel") dialog.SetDefaultButton(download) @@ -84,7 +84,7 @@ func main() { dialog.Show() }) questionMenu.Add("Question (Custom Icon)").OnClick(func(ctx *application.Context) { - dialog := app.NewQuestionDialog() + dialog := app.QuestionDialog() dialog.SetTitle("Custom Icon Example") dialog.SetMessage("Using a custom icon") dialog.SetIcon(application.WailsLogoWhiteTransparent) @@ -95,23 +95,23 @@ func main() { warningMenu := menu.AddSubmenu("Warning") warningMenu.Add("Warning").OnClick(func(ctx *application.Context) { - dialog := app.NewWarningDialog() + dialog := app.WarningDialog() dialog.SetTitle("Custom Title") dialog.SetMessage("This is a custom message") dialog.Show() }) warningMenu.Add("Warning (Title only)").OnClick(func(ctx *application.Context) { - dialog := app.NewWarningDialog() + dialog := app.WarningDialog() dialog.SetTitle("Custom Title") dialog.Show() }) warningMenu.Add("Warning (Message only)").OnClick(func(ctx *application.Context) { - dialog := app.NewWarningDialog() + dialog := app.WarningDialog() dialog.SetMessage("This is a custom message") dialog.Show() }) warningMenu.Add("Warning (Custom Icon)").OnClick(func(ctx *application.Context) { - dialog := app.NewWarningDialog() + dialog := app.WarningDialog() dialog.SetTitle("Custom Icon Example") dialog.SetMessage("Using a custom icon") dialog.SetIcon(application.DefaultApplicationIcon) @@ -120,23 +120,23 @@ func main() { errorMenu := menu.AddSubmenu("Error") errorMenu.Add("Error").OnClick(func(ctx *application.Context) { - dialog := app.NewErrorDialog() + dialog := app.ErrorDialog() dialog.SetTitle("Ooops") dialog.SetMessage("I accidentally the whole of Twitter") dialog.Show() }) errorMenu.Add("Error (Title Only)").OnClick(func(ctx *application.Context) { - dialog := app.NewErrorDialog() + dialog := app.ErrorDialog() dialog.SetTitle("Custom Title") dialog.Show() }) errorMenu.Add("Error (Custom Message)").OnClick(func(ctx *application.Context) { - dialog := app.NewErrorDialog() + dialog := app.ErrorDialog() dialog.SetMessage("This is a custom message") dialog.Show() }) errorMenu.Add("Error (Custom Icon)").OnClick(func(ctx *application.Context) { - dialog := app.NewErrorDialog() + dialog := app.ErrorDialog() dialog.SetTitle("Custom Icon Example") dialog.SetMessage("Using a custom icon") dialog.SetIcon(application.WailsLogoWhite) @@ -145,87 +145,87 @@ func main() { openMenu := menu.AddSubmenu("Open") openMenu.Add("Open File").OnClick(func(ctx *application.Context) { - result, _ := app.NewOpenFileDialog(). + result, _ := app.OpenFileDialog(). CanChooseFiles(true). PromptForSingleSelection() if result != "" { - app.NewInfoDialog().SetMessage(result).Show() + app.InfoDialog().SetMessage(result).Show() } else { - app.NewInfoDialog().SetMessage("No file selected").Show() + app.InfoDialog().SetMessage("No file selected").Show() } }) openMenu.Add("Open File (Show Hidden Files)").OnClick(func(ctx *application.Context) { - result, _ := app.NewOpenFileDialog(). + result, _ := app.OpenFileDialog(). CanChooseFiles(true). CanCreateDirectories(true). ShowHiddenFiles(true). PromptForSingleSelection() if result != "" { - app.NewInfoDialog().SetMessage(result).Show() + app.InfoDialog().SetMessage(result).Show() } else { - app.NewInfoDialog().SetMessage("No file selected").Show() + app.InfoDialog().SetMessage("No file selected").Show() } }) openMenu.Add("Open File (Attach to window)").OnClick(func(ctx *application.Context) { - result, _ := app.NewOpenFileDialog(). + result, _ := app.OpenFileDialog(). CanChooseFiles(true). CanCreateDirectories(true). ShowHiddenFiles(true). AttachToWindow(app.CurrentWindow()). PromptForSingleSelection() if result != "" { - app.NewInfoDialog().SetMessage(result).Show() + app.InfoDialog().SetMessage(result).Show() } else { - app.NewInfoDialog().SetMessage("No file selected").Show() + app.InfoDialog().SetMessage("No file selected").Show() } }) openMenu.Add("Open Multiple Files (Show Hidden Files)").OnClick(func(ctx *application.Context) { - result, _ := app.NewOpenFileDialog(). + result, _ := app.OpenFileDialog(). CanChooseFiles(true). CanCreateDirectories(true). ShowHiddenFiles(true). PromptForMultipleSelection() if len(result) > 0 { - app.NewInfoDialog().SetMessage(strings.Join(result, ",")).Show() + app.InfoDialog().SetMessage(strings.Join(result, ",")).Show() } else { - app.NewInfoDialog().SetMessage("No file selected").Show() + app.InfoDialog().SetMessage("No file selected").Show() } }) openMenu.Add("Open Directory").OnClick(func(ctx *application.Context) { - result, _ := app.NewOpenFileDialog(). + result, _ := app.OpenFileDialog(). CanChooseDirectories(true). PromptForSingleSelection() if result != "" { - app.NewInfoDialog().SetMessage(result).Show() + app.InfoDialog().SetMessage(result).Show() } else { - app.NewInfoDialog().SetMessage("No directory selected").Show() + app.InfoDialog().SetMessage("No directory selected").Show() } }) openMenu.Add("Open Directory (Create Directories)").OnClick(func(ctx *application.Context) { - result, _ := app.NewOpenFileDialog(). + result, _ := app.OpenFileDialog(). CanChooseDirectories(true). CanCreateDirectories(true). PromptForSingleSelection() if result != "" { - app.NewInfoDialog().SetMessage(result).Show() + app.InfoDialog().SetMessage(result).Show() } else { - app.NewInfoDialog().SetMessage("No directory selected").Show() + app.InfoDialog().SetMessage("No directory selected").Show() } }) openMenu.Add("Open Directory (Resolves Aliases)").OnClick(func(ctx *application.Context) { - result, _ := app.NewOpenFileDialog(). + result, _ := app.OpenFileDialog(). CanChooseDirectories(true). CanCreateDirectories(true). ResolvesAliases(true). PromptForSingleSelection() if result != "" { - app.NewInfoDialog().SetMessage(result).Show() + app.InfoDialog().SetMessage(result).Show() } else { - app.NewInfoDialog().SetMessage("No directory selected").Show() + app.InfoDialog().SetMessage("No directory selected").Show() } }) openMenu.Add("Open File/Directory (Set Title)").OnClick(func(ctx *application.Context) { - dialog := app.NewOpenFileDialog(). + dialog := app.OpenFileDialog(). CanChooseDirectories(true). CanCreateDirectories(true). ResolvesAliases(true) @@ -237,14 +237,14 @@ func main() { result, _ := dialog.PromptForSingleSelection() if result != "" { - app.NewInfoDialog().SetMessage(result).Show() + app.InfoDialog().SetMessage(result).Show() } else { - app.NewInfoDialog().SetMessage("No file/directory selected").Show() + app.InfoDialog().SetMessage("No file/directory selected").Show() } }) openMenu.Add("Open (Full Example)").OnClick(func(ctx *application.Context) { cwd, _ := os.Getwd() - dialog := app.NewOpenFileDialog(). + dialog := app.OpenFileDialog(). SetTitle("Select a file"). SetMessage("Select a file to open"). SetButtonText("Let's do this!"). @@ -266,46 +266,46 @@ func main() { result, _ := dialog.PromptForSingleSelection() if result != "" { - app.NewInfoDialog().SetMessage(result).Show() + app.InfoDialog().SetMessage(result).Show() } else { - app.NewInfoDialog().SetMessage("No file selected").Show() + app.InfoDialog().SetMessage("No file selected").Show() } }) saveMenu := menu.AddSubmenu("Save") saveMenu.Add("Select File (Defaults)").OnClick(func(ctx *application.Context) { - result, _ := app.NewSaveFileDialog(). + result, _ := app.SaveFileDialog(). PromptForSingleSelection() if result != "" { - app.NewInfoDialog().SetMessage(result).Show() + app.InfoDialog().SetMessage(result).Show() } }) saveMenu.Add("Select File (Attach To WebviewWindow)").OnClick(func(ctx *application.Context) { - result, _ := app.NewSaveFileDialog(). + result, _ := app.SaveFileDialog(). AttachToWindow(app.CurrentWindow()). PromptForSingleSelection() if result != "" { - app.NewInfoDialog().SetMessage(result).Show() + app.InfoDialog().SetMessage(result).Show() } }) saveMenu.Add("Select File (Show Hidden Files)").OnClick(func(ctx *application.Context) { - result, _ := app.NewSaveFileDialog(). + result, _ := app.SaveFileDialog(). ShowHiddenFiles(true). PromptForSingleSelection() if result != "" { - app.NewInfoDialog().SetMessage(result).Show() + app.InfoDialog().SetMessage(result).Show() } }) saveMenu.Add("Select File (Cannot Create Directories)").OnClick(func(ctx *application.Context) { - result, _ := app.NewSaveFileDialog(). + result, _ := app.SaveFileDialog(). CanCreateDirectories(false). PromptForSingleSelection() if result != "" { - app.NewInfoDialog().SetMessage(result).Show() + app.InfoDialog().SetMessage(result).Show() } }) saveMenu.Add("Select File (Full Example)").OnClick(func(ctx *application.Context) { - result, _ := app.NewSaveFileDialog(). + result, _ := app.SaveFileDialog(). CanCreateDirectories(false). ShowHiddenFiles(true). SetMessage("Select a file"). @@ -318,7 +318,7 @@ func main() { ShowHiddenFiles(true). PromptForSingleSelection() if result != "" { - app.NewInfoDialog().SetMessage(result).Show() + app.InfoDialog().SetMessage(result).Show() } }) diff --git a/exp/examples/systray/main.go b/exp/examples/systray/main.go index f037bbb6a..5508ad904 100644 --- a/exp/examples/systray/main.go +++ b/exp/examples/systray/main.go @@ -26,7 +26,7 @@ func main() { myMenu := app.NewMenu() myMenu.Add("Hello World!").OnClick(func(ctx *application.Context) { - app.NewInfoDialog().SetTitle("Hello World!").SetMessage("Hello World!").Show() + app.InfoDialog().SetTitle("Hello World!").SetMessage("Hello World!").Show() }) subMenu := myMenu.AddSubmenu("Submenu") subMenu.Add("Click me!").OnClick(func(ctx *application.Context) { diff --git a/exp/examples/window/main.go b/exp/examples/window/main.go index 6a9f1f9c8..269d324c0 100644 --- a/exp/examples/window/main.go +++ b/exp/examples/window/main.go @@ -137,7 +137,7 @@ func main() { sizeMenu.Add("Get Current WebviewWindow Size").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.WebviewWindow) { width, height := w.Size() - app.NewInfoDialog().SetTitle("Current WebviewWindow Size").SetMessage("Width: " + strconv.Itoa(width) + " Height: " + strconv.Itoa(height)).Show() + app.InfoDialog().SetTitle("Current WebviewWindow Size").SetMessage("Width: " + strconv.Itoa(width) + " Height: " + strconv.Itoa(height)).Show() }) }) @@ -168,7 +168,7 @@ func main() { positionMenu.Add("Get Position").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.WebviewWindow) { x, y := w.Position() - app.NewInfoDialog().SetTitle("Current WebviewWindow Position").SetMessage("X: " + strconv.Itoa(x) + " Y: " + strconv.Itoa(y)).Show() + app.InfoDialog().SetTitle("Current WebviewWindow Position").SetMessage("X: " + strconv.Itoa(x) + " Y: " + strconv.Itoa(y)).Show() }) }) @@ -235,32 +235,32 @@ func main() { stateMenu.Add("Get Primary Screen").OnClick(func(ctx *application.Context) { screen, err := app.GetPrimaryScreen() if err != nil { - app.NewErrorDialog().SetTitle("Error").SetMessage(err.Error()).Show() + app.ErrorDialog().SetTitle("Error").SetMessage(err.Error()).Show() return } msg := fmt.Sprintf("Screen: %+v", screen) - app.NewInfoDialog().SetTitle("Primary Screen").SetMessage(msg).Show() + app.InfoDialog().SetTitle("Primary Screen").SetMessage(msg).Show() }) stateMenu.Add("Get Screens").OnClick(func(ctx *application.Context) { screens, err := app.GetScreens() if err != nil { - app.NewErrorDialog().SetTitle("Error").SetMessage(err.Error()).Show() + app.ErrorDialog().SetTitle("Error").SetMessage(err.Error()).Show() return } for _, screen := range screens { msg := fmt.Sprintf("Screen: %+v", screen) - app.NewInfoDialog().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show() + app.InfoDialog().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show() } }) stateMenu.Add("Get Screen for WebviewWindow").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.WebviewWindow) { screen, err := w.GetScreen() if err != nil { - app.NewErrorDialog().SetTitle("Error").SetMessage(err.Error()).Show() + app.ErrorDialog().SetTitle("Error").SetMessage(err.Error()).Show() return } msg := fmt.Sprintf("Screen: %+v", screen) - app.NewInfoDialog().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show() + app.InfoDialog().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show() }) }) app.NewWebviewWindow() diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index ce7d0fc0f..28a102f44 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -302,31 +302,31 @@ func (a *App) ShowAboutDialog() { } } -func (a *App) NewInfoDialog() *MessageDialog { +func (a *App) InfoDialog() *MessageDialog { return newMessageDialog(InfoDialog) } -func (a *App) NewQuestionDialog() *MessageDialog { +func (a *App) QuestionDialog() *MessageDialog { return newMessageDialog(QuestionDialog) } -func (a *App) NewWarningDialog() *MessageDialog { +func (a *App) WarningDialog() *MessageDialog { return newMessageDialog(WarningDialog) } -func (a *App) NewErrorDialog() *MessageDialog { +func (a *App) ErrorDialog() *MessageDialog { return newMessageDialog(ErrorDialog) } -func (a *App) NewOpenDirectoryDialog() *MessageDialog { +func (a *App) OpenDirectoryDialog() *MessageDialog { return newMessageDialog(OpenDirectoryDialog) } -func (a *App) NewOpenFileDialog() *OpenFileDialog { +func (a *App) OpenFileDialog() *OpenFileDialog { return newOpenFileDialog() } -func (a *App) NewSaveFileDialog() *SaveFileDialog { +func (a *App) SaveFileDialog() *SaveFileDialog { return newSaveFileDialog() } From 62a55093901e52d5752a32d442d0baa3aa2ad3ae Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Fri, 6 Jan 2023 20:20:40 +1100 Subject: [PATCH 72/85] Do not display internal tasks when using `wails task list` --- exp/internal/commands/task.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/exp/internal/commands/task.go b/exp/internal/commands/task.go index 67c4f9fa3..82a8bf549 100644 --- a/exp/internal/commands/task.go +++ b/exp/internal/commands/task.go @@ -49,6 +49,9 @@ func ListTasks(options *ListTaskOptions) error { println() for _, thisTask := range tasks { + if thisTask.Internal { + continue + } var thisRow = make([]string, 2) thisRow[0] = thisTask.Task thisRow[1] = thisTask.Summary From 06a03779632975767a094322547e3eb1e82eaaf1 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sat, 7 Jan 2023 11:26:46 +1100 Subject: [PATCH 73/85] Fix frameless Add rounded corners for frameless Create NSWindow subclass Add pre-post build hooks --- exp/examples/build/Taskfile.yml | 13 +- exp/examples/window/main.go | 14 +- exp/pkg/application/application_darwin.go | 4 +- exp/pkg/application/clipboard_darwin.go | 2 +- exp/pkg/application/dialogs_darwin.go | 2 +- ...iew_window_delegate.h => webview_window.h} | 13 + ...iew_window_delegate.m => webview_window.m} | 32 ++- exp/pkg/application/webview_window_darwin.go | 244 ++++++++++++------ .../application/webview_window_devtools.go | 2 +- 9 files changed, 227 insertions(+), 99 deletions(-) rename exp/pkg/application/{webview_window_delegate.h => webview_window.h} (53%) rename exp/pkg/application/{webview_window_delegate.m => webview_window.m} (95%) diff --git a/exp/examples/build/Taskfile.yml b/exp/examples/build/Taskfile.yml index 316d18473..ed71e373c 100644 --- a/exp/examples/build/Taskfile.yml +++ b/exp/examples/build/Taskfile.yml @@ -1,12 +1,19 @@ version: '3' tasks: + + pre-build: + summary: Pre-build hooks + + post-build: + summary: Post-build hooks + build: summary: Builds the application cmds: + - task: pre-build - go build -gcflags=all="-N -l" -o bin/testapp main.go - vars: - BIN_NAME: $NAME + - task: post-build env: CGO_CFLAGS: "-mmacosx-version-min=10.13" CGO_LDFLAGS: "-mmacosx-version-min=10.13" @@ -24,7 +31,7 @@ tasks: - go build -tags production -ldflags="-w -s" -o bin/testapp package-darwin: - summary: Packages a production build of the application into a `.app` + summary: Packages a production build of the application into a `.app` bundle deps: - build-prod - generate-icons diff --git a/exp/examples/window/main.go b/exp/examples/window/main.go index 269d324c0..80b249a37 100644 --- a/exp/examples/window/main.go +++ b/exp/examples/window/main.go @@ -58,12 +58,14 @@ func main() { myMenu.Add("New Frameless WebviewWindow"). SetAccelerator("CmdOrCtrl+F"). OnClick(func(ctx *application.Context) { - app.NewWebviewWindow(). - SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). - SetPosition(rand.Intn(1000), rand.Intn(800)). - SetURL("https://wails.io"). - SetFrameless(true). - Show() + app.NewWebviewWindowWithOptions(&options.WebviewWindow{ + X: rand.Intn(1000), + Y: rand.Intn(800), + Frameless: true, + Mac: options.MacWindow{ + InvisibleTitleBarHeight: 50, + }, + }).Show() windowCounter++ }) if runtime.GOOS == "darwin" { diff --git a/exp/pkg/application/application_darwin.go b/exp/pkg/application/application_darwin.go index 44861d935..48fb30a0f 100644 --- a/exp/pkg/application/application_darwin.go +++ b/exp/pkg/application/application_darwin.go @@ -4,12 +4,12 @@ package application /* -#cgo CFLAGS: -x objective-c +#cgo CFLAGS: -mmacosx-version-min=10.13 -x objective-c #cgo LDFLAGS: -framework Cocoa -mmacosx-version-min=10.13 #include "application.h" #include "app_delegate.h" -#include "webview_window_delegate.h" +#include "webview_window.h" #include extern void registerListener(unsigned int event); diff --git a/exp/pkg/application/clipboard_darwin.go b/exp/pkg/application/clipboard_darwin.go index 1d9fb0c59..a46ff66d5 100644 --- a/exp/pkg/application/clipboard_darwin.go +++ b/exp/pkg/application/clipboard_darwin.go @@ -3,7 +3,7 @@ package application /* -#cgo CFLAGS: -x objective-c +#cgo CFLAGS: -mmacosx-version-min=10.13 -x objective-c #cgo LDFLAGS: -framework Cocoa -mmacosx-version-min=10.13 #import diff --git a/exp/pkg/application/dialogs_darwin.go b/exp/pkg/application/dialogs_darwin.go index 640bf6bfb..91e94d6ba 100644 --- a/exp/pkg/application/dialogs_darwin.go +++ b/exp/pkg/application/dialogs_darwin.go @@ -3,7 +3,7 @@ package application /* -#cgo CFLAGS: -x objective-c +#cgo CFLAGS: -mmacosx-version-min=10.13 -x objective-c #cgo LDFLAGS: -framework Cocoa -mmacosx-version-min=10.13 -framework UniformTypeIdentifiers #import diff --git a/exp/pkg/application/webview_window_delegate.h b/exp/pkg/application/webview_window.h similarity index 53% rename from exp/pkg/application/webview_window_delegate.h rename to exp/pkg/application/webview_window.h index f0546116e..b8962b056 100644 --- a/exp/pkg/application/webview_window_delegate.h +++ b/exp/pkg/application/webview_window.h @@ -6,17 +6,30 @@ #import #import +@interface WebviewWindow : NSWindow +- (BOOL) canBecomeKeyWindow; +- (BOOL) canBecomeMainWindow; +- (BOOL) acceptsFirstResponder; +- (BOOL) becomeFirstResponder; +- (BOOL) resignFirstResponder; +- (WebviewWindow*) initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)windowStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation; + +@end + @interface WebviewWindowDelegate : NSObject @property bool hideOnClose; @property (retain) WKWebView* webView; @property unsigned int windowId; +@property (retain) NSWindow* window; @property (retain) NSEvent* leftMouseEvent; @property unsigned int invisibleTitleBarHeight; +@property NSWindowStyleMask previousStyleMask; // Used to restore the window style mask when using frameless - (void)handleLeftMouseUp:(NSWindow *)window; - (void)handleLeftMouseDown:(NSEvent*)event; + @end diff --git a/exp/pkg/application/webview_window_delegate.m b/exp/pkg/application/webview_window.m similarity index 95% rename from exp/pkg/application/webview_window_delegate.m rename to exp/pkg/application/webview_window.m index bf5040fa8..ff5d22bc4 100644 --- a/exp/pkg/application/webview_window_delegate.m +++ b/exp/pkg/application/webview_window.m @@ -2,12 +2,42 @@ #import #import -#import "webview_window_delegate.h" +#import "webview_window.h" #import "../events/events.h" extern void processMessage(unsigned int, const char*); extern bool hasListeners(unsigned int); +@implementation WebviewWindow + +- (WebviewWindow*) initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)windowStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation; +{ + self = [super initWithContentRect:contentRect styleMask:windowStyle backing:bufferingType defer:deferCreation]; + [self setAlphaValue:1.0]; + [self setBackgroundColor:[NSColor clearColor]]; + [self setOpaque:NO]; + [self setMovableByWindowBackground:YES]; + return self; +} + +- (BOOL)canBecomeKeyWindow { + return YES; +} + +- (BOOL) canBecomeMainWindow { + return YES; +} +- (BOOL) acceptsFirstResponder { + return YES; +} +- (BOOL) becomeFirstResponder { + return YES; +} +- (BOOL) resignFirstResponder { + return YES; +} +@end + @implementation WebviewWindowDelegate - (BOOL)windowShouldClose:(NSWindow *)sender { diff --git a/exp/pkg/application/webview_window_darwin.go b/exp/pkg/application/webview_window_darwin.go index 5fd193d38..d66bc59ea 100644 --- a/exp/pkg/application/webview_window_darwin.go +++ b/exp/pkg/application/webview_window_darwin.go @@ -7,7 +7,7 @@ package application #cgo LDFLAGS: -framework Cocoa -framework WebKit #include "application.h" -#include "webview_window_delegate.h" +#include "webview_window.h" #include #include "Cocoa/Cocoa.h" #import @@ -16,9 +16,14 @@ package application extern void registerListener(unsigned int event); // Create a new Window -void* windowNew(unsigned int id, int width, int height, bool fraudulentWebsiteWarningEnabled) { - NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, width-1, height-1) - styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable +void* windowNew(unsigned int id, int width, int height, bool fraudulentWebsiteWarningEnabled, bool frameless) { + + NSWindowStyleMask styleMask = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable; + if (frameless) { + styleMask = NSWindowStyleMaskBorderless | NSWindowStyleMaskResizable; + } + WebviewWindow* window = [[WebviewWindow alloc] initWithContentRect:NSMakeRect(0, 0, width-1, height-1) + styleMask:styleMask backing:NSBackingStoreBuffered defer:NO]; @@ -27,10 +32,15 @@ void* windowNew(unsigned int id, int width, int height, bool fraudulentWebsiteWa // Set delegate [window setDelegate:delegate]; delegate.windowId = id; + delegate.window = window; // Add NSView to window NSView* view = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, width-1, height-1)]; [view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + if( frameless ) { + [view setWantsLayer:YES]; + view.layer.cornerRadius = 8.0; + } [window setContentView:view]; // Embed wkwebview in window @@ -61,9 +71,62 @@ void* windowNew(unsigned int id, int width, int height, bool fraudulentWebsiteWa return window; } + +void printWindowStyle(void *window) { + WebviewWindow* nsWindow = (WebviewWindow*)window; + NSWindowStyleMask styleMask = [nsWindow styleMask]; + // Get delegate + WebviewWindowDelegate* windowDelegate = (WebviewWindowDelegate*)[nsWindow delegate]; + + printf("Window %d style mask: ", windowDelegate.windowId); + + if (styleMask & NSWindowStyleMaskTitled) + { + printf("NSWindowStyleMaskTitled "); + } + + if (styleMask & NSWindowStyleMaskClosable) + { + printf("NSWindowStyleMaskClosable "); + } + + if (styleMask & NSWindowStyleMaskMiniaturizable) + { + printf("NSWindowStyleMaskMiniaturizable "); + } + + if (styleMask & NSWindowStyleMaskResizable) + { + printf("NSWindowStyleMaskResizable "); + } + + if (styleMask & NSWindowStyleMaskFullSizeContentView) + { + printf("NSWindowStyleMaskFullSizeContentView "); + } + + if (styleMask & NSWindowStyleMaskNonactivatingPanel) + { + printf("NSWindowStyleMaskNonactivatingPanel "); + } + + if (styleMask & NSWindowStyleMaskFullScreen) + { + printf("NSWindowStyleMaskFullScreen "); + } + + if (styleMask & NSWindowStyleMaskBorderless) + { + printf("MSWindowStyleMaskBorderless "); + } + + printf("\n"); +} + + // setInvisibleTitleBarHeight sets the invisible title bar height void setInvisibleTitleBarHeight(void* window, unsigned int height) { - NSWindow* nsWindow = (NSWindow*)window; + WebviewWindow* nsWindow = (WebviewWindow*)window; // Get delegate WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[nsWindow delegate]; // Set height @@ -74,7 +137,7 @@ void setInvisibleTitleBarHeight(void* window, unsigned int height) { void windowSetTransparent(void* nsWindow) { // On main thread dispatch_async(dispatch_get_main_queue(), ^{ - NSWindow* window = (NSWindow*)nsWindow; + WebviewWindow* window = (WebviewWindow*)nsWindow; [window setOpaque:NO]; [window setBackgroundColor:[NSColor clearColor]]; }); @@ -83,7 +146,7 @@ void windowSetTransparent(void* nsWindow) { void windowSetInvisibleTitleBar(void* nsWindow, unsigned int height) { // On main thread dispatch_async(dispatch_get_main_queue(), ^{ - NSWindow* window = (NSWindow*)nsWindow; + WebviewWindow* window = (WebviewWindow*)nsWindow; // Get delegate WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[window delegate]; // Set height @@ -97,7 +160,7 @@ void windowSetTitle(void* nsWindow, char* title) { // Set window title on main thread dispatch_async(dispatch_get_main_queue(), ^{ NSString* nsTitle = [NSString stringWithUTF8String:title]; - [(NSWindow*)nsWindow setTitle:nsTitle]; + [(WebviewWindow*)nsWindow setTitle:nsTitle]; free(title); }); } @@ -106,7 +169,7 @@ void windowSetTitle(void* nsWindow, char* title) { void windowSetSize(void* nsWindow, int width, int height) { // Set window size on main thread dispatch_async(dispatch_get_main_queue(), ^{ - NSWindow* window = (NSWindow*)nsWindow; + WebviewWindow* window = (WebviewWindow*)nsWindow; NSSize contentSize = [window contentRectForFrameRect:NSMakeRect(0, 0, width, height)].size; [window setContentSize:contentSize]; [window setFrame:NSMakeRect(window.frame.origin.x, window.frame.origin.y, width, height) display:YES animate:YES]; @@ -117,7 +180,7 @@ void windowSetSize(void* nsWindow, int width, int height) { void windowSetAlwaysOnTop(void* nsWindow, bool alwaysOnTop) { // Set window always on top on main thread dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)nsWindow setLevel:alwaysOnTop ? NSStatusWindowLevel : NSNormalWindowLevel]; + [(WebviewWindow*)nsWindow setLevel:alwaysOnTop ? NSStatusWindowLevel : NSNormalWindowLevel]; }); } @@ -127,7 +190,7 @@ void navigationLoadURL(void* nsWindow, char* url) { dispatch_async(dispatch_get_main_queue(), ^{ NSURL* nsURL = [NSURL URLWithString:[NSString stringWithUTF8String:url]]; NSURLRequest* request = [NSURLRequest requestWithURL:nsURL]; - [[(WebviewWindowDelegate*)[(NSWindow*)nsWindow delegate] webView] loadRequest:request]; + [[(WebviewWindowDelegate*)[(WebviewWindow*)nsWindow delegate] webView] loadRequest:request]; free(url); }); } @@ -136,11 +199,16 @@ void navigationLoadURL(void* nsWindow, char* url) { void windowSetResizable(void* nsWindow, bool resizable) { // Set window resizable on main thread dispatch_async(dispatch_get_main_queue(), ^{ - NSWindow* window = (NSWindow*)nsWindow; + WebviewWindow* window = (WebviewWindow*)nsWindow; if (resizable) { - [window setStyleMask:[window styleMask] | NSWindowStyleMaskResizable]; + printf("Setting resizable to true\n"); + NSWindowStyleMask styleMask = [window styleMask] | NSWindowStyleMaskResizable; + [window setStyleMask:styleMask]; + } else { - [window setStyleMask:[window styleMask] & ~NSWindowStyleMaskResizable]; + printf("Setting resizable to false\n"); + NSWindowStyleMask styleMask = [window styleMask] & ~NSWindowStyleMaskResizable; + [window setStyleMask:styleMask]; } }); } @@ -149,7 +217,7 @@ void windowSetResizable(void* nsWindow, bool resizable) { void windowSetMinSize(void* nsWindow, int width, int height) { // Set window min size on main thread dispatch_async(dispatch_get_main_queue(), ^{ - NSWindow* window = (NSWindow*)nsWindow; + WebviewWindow* window = (WebviewWindow*)nsWindow; NSSize contentSize = [window contentRectForFrameRect:NSMakeRect(0, 0, width, height)].size; [window setContentMinSize:contentSize]; NSSize size = { width, height }; @@ -164,7 +232,7 @@ void windowSetMaxSize(void* nsWindow, int width, int height) { NSSize size = { FLT_MAX, FLT_MAX }; size.width = width > 0 ? width : FLT_MAX; size.height = height > 0 ? height : FLT_MAX; - NSWindow* window = (NSWindow*)nsWindow; + WebviewWindow* window = (WebviewWindow*)nsWindow; NSSize contentSize = [window contentRectForFrameRect:NSMakeRect(0, 0, size.width, size.height)].size; [window setContentMaxSize:contentSize]; [window setMaxSize:size]; @@ -176,7 +244,7 @@ void windowEnableDevTools(void* nsWindow) { // Enable devtools on main thread dispatch_async(dispatch_get_main_queue(), ^{ // Get window delegate - WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(NSWindow*)nsWindow delegate]; + WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(WebviewWindow*)nsWindow delegate]; // Enable devtools in webview [delegate.webView.configuration.preferences setValue:@YES forKey:@"developerExtrasEnabled"]; }); @@ -187,7 +255,7 @@ void windowResetZoom(void* nsWindow) { // Reset zoom on main thread dispatch_async(dispatch_get_main_queue(), ^{ // Get window delegate - WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(NSWindow*)nsWindow delegate]; + WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(WebviewWindow*)nsWindow delegate]; // Reset zoom [delegate.webView setMagnification:1.0]; }); @@ -198,7 +266,7 @@ void windowZoomIn(void* nsWindow) { // Zoom in on main thread dispatch_async(dispatch_get_main_queue(), ^{ // Get window delegate - WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(NSWindow*)nsWindow delegate]; + WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(WebviewWindow*)nsWindow delegate]; // Zoom in [delegate.webView setMagnification:delegate.webView.magnification + 0.05]; }); @@ -209,7 +277,7 @@ void windowZoomOut(void* nsWindow) { // Zoom out on main thread dispatch_async(dispatch_get_main_queue(), ^{ // Get window delegate - WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(NSWindow*)nsWindow delegate]; + WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(WebviewWindow*)nsWindow delegate]; // Zoom out if( delegate.webView.magnification > 1.05 ) { [delegate.webView setMagnification:delegate.webView.magnification - 0.05]; @@ -223,7 +291,7 @@ void windowZoomOut(void* nsWindow) { void windowSetPosition(void* nsWindow, int x, int y) { // Set window position on main thread dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)nsWindow setFrameOrigin:NSMakePoint(x, y)]; + [(WebviewWindow*)nsWindow setFrameOrigin:NSMakePoint(x, y)]; }); } @@ -231,7 +299,7 @@ void windowSetPosition(void* nsWindow, int x, int y) { void windowExecJS(void* nsWindow, const char* js) { // Execute JS on main thread dispatch_async(dispatch_get_main_queue(), ^{ - WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(NSWindow*)nsWindow delegate]; + WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(WebviewWindow*)nsWindow delegate]; [delegate.webView evaluateJavaScript:[NSString stringWithUTF8String:js] completionHandler:nil]; free((void*)js); }); @@ -243,10 +311,10 @@ void windowSetTranslucent(void* nsWindow) { dispatch_async(dispatch_get_main_queue(), ^{ // Get window - NSWindow* window = (NSWindow*)nsWindow; + WebviewWindow* window = (WebviewWindow*)nsWindow; // Get window delegate - WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(NSWindow*)nsWindow delegate]; + WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(WebviewWindow*)nsWindow delegate]; id contentView = [window contentView]; NSVisualEffectView *effectView = [NSVisualEffectView alloc]; @@ -264,7 +332,7 @@ void webviewSetTransparent(void* nsWindow) { // Set webview transparent on main thread dispatch_async(dispatch_get_main_queue(), ^{ // Get window delegate - WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(NSWindow*)nsWindow delegate]; + WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(WebviewWindow*)nsWindow delegate]; // Set webview background transparent [delegate.webView setValue:@NO forKey:@"drawsBackground"]; }); @@ -275,7 +343,7 @@ void webviewSetBackgroundColour(void* nsWindow, int r, int g, int b, int alpha) // Set webview background color on main thread dispatch_async(dispatch_get_main_queue(), ^{ // Get window delegate - WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(NSWindow*)nsWindow delegate]; + WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[(WebviewWindow*)nsWindow delegate]; // Set webview background color [delegate.webView setValue:[NSColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:alpha/255.0] forKey:@"backgroundColor"]; }); @@ -286,22 +354,22 @@ void windowSetBackgroundColour(void* nsWindow, int r, int g, int b, int alpha) { // Set window background color on main thread dispatch_async(dispatch_get_main_queue(), ^{ // Get window - NSWindow* window = (NSWindow*)nsWindow; + WebviewWindow* window = (WebviewWindow*)nsWindow; // Set window background color [window setBackgroundColor:[NSColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:alpha/255.0]]; }); } bool windowIsMaximised(void* nsWindow) { - return [(NSWindow*)nsWindow isZoomed]; + return [(WebviewWindow*)nsWindow isZoomed]; } bool windowIsFullscreen(void* nsWindow) { - return [(NSWindow*)nsWindow styleMask] & NSWindowStyleMaskFullScreen; + return [(WebviewWindow*)nsWindow styleMask] & NSWindowStyleMaskFullScreen; } bool windowIsMinimised(void* nsWindow) { - return [(NSWindow*)nsWindow isMiniaturized]; + return [(WebviewWindow*)nsWindow isMiniaturized]; } // Set Window fullscreen @@ -310,7 +378,7 @@ void windowFullscreen(void* nsWindow) { return; } dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)nsWindow toggleFullScreen:nil]; + [(WebviewWindow*)nsWindow toggleFullScreen:nil]; });} void windowUnFullscreen(void* nsWindow) { @@ -318,7 +386,7 @@ void windowUnFullscreen(void* nsWindow) { return; } dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)nsWindow toggleFullScreen:nil]; + [(WebviewWindow*)nsWindow toggleFullScreen:nil]; }); } @@ -327,16 +395,16 @@ void windowRestore(void* nsWindow) { // Set window normal on main thread dispatch_async(dispatch_get_main_queue(), ^{ // If window is fullscreen - if([(NSWindow*)nsWindow styleMask] & NSWindowStyleMaskFullScreen) { - [(NSWindow*)nsWindow toggleFullScreen:nil]; + if([(WebviewWindow*)nsWindow styleMask] & NSWindowStyleMaskFullScreen) { + [(WebviewWindow*)nsWindow toggleFullScreen:nil]; } // If window is maximised - if([(NSWindow*)nsWindow isZoomed]) { - [(NSWindow*)nsWindow zoom:nil]; + if([(WebviewWindow*)nsWindow isZoomed]) { + [(WebviewWindow*)nsWindow zoom:nil]; } // If window in minimised - if([(NSWindow*)nsWindow isMiniaturized]) { - [(NSWindow*)nsWindow deminiaturize:nil]; + if([(WebviewWindow*)nsWindow isMiniaturized]) { + [(WebviewWindow*)nsWindow deminiaturize:nil]; } }); } @@ -346,7 +414,7 @@ void setFullscreenButtonEnabled(void* nsWindow, bool enabled) { // Disable fullscreen button on main thread dispatch_async(dispatch_get_main_queue(), ^{ // Get window - NSWindow* window = (NSWindow*)nsWindow; + WebviewWindow* window = (WebviewWindow*)nsWindow; NSButton *fullscreenButton = [window standardWindowButton:NSWindowZoomButton]; fullscreenButton.enabled = enabled; }); @@ -357,9 +425,9 @@ void windowSetTitleBarAppearsTransparent(void* nsWindow, bool transparent) { // Set window titlebar style on main thread dispatch_async(dispatch_get_main_queue(), ^{ if( transparent ) { - [(NSWindow*)nsWindow setTitlebarAppearsTransparent:true]; + [(WebviewWindow*)nsWindow setTitlebarAppearsTransparent:true]; } else { - [(NSWindow*)nsWindow setTitlebarAppearsTransparent:false]; + [(WebviewWindow*)nsWindow setTitlebarAppearsTransparent:false]; } }); } @@ -369,9 +437,9 @@ void windowSetFullSizeContent(void* nsWindow, bool fullSize) { // Set window fullsize content view on main thread dispatch_async(dispatch_get_main_queue(), ^{ if( fullSize ) { - [(NSWindow*)nsWindow setStyleMask:[(NSWindow*)nsWindow styleMask] | NSWindowStyleMaskFullSizeContentView]; + [(WebviewWindow*)nsWindow setStyleMask:[(WebviewWindow*)nsWindow styleMask] | NSWindowStyleMaskFullSizeContentView]; } else { - [(NSWindow*)nsWindow setStyleMask:[(NSWindow*)nsWindow styleMask] & ~NSWindowStyleMaskFullSizeContentView]; + [(WebviewWindow*)nsWindow setStyleMask:[(WebviewWindow*)nsWindow styleMask] & ~NSWindowStyleMaskFullSizeContentView]; } }); } @@ -381,9 +449,9 @@ void windowSetHideTitleBar(void* nsWindow, bool hideTitlebar) { // Set window titlebar hidden on main thread dispatch_async(dispatch_get_main_queue(), ^{ if( hideTitlebar ) { - [(NSWindow*)nsWindow setStyleMask:[(NSWindow*)nsWindow styleMask] & ~NSWindowStyleMaskTitled]; + [(WebviewWindow*)nsWindow setStyleMask:[(WebviewWindow*)nsWindow styleMask] & ~NSWindowStyleMaskTitled]; } else { - [(NSWindow*)nsWindow setStyleMask:[(NSWindow*)nsWindow styleMask] | NSWindowStyleMaskTitled]; + [(WebviewWindow*)nsWindow setStyleMask:[(WebviewWindow*)nsWindow styleMask] | NSWindowStyleMaskTitled]; } }); } @@ -393,9 +461,9 @@ void windowSetHideTitle(void* nsWindow, bool hideTitle) { // Set window titlebar hidden on main thread dispatch_async(dispatch_get_main_queue(), ^{ if( hideTitle ) { - [(NSWindow*)nsWindow setTitleVisibility:NSWindowTitleHidden]; + [(WebviewWindow*)nsWindow setTitleVisibility:NSWindowTitleHidden]; } else { - [(NSWindow*)nsWindow setTitleVisibility:NSWindowTitleVisible]; + [(WebviewWindow*)nsWindow setTitleVisibility:NSWindowTitleVisible]; } }); } @@ -405,7 +473,7 @@ void windowSetUseToolbar(void* nsWindow, bool useToolbar, int toolbarStyle) { // Set window use toolbar on main thread dispatch_async(dispatch_get_main_queue(), ^{ // get main window - NSWindow* window = (NSWindow*)nsWindow; + WebviewWindow* window = (WebviewWindow*)nsWindow; if( useToolbar ) { NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"wails.toolbar"]; [toolbar autorelease]; @@ -430,7 +498,7 @@ void windowSetToolbarStyle(void* nsWindow, int style) { // Set window toolbar style on main thread dispatch_async(dispatch_get_main_queue(), ^{ // get main window - NSWindow* window = (NSWindow*)nsWindow; + WebviewWindow* window = (WebviewWindow*)nsWindow; // get toolbar NSToolbar* toolbar = [window toolbar]; // set toolbar style @@ -444,7 +512,7 @@ void windowSetHideToolbarSeparator(void* nsWindow, bool hideSeparator) { // Set window hide toolbar separator on main thread dispatch_async(dispatch_get_main_queue(), ^{ // get main window - NSWindow* window = (NSWindow*)nsWindow; + WebviewWindow* window = (WebviewWindow*)nsWindow; // get toolbar NSToolbar* toolbar = [window toolbar]; // Return if toolbar nil @@ -464,7 +532,7 @@ void windowSetAppearanceTypeByName(void* nsWindow, const char *appearanceName) { // Set window appearance type on main thread dispatch_async(dispatch_get_main_queue(), ^{ // get main window - NSWindow* window = (NSWindow*)nsWindow; + WebviewWindow* window = (WebviewWindow*)nsWindow; // set window appearance type by name // Convert appearance name to NSString NSString* appearanceNameString = [NSString stringWithUTF8String:appearanceName]; @@ -480,7 +548,7 @@ void windowCenter(void* nsWindow) { // Center window on main thread dispatch_async(dispatch_get_main_queue(), ^{ // get main window - NSWindow* window = (NSWindow*)nsWindow; + WebviewWindow* window = (WebviewWindow*)nsWindow; [window center]; }); } @@ -488,7 +556,7 @@ void windowCenter(void* nsWindow) { // Get the current size of the window void windowGetSize(void* nsWindow, int* width, int* height) { // get main window - NSWindow* window = (NSWindow*)nsWindow; + WebviewWindow* window = (WebviewWindow*)nsWindow; // get window frame NSRect frame = [window frame]; // set width and height @@ -499,7 +567,7 @@ void windowGetSize(void* nsWindow, int* width, int* height) { // Get window width int windowGetWidth(void* nsWindow) { // get main window - NSWindow* window = (NSWindow*)nsWindow; + WebviewWindow* window = (WebviewWindow*)nsWindow; // get window frame NSRect frame = [window frame]; // return width @@ -509,7 +577,7 @@ int windowGetWidth(void* nsWindow) { // Get window height int windowGetHeight(void* nsWindow) { // get main window - NSWindow* window = (NSWindow*)nsWindow; + WebviewWindow* window = (WebviewWindow*)nsWindow; // get window frame NSRect frame = [window frame]; // return height @@ -519,7 +587,7 @@ int windowGetHeight(void* nsWindow) { // Get window position void windowGetPosition(void* nsWindow, int* x, int* y) { // get main window - NSWindow* window = (NSWindow*)nsWindow; + WebviewWindow* window = (WebviewWindow*)nsWindow; // get window frame NSRect frame = [window frame]; // set x and y @@ -532,7 +600,7 @@ void windowDestroy(void* nsWindow) { // Destroy window on main thread dispatch_async(dispatch_get_main_queue(), ^{ // get main window - NSWindow* window = (NSWindow*)nsWindow; + WebviewWindow* window = (WebviewWindow*)nsWindow; // close window [window close]; }); @@ -543,7 +611,7 @@ void windowDestroy(void* nsWindow) { static void windowClose(void *window) { dispatch_async(dispatch_get_main_queue(), ^{ // close window - [(NSWindow*)window close]; + [(WebviewWindow*)window close]; }); } @@ -551,7 +619,7 @@ static void windowClose(void *window) { static void windowZoom(void *window) { dispatch_async(dispatch_get_main_queue(), ^{ // zoom window - [(NSWindow*)window zoom:nil]; + [(WebviewWindow*)window zoom:nil]; }); } @@ -559,7 +627,7 @@ static void windowZoom(void *window) { static void windowMiniaturize(void *window) { dispatch_async(dispatch_get_main_queue(), ^{ // miniaturize window - [(NSWindow*)window miniaturize:nil]; + [(WebviewWindow*)window miniaturize:nil]; }); } @@ -567,7 +635,7 @@ static void windowMiniaturize(void *window) { static void windowRenderHTML(void *window, const char *html) { dispatch_async(dispatch_get_main_queue(), ^{ // get main window - NSWindow* nsWindow = (NSWindow*)window; + WebviewWindow* nsWindow = (WebviewWindow*)window; // get window delegate WebviewWindowDelegate* windowDelegate = (WebviewWindowDelegate*)[nsWindow delegate]; // render html @@ -578,7 +646,7 @@ static void windowRenderHTML(void *window, const char *html) { static void windowInjectCSS(void *window, const char *css) { dispatch_async(dispatch_get_main_queue(), ^{ // get main window - NSWindow* nsWindow = (NSWindow*)window; + WebviewWindow* nsWindow = (WebviewWindow*)window; // get window delegate WebviewWindowDelegate* windowDelegate = (WebviewWindowDelegate*)[nsWindow delegate]; // inject css @@ -590,7 +658,7 @@ static void windowInjectCSS(void *window, const char *css) { static void windowMinimise(void *window) { dispatch_async(dispatch_get_main_queue(), ^{ // minimize window - [(NSWindow*)window miniaturize:nil]; + [(WebviewWindow*)window miniaturize:nil]; }); } @@ -598,13 +666,13 @@ static void windowMinimise(void *window) { static void windowMaximise(void *window) { dispatch_async(dispatch_get_main_queue(), ^{ // maximize window - [(NSWindow*)window zoom:nil]; + [(WebviewWindow*)window zoom:nil]; }); } static bool isFullScreen(void *window) { // get main window - NSWindow* nsWindow = (NSWindow*)window; + WebviewWindow* nsWindow = (WebviewWindow*)window; long mask = [nsWindow styleMask]; return (mask & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen; } @@ -615,7 +683,7 @@ static void windowSetFullScreen(void *window, bool fullscreen) { return; } dispatch_async(dispatch_get_main_queue(), ^{ - NSWindow* nsWindow = (NSWindow*)window; + WebviewWindow* nsWindow = (WebviewWindow*)window; windowSetMaxSize(nsWindow, 0, 0); windowSetMinSize(nsWindow, 0, 0); [nsWindow toggleFullScreen:nil]; @@ -626,7 +694,7 @@ static void windowSetFullScreen(void *window, bool fullscreen) { static void windowUnminimise(void *window) { dispatch_async(dispatch_get_main_queue(), ^{ // unminimize window - [(NSWindow*)window deminiaturize:nil]; + [(WebviewWindow*)window deminiaturize:nil]; }); } @@ -634,14 +702,14 @@ static void windowUnminimise(void *window) { static void windowUnmaximise(void *window) { dispatch_async(dispatch_get_main_queue(), ^{ // unmaximize window - [(NSWindow*)window zoom:nil]; + [(WebviewWindow*)window zoom:nil]; }); } static void windowDisableSizeConstraints(void *window) { dispatch_async(dispatch_get_main_queue(), ^{ // get main window - NSWindow* nsWindow = (NSWindow*)window; + WebviewWindow* nsWindow = (WebviewWindow*)window; // disable size constraints [nsWindow setContentMinSize:CGSizeZero]; [nsWindow setContentMaxSize:CGSizeZero]; @@ -651,13 +719,13 @@ static void windowDisableSizeConstraints(void *window) { static void windowShow(void *window) { dispatch_async(dispatch_get_main_queue(), ^{ // show window - [(NSWindow*)window makeKeyAndOrderFront:nil]; + [(WebviewWindow*)window makeKeyAndOrderFront:nil]; }); } static void windowHide(void *window) { dispatch_async(dispatch_get_main_queue(), ^{ - [(NSWindow*)window orderOut:nil]; + [(WebviewWindow*)window orderOut:nil]; }); } @@ -665,7 +733,7 @@ static void windowHide(void *window) { static void windowSetFrameless(void *window, bool frameless) { dispatch_async(dispatch_get_main_queue(), ^{ // get main window - NSWindow* nsWindow = (NSWindow*)window; + WebviewWindow* nsWindow = (WebviewWindow*)window; // set the window style to be frameless if (frameless) { [nsWindow setStyleMask:([nsWindow styleMask] | NSWindowStyleMaskFullSizeContentView)]; @@ -860,8 +928,10 @@ func newWindowImpl(parent *WebviewWindow) *macosWebviewWindow { } func (w *macosWebviewWindow) setTitle(title string) { - cTitle := C.CString(title) - C.windowSetTitle(w.nsWindow, cTitle) + if !w.parent.options.Frameless { + cTitle := C.CString(title) + C.windowSetTitle(w.nsWindow, cTitle) + } } func (w *macosWebviewWindow) setSize(width, height int) { @@ -926,8 +996,12 @@ func (w *macosWebviewWindow) run() { w.on(eventId) } globalApplication.dispatchOnMainThread(func() { - w.nsWindow = C.windowNew(C.uint(w.parent.id), C.int(w.parent.options.Width), C.int(w.parent.options.Height), C.bool(w.parent.options.EnableFraudulentWebsiteWarnings)) - w.setFrameless(w.parent.options.Frameless) + w.nsWindow = C.windowNew(C.uint(w.parent.id), + C.int(w.parent.options.Width), + C.int(w.parent.options.Height), + C.bool(w.parent.options.EnableFraudulentWebsiteWarnings), + C.bool(w.parent.options.Frameless), + ) w.setTitle(w.parent.options.Title) w.setAlwaysOnTop(w.parent.options.AlwaysOnTop) w.setResizable(!w.parent.options.DisableResize) @@ -951,15 +1025,16 @@ func (w *macosWebviewWindow) run() { } titleBarOptions := macOptions.TitleBar - C.windowSetTitleBarAppearsTransparent(w.nsWindow, C.bool(titleBarOptions.AppearsTransparent)) - C.windowSetHideTitleBar(w.nsWindow, C.bool(titleBarOptions.Hide)) - C.windowSetHideTitle(w.nsWindow, C.bool(titleBarOptions.HideTitle)) - C.windowSetFullSizeContent(w.nsWindow, C.bool(titleBarOptions.FullSizeContent)) - if titleBarOptions.UseToolbar { - C.windowSetUseToolbar(w.nsWindow, C.bool(titleBarOptions.UseToolbar), C.int(titleBarOptions.ToolbarStyle)) + if !w.parent.options.Frameless { + C.windowSetTitleBarAppearsTransparent(w.nsWindow, C.bool(titleBarOptions.AppearsTransparent)) + C.windowSetHideTitleBar(w.nsWindow, C.bool(titleBarOptions.Hide)) + C.windowSetHideTitle(w.nsWindow, C.bool(titleBarOptions.HideTitle)) + C.windowSetFullSizeContent(w.nsWindow, C.bool(titleBarOptions.FullSizeContent)) + if titleBarOptions.UseToolbar { + C.windowSetUseToolbar(w.nsWindow, C.bool(titleBarOptions.UseToolbar), C.int(titleBarOptions.ToolbarStyle)) + } + C.windowSetHideToolbarSeparator(w.nsWindow, C.bool(titleBarOptions.HideToolbarSeparator)) } - C.windowSetHideToolbarSeparator(w.nsWindow, C.bool(titleBarOptions.HideToolbarSeparator)) - if macOptions.Appearance != "" { C.windowSetAppearanceTypeByName(w.nsWindow, C.CString(string(macOptions.Appearance))) } @@ -997,6 +1072,7 @@ func (w *macosWebviewWindow) run() { if w.parent.options.Hidden == false { C.windowShow(w.nsWindow) } + C.printWindowStyle(w.nsWindow) }) } diff --git a/exp/pkg/application/webview_window_devtools.go b/exp/pkg/application/webview_window_devtools.go index f1121384b..98d022ccf 100644 --- a/exp/pkg/application/webview_window_devtools.go +++ b/exp/pkg/application/webview_window_devtools.go @@ -8,7 +8,7 @@ package application #import -#include "webview_window_delegate.h" +#include "webview_window.h" @interface _WKInspector : NSObject - (void)show; From e5d3803fc143da11532f732c18d108529a14d637 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 8 Jan 2023 21:06:31 +1100 Subject: [PATCH 74/85] Initial runtime builds Added Taskfile for fast runtime builds --- .gitignore | 2 + exp/Taskfile.yaml | 136 ++ exp/internal/runtime/desktop/bindings.js | 67 + exp/internal/runtime/desktop/browser.js | 8 + exp/internal/runtime/desktop/calls.js | 189 ++ exp/internal/runtime/desktop/events.js | 212 +++ exp/internal/runtime/desktop/events.test.js | 132 ++ exp/internal/runtime/desktop/ipc.js | 23 + exp/internal/runtime/desktop/log.js | 113 ++ exp/internal/runtime/desktop/main.js | 80 + exp/internal/runtime/desktop/screen.js | 25 + exp/internal/runtime/desktop/window.js | 269 +++ exp/internal/runtime/dev/Overlay.svelte | 54 + exp/internal/runtime/dev/build.js | 15 + exp/internal/runtime/dev/log.js | 8 + exp/internal/runtime/dev/main.js | 125 ++ exp/internal/runtime/dev/package-lock.json | 1536 +++++++++++++++++ exp/internal/runtime/dev/package.json | 18 + exp/internal/runtime/dev/store.js | 12 + exp/internal/runtime/ipc.go | 9 + exp/internal/runtime/ipc.js | 1 + exp/internal/runtime/ipc_websocket.js | 22 + exp/internal/runtime/package-lock.json | 1503 ++++++++++++++++ exp/internal/runtime/package.json | 14 + exp/internal/runtime/runtime_debug_darwin.go | 8 + .../runtime/runtime_debug_desktop_darwin.js | 420 +++++ .../runtime/runtime_debug_desktop_linux.js | 420 +++++ .../runtime/runtime_debug_desktop_windows.js | 420 +++++ exp/internal/runtime/runtime_debug_linux.go | 8 + exp/internal/runtime/runtime_debug_windows.go | 8 + .../runtime/runtime_production_darwin.go | 8 + .../runtime_production_desktop_darwin.js | 1 + .../runtime_production_desktop_linux.js | 1 + .../runtime_production_desktop_windows.js | 1 + .../runtime/runtime_production_linux.go | 8 + .../runtime/runtime_production_windows.go | 8 + exp/internal/runtime/vite.config.ts | 7 + 37 files changed, 5891 insertions(+) create mode 100644 exp/Taskfile.yaml create mode 100644 exp/internal/runtime/desktop/bindings.js create mode 100644 exp/internal/runtime/desktop/browser.js create mode 100644 exp/internal/runtime/desktop/calls.js create mode 100644 exp/internal/runtime/desktop/events.js create mode 100644 exp/internal/runtime/desktop/events.test.js create mode 100644 exp/internal/runtime/desktop/ipc.js create mode 100644 exp/internal/runtime/desktop/log.js create mode 100644 exp/internal/runtime/desktop/main.js create mode 100644 exp/internal/runtime/desktop/screen.js create mode 100644 exp/internal/runtime/desktop/window.js create mode 100644 exp/internal/runtime/dev/Overlay.svelte create mode 100644 exp/internal/runtime/dev/build.js create mode 100644 exp/internal/runtime/dev/log.js create mode 100644 exp/internal/runtime/dev/main.js create mode 100644 exp/internal/runtime/dev/package-lock.json create mode 100644 exp/internal/runtime/dev/package.json create mode 100644 exp/internal/runtime/dev/store.js create mode 100644 exp/internal/runtime/ipc.go create mode 100644 exp/internal/runtime/ipc.js create mode 100644 exp/internal/runtime/ipc_websocket.js create mode 100644 exp/internal/runtime/package-lock.json create mode 100644 exp/internal/runtime/package.json create mode 100644 exp/internal/runtime/runtime_debug_darwin.go create mode 100644 exp/internal/runtime/runtime_debug_desktop_darwin.js create mode 100644 exp/internal/runtime/runtime_debug_desktop_linux.js create mode 100644 exp/internal/runtime/runtime_debug_desktop_windows.js create mode 100644 exp/internal/runtime/runtime_debug_linux.go create mode 100644 exp/internal/runtime/runtime_debug_windows.go create mode 100644 exp/internal/runtime/runtime_production_darwin.go create mode 100644 exp/internal/runtime/runtime_production_desktop_darwin.js create mode 100644 exp/internal/runtime/runtime_production_desktop_linux.js create mode 100644 exp/internal/runtime/runtime_production_desktop_windows.js create mode 100644 exp/internal/runtime/runtime_production_linux.go create mode 100644 exp/internal/runtime/runtime_production_windows.go create mode 100644 exp/internal/runtime/vite.config.ts diff --git a/.gitignore b/.gitignore index 62acc1e8d..567f8ea27 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,5 @@ v2/cmd/wails/internal/commands/initialise/templates/testtemplates/ .env /website/static/img/.cache.json +/exp/.task +/exp/examples/build/bin/testapp diff --git a/exp/Taskfile.yaml b/exp/Taskfile.yaml new file mode 100644 index 000000000..fc145cf68 --- /dev/null +++ b/exp/Taskfile.yaml @@ -0,0 +1,136 @@ +# https://taskfile.dev + +version: '3' + +tasks: + + build-runtime-debug: + dir: internal/runtime + internal: true + cmds: + - npx esbuild desktop/main.js --bundle --sourcemap=inline --outfile=runtime_debug_desktop_{{.PLATFORM}}.js --define:DEBUG=true --define:WINDOWS={{.WINDOWS}} --define:DARWIN={{.DARWIN}} --define:LINUX={{.LINUX}} --define:PLATFORM={{.PLATFORM}} + + build-runtime-debug-windows: + cmds: + - task: build-runtime-debug + vars: + WINDOWS: true + DARWIN: false + LINUX: false + PLATFORM: windows + + build-runtime-debug-linux: + cmds: + - task: build-runtime-debug + vars: + WINDOWS: false + DARWIN: false + LINUX: true + PLATFORM: linux + + build-runtime-debug-darwin: + cmds: + - task: build-runtime-debug + vars: + WINDOWS: false + DARWIN: true + LINUX: false + PLATFORM: darwin + + build-runtime-production: + dir: internal/runtime + internal: true + cmds: + - npx esbuild desktop/main.js --bundle --minify --outfile=runtime_production_desktop_{{.PLATFORM}}.js --define:DEBUG=true --define:WINDOWS={{.WINDOWS}} --define:DARWIN={{.DARWIN}} --define:LINUX={{.LINUX}} --define:PLATFORM={{.PLATFORM}} + + build-runtime-production-windows: + cmds: + - task: build-runtime-production + vars: + WINDOWS: true + DARWIN: false + LINUX: false + PLATFORM: windows + + build-runtime-production-linux: + cmds: + - task: build-runtime-production + vars: + WINDOWS: false + DARWIN: false + LINUX: true + PLATFORM: linux + + build-runtime-production-darwin: + cmds: + - task: build-runtime-production + vars: + WINDOWS: false + DARWIN: true + LINUX: false + PLATFORM: darwin + + install-runtime-dev-deps: + dir: internal/runtime/dev + internal: true + sources: + - package.json + cmds: + - npm install + + + install-runtime-deps: + dir: internal/runtime + internal: true + sources: + - package.json + cmds: + - npm install + + build-runtime-dev: + dir: internal/runtime/dev + deps: + - install-runtime-dev-deps + sources: + - ./*.js + generates: + - ../ipc_websocket.js + cmds: + - node build.js + + build-runtime-ipc: + dir: internal/runtime + deps: + - install-runtime-dev-deps + sources: + - ./desktop/ipc.js + generates: + - ipc.js + cmds: + - npx esbuild desktop/ipc.js --bundle --minify --outfile=ipc.js + + test-runtime: + dir: internal/runtime + cmds: + - npx vitest + + build-runtime-all: + dir: internal/runtime + deps: + - build-runtime-production-darwin + - build-runtime-production-windows + - build-runtime-production-linux + - build-runtime-debug-darwin + - build-runtime-debug-windows + - build-runtime-debug-linux + - build-runtime-dev + - build-runtime-ipc + cmds: + - task: test-runtime + + build-runtime: + dir: internal/runtime + deps: + - install-runtime-deps + cmds: + - task: build-runtime-all diff --git a/exp/internal/runtime/desktop/bindings.js b/exp/internal/runtime/desktop/bindings.js new file mode 100644 index 000000000..96e1890f6 --- /dev/null +++ b/exp/internal/runtime/desktop/bindings.js @@ -0,0 +1,67 @@ +/* + _ __ _ __ +| | / /___ _(_) /____ +| | /| / / __ `/ / / ___/ +| |/ |/ / /_/ / / (__ ) +|__/|__/\__,_/_/_/____/ +The electron alternative for Go +(c) Lea Anthony 2019-present +*/ +/* jshint esversion: 6 */ + +import {Call} from './calls'; + +// This is where we bind go method wrappers +window.go = {}; + +export function SetBindings(bindingsMap) { + try { + bindingsMap = JSON.parse(bindingsMap); + } catch (e) { + console.error(e); + } + + // Initialise the bindings map + window.go = window.go || {}; + + // Iterate package names + Object.keys(bindingsMap).forEach((packageName) => { + + // Create inner map if it doesn't exist + window.go[packageName] = window.go[packageName] || {}; + + // Iterate struct names + Object.keys(bindingsMap[packageName]).forEach((structName) => { + + // Create inner map if it doesn't exist + window.go[packageName][structName] = window.go[packageName][structName] || {}; + + Object.keys(bindingsMap[packageName][structName]).forEach((methodName) => { + + window.go[packageName][structName][methodName] = function () { + + // No timeout by default + let timeout = 0; + + // Actual function + function dynamic() { + const args = [].slice.call(arguments); + return Call([packageName, structName, methodName].join('.'), args, timeout); + } + + // Allow setting timeout to function + dynamic.setTimeout = function (newTimeout) { + timeout = newTimeout; + }; + + // Allow getting timeout to function + dynamic.getTimeout = function () { + return timeout; + }; + + return dynamic; + }(); + }); + }); + }); +} diff --git a/exp/internal/runtime/desktop/browser.js b/exp/internal/runtime/desktop/browser.js new file mode 100644 index 000000000..18c5258f2 --- /dev/null +++ b/exp/internal/runtime/desktop/browser.js @@ -0,0 +1,8 @@ +/** + * @description: Use the system default browser to open the url + * @param {string} url + * @return {void} + */ +export function BrowserOpenURL(url) { + window.WailsInvoke('BO:' + url); +} \ No newline at end of file diff --git a/exp/internal/runtime/desktop/calls.js b/exp/internal/runtime/desktop/calls.js new file mode 100644 index 000000000..161aaaed6 --- /dev/null +++ b/exp/internal/runtime/desktop/calls.js @@ -0,0 +1,189 @@ +/* + _ __ _ __ +| | / /___ _(_) /____ +| | /| / / __ `/ / / ___/ +| |/ |/ / /_/ / / (__ ) +|__/|__/\__,_/_/_/____/ +The electron alternative for Go +(c) Lea Anthony 2019-present +*/ +/* jshint esversion: 6 */ + +export const callbacks = {}; + +/** + * Returns a number from the native browser random function + * + * @returns number + */ +function cryptoRandom() { + var array = new Uint32Array(1); + return window.crypto.getRandomValues(array)[0]; +} + +/** + * Returns a number using da old-skool Math.Random + * I likes to call it LOLRandom + * + * @returns number + */ +function basicRandom() { + return Math.random() * 9007199254740991; +} + +// Pick a random number function based on browser capability +var randomFunc; +if (window.crypto) { + randomFunc = cryptoRandom; +} else { + randomFunc = basicRandom; +} + + +/** + * Call sends a message to the backend to call the binding with the + * given data. A promise is returned and will be completed when the + * backend responds. This will be resolved when the call was successful + * or rejected if an error is passed back. + * There is a timeout mechanism. If the call doesn't respond in the given + * time (in milliseconds) then the promise is rejected. + * + * @export + * @param {string} name + * @param {any=} args + * @param {number=} timeout + * @returns + */ +export function Call(name, args, timeout) { + + // Timeout infinite by default + if (timeout == null) { + timeout = 0; + } + + let windowID = window.wails.window.ID(); + + // Create a promise + return new Promise(function (resolve, reject) { + + // Create a unique callbackID + var callbackID; + do { + callbackID = name + '-' + randomFunc(); + } while (callbacks[callbackID]); + + var timeoutHandle; + // Set timeout + if (timeout > 0) { + timeoutHandle = setTimeout(function () { + reject(Error('Call to ' + name + ' timed out. Request ID: ' + callbackID)); + }, timeout); + } + + // Store callback + callbacks[callbackID] = { + timeoutHandle: timeoutHandle, + reject: reject, + resolve: resolve + }; + + try { + const payload = { + name, + args, + callbackID, + windowID, + }; + + // Make the call + window.WailsInvoke('C' + JSON.stringify(payload)); + } catch (e) { + // eslint-disable-next-line + console.error(e); + } + }); +} + +window.ObfuscatedCall = (id, args, timeout) => { + + // Timeout infinite by default + if (timeout == null) { + timeout = 0; + } + + // Create a promise + return new Promise(function (resolve, reject) { + + // Create a unique callbackID + var callbackID; + do { + callbackID = id + '-' + randomFunc(); + } while (callbacks[callbackID]); + + var timeoutHandle; + // Set timeout + if (timeout > 0) { + timeoutHandle = setTimeout(function () { + reject(Error('Call to method ' + id + ' timed out. Request ID: ' + callbackID)); + }, timeout); + } + + // Store callback + callbacks[callbackID] = { + timeoutHandle: timeoutHandle, + reject: reject, + resolve: resolve + }; + + try { + const payload = { + id, + args, + callbackID, + windowID: window.wails.window.ID(), + }; + + // Make the call + window.WailsInvoke('c' + JSON.stringify(payload)); + } catch (e) { + // eslint-disable-next-line + console.error(e); + } + }); +}; + + +/** + * Called by the backend to return data to a previously called + * binding invocation + * + * @export + * @param {string} incomingMessage + */ +export function Callback(incomingMessage) { + // Parse the message + let message; + try { + message = JSON.parse(incomingMessage); + } catch (e) { + const error = `Invalid JSON passed to callback: ${e.message}. Message: ${incomingMessage}`; + runtime.LogDebug(error); + throw new Error(error); + } + let callbackID = message.callbackid; + let callbackData = callbacks[callbackID]; + if (!callbackData) { + const error = `Callback '${callbackID}' not registered!!!`; + console.error(error); // eslint-disable-line + throw new Error(error); + } + clearTimeout(callbackData.timeoutHandle); + + delete callbacks[callbackID]; + + if (message.error) { + callbackData.reject(message.error); + } else { + callbackData.resolve(message.result); + } +} diff --git a/exp/internal/runtime/desktop/events.js b/exp/internal/runtime/desktop/events.js new file mode 100644 index 000000000..0ee9b2dd3 --- /dev/null +++ b/exp/internal/runtime/desktop/events.js @@ -0,0 +1,212 @@ +/* + _ __ _ __ +| | / /___ _(_) /____ +| | /| / / __ `/ / / ___/ +| |/ |/ / /_/ / / (__ ) +|__/|__/\__,_/_/_/____/ +The electron alternative for Go +(c) Lea Anthony 2019-present +*/ +/* jshint esversion: 6 */ + +// Defines a single listener with a maximum number of times to callback + +/** + * The Listener class defines a listener! :-) + * + * @class Listener + */ +class Listener { + /** + * Creates an instance of Listener. + * @param {string} eventName + * @param {function} callback + * @param {number} maxCallbacks + * @memberof Listener + */ + constructor(eventName, callback, maxCallbacks) { + this.eventName = eventName; + // Default of -1 means infinite + this.maxCallbacks = maxCallbacks || -1; + // Callback invokes the callback with the given data + // Returns true if this listener should be destroyed + this.Callback = (data) => { + callback.apply(null, data); + // If maxCallbacks is infinite, return false (do not destroy) + if (this.maxCallbacks === -1) { + return false; + } + // Decrement maxCallbacks. Return true if now 0, otherwise false + this.maxCallbacks -= 1; + return this.maxCallbacks === 0; + }; + } +} + +export const eventListeners = {}; + +/** + * Registers an event listener that will be invoked `maxCallbacks` times before being destroyed + * + * @export + * @param {string} eventName + * @param {function} callback + * @param {number} maxCallbacks + * @returns {function} A function to cancel the listener + */ +export function EventsOnMultiple(eventName, callback, maxCallbacks) { + eventListeners[eventName] = eventListeners[eventName] || []; + const thisListener = new Listener(eventName, callback, maxCallbacks); + eventListeners[eventName].push(thisListener); + return () => listenerOff(thisListener); +} + +/** + * Registers an event listener that will be invoked every time the event is emitted + * + * @export + * @param {string} eventName + * @param {function} callback + * @returns {function} A function to cancel the listener + */ +export function EventsOn(eventName, callback) { + return EventsOnMultiple(eventName, callback, -1); +} + +/** + * Registers an event listener that will be invoked once then destroyed + * + * @export + * @param {string} eventName + * @param {function} callback + * @returns {function} A function to cancel the listener + */ +export function EventsOnce(eventName, callback) { + return EventsOnMultiple(eventName, callback, 1); +} + +function notifyListeners(eventData) { + + // Get the event name + let eventName = eventData.name; + + // Check if we have any listeners for this event + if (eventListeners[eventName]) { + + // Keep a list of listener indexes to destroy + const newEventListenerList = eventListeners[eventName].slice(); + + // Iterate listeners + for (let count = 0; count < eventListeners[eventName].length; count += 1) { + + // Get next listener + const listener = eventListeners[eventName][count]; + + let data = eventData.data; + + // Do the callback + const destroy = listener.Callback(data); + if (destroy) { + // if the listener indicated to destroy itself, add it to the destroy list + newEventListenerList.splice(count, 1); + } + } + + // Update callbacks with new list of listeners + if (newEventListenerList.length === 0) { + removeListener(eventName); + } else { + eventListeners[eventName] = newEventListenerList; + } + } +} + +/** + * Notify informs frontend listeners that an event was emitted with the given data + * + * @export + * @param {string} notifyMessage - encoded notification message + + */ +export function EventsNotify(notifyMessage) { + // Parse the message + let message; + try { + message = JSON.parse(notifyMessage); + } catch (e) { + const error = 'Invalid JSON passed to Notify: ' + notifyMessage; + throw new Error(error); + } + notifyListeners(message); +} + +/** + * Emit an event with the given name and data + * + * @export + * @param {string} eventName + */ +export function EventsEmit(eventName) { + + const payload = { + name: eventName, + data: [].slice.apply(arguments).slice(1), + }; + + // Notify JS listeners + notifyListeners(payload); + + // Notify Go listeners + window.WailsInvoke('EE' + JSON.stringify(payload)); +} + +function removeListener(eventName) { + // Remove local listeners + delete eventListeners[eventName]; + + // Notify Go listeners + window.WailsInvoke('EX' + eventName); +} + +/** + * Off unregisters a listener previously registered with On, + * optionally multiple listeneres can be unregistered via `additionalEventNames` + * + * @param {string} eventName + * @param {...string} additionalEventNames + */ +export function EventsOff(eventName, ...additionalEventNames) { + removeListener(eventName) + + if (additionalEventNames.length > 0) { + additionalEventNames.forEach(eventName => { + removeListener(eventName) + }) + } +} + +/** + * Off unregisters all event listeners previously registered with On + */ + export function EventsOffAll() { + const eventNames = Object.keys(eventListeners); + for (let i = 0; i !== eventNames.length; i++) { + removeListener(eventNames[i]); + } +} + +/** + * listenerOff unregisters a listener previously registered with EventsOn + * + * @param {Listener} listener + */ + function listenerOff(listener) { + const eventName = listener.eventName; + // Remove local listener + eventListeners[eventName] = eventListeners[eventName].filter(l => l !== listener); + + // Clean up if there are no event listeners left + if (eventListeners[eventName].length === 0) { + removeListener(eventName); + } +} diff --git a/exp/internal/runtime/desktop/events.test.js b/exp/internal/runtime/desktop/events.test.js new file mode 100644 index 000000000..69ece676f --- /dev/null +++ b/exp/internal/runtime/desktop/events.test.js @@ -0,0 +1,132 @@ +import { EventsOnMultiple, EventsNotify, eventListeners, EventsOn, EventsEmit, EventsOffAll, EventsOnce, EventsOff } from './events' +import { expect, describe, it, beforeAll, vi, afterEach, beforeEach } from 'vitest' +// Edit an assertion and save to see HMR in action + +beforeAll(() => { + window.WailsInvoke = vi.fn(() => {}) +}) + +afterEach(() => { + EventsOffAll(); + vi.resetAllMocks() +}) + +describe('EventsOnMultiple', () => { + it('should stop after a specified number of times', () => { + const cb = vi.fn() + EventsOnMultiple('a', cb, 5) + EventsNotify(JSON.stringify({name: 'a', data: {}})) + EventsNotify(JSON.stringify({name: 'a', data: {}})) + EventsNotify(JSON.stringify({name: 'a', data: {}})) + EventsNotify(JSON.stringify({name: 'a', data: {}})) + EventsNotify(JSON.stringify({name: 'a', data: {}})) + EventsNotify(JSON.stringify({name: 'a', data: {}})) + expect(cb).toBeCalledTimes(5); + expect(window.WailsInvoke).toBeCalledTimes(1); + expect(window.WailsInvoke).toHaveBeenLastCalledWith('EXa'); + }) + + it('should return a cancel fn', () => { + const cb = vi.fn() + const cancel = EventsOnMultiple('a', cb, 5) + EventsNotify(JSON.stringify({name: 'a', data: {}})) + EventsNotify(JSON.stringify({name: 'a', data: {}})) + cancel() + EventsNotify(JSON.stringify({name: 'a', data: {}})) + EventsNotify(JSON.stringify({name: 'a', data: {}})) + expect(cb).toBeCalledTimes(2) + expect(window.WailsInvoke).toBeCalledTimes(1); + expect(window.WailsInvoke).toHaveBeenLastCalledWith('EXa'); + }) +}) + +describe('EventsOn', () => { + it('should create a listener with a count of -1', () => { + EventsOn('a', () => {}) + expect(eventListeners['a'][0].maxCallbacks).toBe(-1) + }) + + it('should return a cancel fn', () => { + const cancel = EventsOn('a', () => {}) + cancel(); + expect(window.WailsInvoke).toBeCalledTimes(1); + expect(window.WailsInvoke).toHaveBeenLastCalledWith('EXa'); + }) +}) + +describe('EventsOnce', () => { + it('should create a listener with a count of 1', () => { + EventsOnce('a', () => {}) + expect(eventListeners['a'][0].maxCallbacks).toBe(1) + }) + + it('should return a cancel fn', () => { + const cancel = EventsOn('a', () => {}) + cancel(); + expect(window.WailsInvoke).toBeCalledTimes(1); + expect(window.WailsInvoke).toHaveBeenLastCalledWith('EXa'); + }) +}) + +describe('EventsNotify', () => { + it('should inform a listener', () => { + const cb = vi.fn() + EventsOn('a', cb) + EventsNotify(JSON.stringify({name: 'a', data: ["one", "two", "three"]})) + expect(cb).toBeCalledTimes(1); + expect(cb).toHaveBeenLastCalledWith("one", "two", "three"); + expect(window.WailsInvoke).toBeCalledTimes(0); + }) +}) + +describe('EventsEmit', () => { + it('should emit an event', () => { + EventsEmit('a', 'one', 'two', 'three') + expect(window.WailsInvoke).toBeCalledTimes(1); + const calledWith = window.WailsInvoke.calls[0][0]; + expect(calledWith.slice(0, 2)).toBe('EE') + expect(JSON.parse(calledWith.slice(2))).toStrictEqual({data: ["one", "two", "three"], name: "a"}) + }) +}) + +describe('EventsOff', () => { + beforeEach(() => { + EventsOn('a', () => {}) + EventsOn('a', () => {}) + EventsOn('a', () => {}) + EventsOn('b', () => {}) + EventsOn('c', () => {}) + }) + + it('should cancel all event listeners for a single type', () => { + EventsOff('a') + expect(eventListeners['a']).toBeUndefined() + expect(eventListeners['b']).not.toBeUndefined() + expect(eventListeners['c']).not.toBeUndefined() + expect(window.WailsInvoke).toBeCalledTimes(1); + expect(window.WailsInvoke).toHaveBeenLastCalledWith('EXa'); + }) + + it('should cancel all event listeners for multiple types', () => { + EventsOff('a', 'b') + expect(eventListeners['a']).toBeUndefined() + expect(eventListeners['b']).toBeUndefined() + expect(eventListeners['c']).not.toBeUndefined() + expect(window.WailsInvoke).toBeCalledTimes(2); + expect(window.WailsInvoke.calls).toStrictEqual([['EXa'], ['EXb']]); + }) +}) + +describe('EventsOffAll', () => { + it('should cancel all event listeners', () => { + EventsOn('a', () => {}) + EventsOn('a', () => {}) + EventsOn('a', () => {}) + EventsOn('b', () => {}) + EventsOn('c', () => {}) + EventsOffAll() + expect(eventListeners).toStrictEqual({}) + expect(window.WailsInvoke).toBeCalledTimes(3); + expect(window.WailsInvoke.calls).toStrictEqual([['EXa'], ['EXb'], ['EXc']]); + }) +}) diff --git a/exp/internal/runtime/desktop/ipc.js b/exp/internal/runtime/desktop/ipc.js new file mode 100644 index 000000000..62fdbdf4b --- /dev/null +++ b/exp/internal/runtime/desktop/ipc.js @@ -0,0 +1,23 @@ +/* + _ __ _ __ +| | / /___ _(_) /____ +| | /| / / __ `/ / / ___/ +| |/ |/ / /_/ / / (__ ) +|__/|__/\__,_/_/_/____/ +The electron alternative for Go +(c) Lea Anthony 2019-present +*/ +/* jshint esversion: 6 */ + +/** + * WailsInvoke sends the given message to the backend + * + * @param {string} message + */ + +(function () { + window.WailsInvoke = (message) => { + WINDOWS && window.chrome.webview.postMessage(message); + (DARWIN || LINUX) && window.webkit.messageHandlers.wails.postMessage(message); + } +})(); \ No newline at end of file diff --git a/exp/internal/runtime/desktop/log.js b/exp/internal/runtime/desktop/log.js new file mode 100644 index 000000000..ff52f5919 --- /dev/null +++ b/exp/internal/runtime/desktop/log.js @@ -0,0 +1,113 @@ +/* + _ __ _ __ +| | / /___ _(_) /____ +| | /| / / __ `/ / / ___/ +| |/ |/ / /_/ / / (__ ) +|__/|__/\__,_/_/_/____/ +The electron alternative for Go +(c) Lea Anthony 2019-present +*/ + +/* jshint esversion: 6 */ + +/** + * Sends a log message to the backend with the given level + message + * + * @param {string} level + * @param {string} message + */ +function sendLogMessage(level, message) { + + // Log Message format: + // l[type][message] + window.WailsInvoke('L' + level + message); +} + +/** + * Log the given trace message with the backend + * + * @export + * @param {string} message + */ +export function LogTrace(message) { + sendLogMessage('T', message); +} + +/** + * Log the given message with the backend + * + * @export + * @param {string} message + */ +export function LogPrint(message) { + sendLogMessage('P', message); +} + +/** + * Log the given debug message with the backend + * + * @export + * @param {string} message + */ +export function LogDebug(message) { + sendLogMessage('D', message); +} + +/** + * Log the given info message with the backend + * + * @export + * @param {string} message + */ +export function LogInfo(message) { + sendLogMessage('I', message); +} + +/** + * Log the given warning message with the backend + * + * @export + * @param {string} message + */ +export function LogWarning(message) { + sendLogMessage('W', message); +} + +/** + * Log the given error message with the backend + * + * @export + * @param {string} message + */ +export function LogError(message) { + sendLogMessage('E', message); +} + +/** + * Log the given fatal message with the backend + * + * @export + * @param {string} message + */ +export function LogFatal(message) { + sendLogMessage('F', message); +} + +/** + * Sets the Log level to the given log level + * + * @export + * @param {number} loglevel + */ +export function SetLogLevel(loglevel) { + sendLogMessage('S', loglevel); +} + +// Log levels +export const LogLevel = { + TRACE: 1, + DEBUG: 2, + INFO: 3, + WARNING: 4, + ERROR: 5, +}; diff --git a/exp/internal/runtime/desktop/main.js b/exp/internal/runtime/desktop/main.js new file mode 100644 index 000000000..331bc866e --- /dev/null +++ b/exp/internal/runtime/desktop/main.js @@ -0,0 +1,80 @@ +/* + _ __ _ __ +| | / /___ _(_) /____ +| | /| / / __ `/ / / ___/ +| |/ |/ / /_/ / / (__ ) +|__/|__/\__,_/_/_/____/ +The electron alternative for Go +(c) Lea Anthony 2019-present +*/ +/* jshint esversion: 9 */ + +import "./ipc.js"; +import {Callback, callbacks} from './calls'; +import {EventsNotify, eventListeners} from "./events"; +import {SetBindings} from "./bindings"; + +import * as Window from "./window"; +import * as Screen from "./screen"; +import * as Browser from "./browser"; +import * as Log from './log'; + +let windowID = -1; + + +export function Quit() { + window.WailsInvoke('Q'); +} + +export function Show() { + window.WailsInvoke('S'); +} + +export function Hide() { + window.WailsInvoke('H'); +} + +// export function Environment() { +// return Call(":wails:Environment"); +// } + +// Internal wails endpoints +window.wails = { + Callback, + callbacks, + EventsNotify, + eventListeners, + SetBindings, + window: { + ID: () => { + return windowID + }, + } +}; + +window.runtime = { + ...Log, + ...Window, + ...Browser, + ...Screen, + EventsOn, + EventsOnce, + EventsOnMultiple, + EventsEmit, + EventsOff, + // Environment, + Show, + Hide, + Quit, +} + +// Process the expected runtime config from the backend +if( window.wails_config ) { + windowID = window.wails_config.windowID; + window.wails_config = null; +} + +if (DEBUG) { + console.log("Wails v3.0.0 Debug Mode Enabled"); +} + diff --git a/exp/internal/runtime/desktop/screen.js b/exp/internal/runtime/desktop/screen.js new file mode 100644 index 000000000..f2afb0506 --- /dev/null +++ b/exp/internal/runtime/desktop/screen.js @@ -0,0 +1,25 @@ +/* + _ __ _ __ +| | / /___ _(_) /____ +| | /| / / __ `/ / / ___/ +| |/ |/ / /_/ / / (__ ) +|__/|__/\__,_/_/_/____/ +The electron alternative for Go +(c) Lea Anthony 2019-present +*/ + +/* jshint esversion: 9 */ + + +import {Call} from "./calls"; + + +/** + * Gets the all screens. Call this anew each time you want to refresh data from the underlying windowing system. + * @export + * @typedef {import('../wrapper/runtime').Screen} Screen + * @return {Promise<{Screen[]}>} The screens + */ +export function ScreenGetAll() { + return Call(":wails:ScreenGetAll"); +} diff --git a/exp/internal/runtime/desktop/window.js b/exp/internal/runtime/desktop/window.js new file mode 100644 index 000000000..f24cdd9c2 --- /dev/null +++ b/exp/internal/runtime/desktop/window.js @@ -0,0 +1,269 @@ +/* + _ __ _ __ +| | / /___ _(_) /____ +| | /| / / __ `/ / / ___/ +| |/ |/ / /_/ / / (__ ) +|__/|__/\__,_/_/_/____/ +The electron alternative for Go +(c) Lea Anthony 2019-present +*/ + +/* jshint esversion: 9 */ + + +import {Call} from "./calls"; + +export function WindowReload() { + window.location.reload(); +} + +export function WindowReloadApp() { + window.WailsInvoke('WR'); +} + +export function WindowSetSystemDefaultTheme() { + window.WailsInvoke('WASDT'); +} + +export function WindowSetLightTheme() { + window.WailsInvoke('WALT'); +} + +export function WindowSetDarkTheme() { + window.WailsInvoke('WADT'); +} + +/** + * Place the window in the center of the screen + * + * @export + */ +export function WindowCenter() { + window.WailsInvoke('Wc'); +} + +/** + * Sets the window title + * + * @param {string} title + * @export + */ +export function WindowSetTitle(title) { + window.WailsInvoke('WT' + title); +} + +/** + * Makes the window go fullscreen + * + * @export + */ +export function WindowFullscreen() { + window.WailsInvoke('WF'); +} + +/** + * Reverts the window from fullscreen + * + * @export + */ +export function WindowUnfullscreen() { + window.WailsInvoke('Wf'); +} + +/** + * Returns the state of the window, i.e. whether the window is in full screen mode or not. + * + * @export + * @return {Promise} The state of the window + */ +export function WindowIsFullscreen() { + return Call(":wails:WindowIsFullscreen"); +} + +/** + * Set the Size of the window + * + * @export + * @param {number} width + * @param {number} height + */ +export function WindowSetSize(width, height) { + window.WailsInvoke('Ws:' + width + ':' + height); +} + +/** + * Get the Size of the window + * + * @export + * @return {Promise<{w: number, h: number}>} The size of the window + + */ +export function WindowGetSize() { + return Call(":wails:WindowGetSize"); +} + +/** + * Set the maximum size of the window + * + * @export + * @param {number} width + * @param {number} height + */ +export function WindowSetMaxSize(width, height) { + window.WailsInvoke('WZ:' + width + ':' + height); +} + +/** + * Set the minimum size of the window + * + * @export + * @param {number} width + * @param {number} height + */ +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 + * + * @export + * @param {number} x + * @param {number} y + */ +export function WindowSetPosition(x, y) { + window.WailsInvoke('Wp:' + x + ':' + y); +} + +/** + * Get the Position of the window + * + * @export + * @return {Promise<{x: number, y: number}>} The position of the window + */ +export function WindowGetPosition() { + return Call(":wails:WindowGetPos"); +} + +/** + * Hide the Window + * + * @export + */ +export function WindowHide() { + window.WailsInvoke('WH'); +} + +/** + * Show the Window + * + * @export + */ +export function WindowShow() { + window.WailsInvoke('WS'); +} + +/** + * Maximise the Window + * + * @export + */ +export function WindowMaximise() { + window.WailsInvoke('WM'); +} + +/** + * Toggle the Maximise of the Window + * + * @export + */ +export function WindowToggleMaximise() { + window.WailsInvoke('Wt'); +} + +/** + * Unmaximise the Window + * + * @export + */ +export function WindowUnmaximise() { + window.WailsInvoke('WU'); +} + +/** + * Returns the state of the window, i.e. whether the window is maximised or not. + * + * @export + * @return {Promise} The state of the window + */ +export function WindowIsMaximised() { + return Call(":wails:WindowIsMaximised"); +} + +/** + * Minimise the Window + * + * @export + */ +export function WindowMinimise() { + window.WailsInvoke('Wm'); +} + +/** + * Unminimise the Window + * + * @export + */ +export function WindowUnminimise() { + window.WailsInvoke('Wu'); +} + +/** + * Returns the state of the window, i.e. whether the window is minimised or not. + * + * @export + * @return {Promise} The state of the window + */ +export function WindowIsMinimised() { + return Call(":wails:WindowIsMinimised"); +} + +/** + * Returns the state of the window, i.e. whether the window is normal or not. + * + * @export + * @return {Promise} The state of the window + */ +export function WindowIsNormal() { + return Call(":wails:WindowIsNormal"); +} + +/** + * Sets the background colour of the window + * + * @export + * @param {number} R Red + * @param {number} G Green + * @param {number} B Blue + * @param {number} A Alpha + */ +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/exp/internal/runtime/dev/Overlay.svelte b/exp/internal/runtime/dev/Overlay.svelte new file mode 100644 index 000000000..dfe02b21b --- /dev/null +++ b/exp/internal/runtime/dev/Overlay.svelte @@ -0,0 +1,54 @@ + + +{#if $overlayVisible } +

+
+
+
+
+{/if} + + \ No newline at end of file diff --git a/exp/internal/runtime/dev/build.js b/exp/internal/runtime/dev/build.js new file mode 100644 index 000000000..6e5e8bb2f --- /dev/null +++ b/exp/internal/runtime/dev/build.js @@ -0,0 +1,15 @@ +/* jshint esversion: 8 */ +const esbuild = require("esbuild"); +const sveltePlugin = require("esbuild-svelte"); + +esbuild + .build({ + entryPoints: ["main.js"], + bundle: true, + minify: true, + outfile: "../ipc_websocket.js", + plugins: [sveltePlugin({compileOptions: {css: true}})], + logLevel: "info", + sourcemap: "inline", + }) + .catch(() => process.exit(1)); \ No newline at end of file diff --git a/exp/internal/runtime/dev/log.js b/exp/internal/runtime/dev/log.js new file mode 100644 index 000000000..e128c97f0 --- /dev/null +++ b/exp/internal/runtime/dev/log.js @@ -0,0 +1,8 @@ +export function log(message) { + // eslint-disable-next-line + console.log( + '%c wails dev %c ' + message + ' ', + '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' + ); +} \ No newline at end of file diff --git a/exp/internal/runtime/dev/main.js b/exp/internal/runtime/dev/main.js new file mode 100644 index 000000000..e6e05be54 --- /dev/null +++ b/exp/internal/runtime/dev/main.js @@ -0,0 +1,125 @@ +/* + _ __ _ __ +| | / /___ _(_) /____ +| | /| / / __ `/ / / ___/ +| |/ |/ / /_/ / / (__ ) +|__/|__/\__,_/_/_/____/ +The electron alternative for Go +(c) Lea Anthony 2019-present +*/ +/* jshint esversion: 6 */ + +import {log} from "./log"; +import Overlay from "./Overlay.svelte"; +import {hideOverlay, showOverlay} from "./store"; + +let components = {}; + +let wailsInvokeInternal = null; +let messageQueue = []; + +window.WailsInvoke = (message) => { + if (!wailsInvokeInternal) { + console.log("Queueing: " + message); + messageQueue.push(message); + return; + } + wailsInvokeInternal(message); +}; + +window.addEventListener('DOMContentLoaded', () => { + components.overlay = new Overlay({ + target: document.body, + anchor: document.querySelector('#wails-spinner'), + }); +}); + +let websocket = null; +let connectTimer; + +window.onbeforeunload = function () { + if (websocket) { + websocket.onclose = function () { + }; + websocket.close(); + websocket = null; + } +}; + +// ...and attempt to connect +connect(); + +function setupIPCBridge() { + wailsInvokeInternal = (message) => { + websocket.send(message); + }; + for (let i = 0; i < messageQueue.length; i++) { + console.log("sending queued message: " + messageQueue[i]); + window.WailsInvoke(messageQueue[i]); + } + messageQueue = []; +} + +// Handles incoming websocket connections +function handleConnect() { + log('Connected to backend'); + hideOverlay(); + setupIPCBridge(); + clearInterval(connectTimer); + websocket.onclose = handleDisconnect; + websocket.onmessage = handleMessage; +} + +// Handles websocket disconnects +function handleDisconnect() { + log('Disconnected from backend'); + websocket = null; + showOverlay(); + connect(); +} + +function _connect() { + if (websocket == null) { + websocket = new WebSocket('ws://' + window.location.host + '/wails/ipc'); + websocket.onopen = handleConnect; + websocket.onerror = function (e) { + e.stopImmediatePropagation(); + e.stopPropagation(); + e.preventDefault(); + websocket = null; + return false; + }; + } +} + +// Try to connect to the backend every .5s +function connect() { + _connect(); + connectTimer = setInterval(_connect, 500); +} + +function handleMessage(message) { + + if (message.data === "reload") { + window.runtime.WindowReload(); + return; + } + if (message.data === "reloadapp") { + window.runtime.WindowReloadApp() + return; + } + + // As a bridge we ignore js and css injections + switch (message.data[0]) { + // Notifications + case 'n': + window.wails.EventsNotify(message.data.slice(1)); + break; + case 'c': + const callbackData = message.data.slice(1); + window.wails.Callback(callbackData); + break; + default: + log('Unknown message: ' + message.data); + } +} diff --git a/exp/internal/runtime/dev/package-lock.json b/exp/internal/runtime/dev/package-lock.json new file mode 100644 index 000000000..c5917b6fd --- /dev/null +++ b/exp/internal/runtime/dev/package-lock.json @@ -0,0 +1,1536 @@ +{ + "name": "dev", + "version": "3.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "dev", + "version": "3.0.0", + "license": "ISC", + "devDependencies": { + "esbuild": "^0.12.17", + "esbuild-svelte": "^0.5.6", + "npm-run-all": "^4.1.5", + "svelte": "^3.49.0" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.18.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz", + "integrity": "sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.3", + "is-string": "^1.0.6", + "object-inspect": "^1.11.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.12.21", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.21.tgz", + "integrity": "sha512-7hyXbU3g94aREufI/5nls7Xcc+RGQeZWZApm6hoBaFvt2BPtpT4TjFMQ9Tb1jU8XyBGz00ShmiyflCogphMHFQ==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + } + }, + "node_modules/esbuild-svelte": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/esbuild-svelte/-/esbuild-svelte-0.5.6.tgz", + "integrity": "sha512-Bz8nU45FrT6sP/Tf3M2rQUuBGxnDSNSPZNIoYwSNt5H+wjSyo/t+zm94tgnOZsR6GgpDMbNQgo4jGbK0NLvEfw==", + "dev": true, + "dependencies": { + "svelte": "^3.42.6" + }, + "peerDependencies": { + "esbuild": ">=0.9.6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", + "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/object-inspect": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", + "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shell-quote": { + "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 + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", + "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", + "dev": true + }, + "node_modules/string.prototype.padend": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.2.tgz", + "integrity": "sha512-/AQFLdYvePENU3W5rgurfWSMU6n+Ww8n/3cUt7E+vPBB/D7YDG8x+qjoFs4M/alR2bW7Qg6xMjVwWUOvuQ0XpQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/svelte": { + "version": "3.52.0", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.52.0.tgz", + "integrity": "sha512-FxcnEUOAVfr10vDU5dVgJN19IvqeHQCS1zfe8vayTfis9A2t5Fhx+JDe5uv/C3j//bB1umpLJ6quhgs9xyUbCQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + } + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.18.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz", + "integrity": "sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.3", + "is-string": "^1.0.6", + "object-inspect": "^1.11.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "esbuild": { + "version": "0.12.21", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.21.tgz", + "integrity": "sha512-7hyXbU3g94aREufI/5nls7Xcc+RGQeZWZApm6hoBaFvt2BPtpT4TjFMQ9Tb1jU8XyBGz00ShmiyflCogphMHFQ==", + "dev": true + }, + "esbuild-svelte": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/esbuild-svelte/-/esbuild-svelte-0.5.6.tgz", + "integrity": "sha512-Bz8nU45FrT6sP/Tf3M2rQUuBGxnDSNSPZNIoYwSNt5H+wjSyo/t+zm94tgnOZsR6GgpDMbNQgo4jGbK0NLvEfw==", + "dev": true, + "requires": { + "svelte": "^3.42.6" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } + }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true + }, + "is-core-module": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", + "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true + }, + "is-number-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + } + }, + "object-inspect": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", + "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shell-quote": { + "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": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", + "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", + "dev": true + }, + "string.prototype.padend": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.2.tgz", + "integrity": "sha512-/AQFLdYvePENU3W5rgurfWSMU6n+Ww8n/3cUt7E+vPBB/D7YDG8x+qjoFs4M/alR2bW7Qg6xMjVwWUOvuQ0XpQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.2" + } + }, + "string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "svelte": { + "version": "3.52.0", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.52.0.tgz", + "integrity": "sha512-FxcnEUOAVfr10vDU5dVgJN19IvqeHQCS1zfe8vayTfis9A2t5Fhx+JDe5uv/C3j//bB1umpLJ6quhgs9xyUbCQ==", + "dev": true + }, + "unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + } + } +} diff --git a/exp/internal/runtime/dev/package.json b/exp/internal/runtime/dev/package.json new file mode 100644 index 000000000..ff5024ed7 --- /dev/null +++ b/exp/internal/runtime/dev/package.json @@ -0,0 +1,18 @@ +{ + "name": "dev", + "version": "3.0.0", + "description": "Wails JS Dev", + "main": "main.js", + "scripts": { + "build": "run-p build:*", + "build:dev": "node build.js" + }, + "author": "Lea Anthony ", + "license": "ISC", + "devDependencies": { + "esbuild": "^0.12.17", + "esbuild-svelte": "^0.5.6", + "npm-run-all": "^4.1.5", + "svelte": "^3.49.0" + } +} diff --git a/exp/internal/runtime/dev/store.js b/exp/internal/runtime/dev/store.js new file mode 100644 index 000000000..fc085570b --- /dev/null +++ b/exp/internal/runtime/dev/store.js @@ -0,0 +1,12 @@ +import {writable} from 'svelte/store'; + +/** Overlay */ +export const overlayVisible = writable(false); + +export function showOverlay() { + overlayVisible.set(true); +} + +export function hideOverlay() { + overlayVisible.set(false); +} diff --git a/exp/internal/runtime/ipc.go b/exp/internal/runtime/ipc.go new file mode 100644 index 000000000..eebcd3027 --- /dev/null +++ b/exp/internal/runtime/ipc.go @@ -0,0 +1,9 @@ +package runtime + +import _ "embed" + +//go:embed ipc_websocket.js +var WebsocketIPC []byte + +//go:embed ipc.js +var DesktopIPC []byte diff --git a/exp/internal/runtime/ipc.js b/exp/internal/runtime/ipc.js new file mode 100644 index 000000000..6066287a8 --- /dev/null +++ b/exp/internal/runtime/ipc.js @@ -0,0 +1 @@ +(()=>{(function(){window.WailsInvoke=e=>{WINDOWS&&window.chrome.webview.postMessage(e),(DARWIN||LINUX)&&window.webkit.messageHandlers.wails.postMessage(e)}})();})(); diff --git a/exp/internal/runtime/ipc_websocket.js b/exp/internal/runtime/ipc_websocket.js new file mode 100644 index 000000000..d5dca66af --- /dev/null +++ b/exp/internal/runtime/ipc_websocket.js @@ -0,0 +1,22 @@ +(()=>{function D(t){console.log("%c wails dev %c "+t+" ","background: #aa0000; color: #fff; border-radius: 3px 0px 0px 3px; padding: 1px; font-size: 0.7rem","background: #009900; color: #fff; border-radius: 0px 3px 3px 0px; padding: 1px; font-size: 0.7rem")}function p(){}var A=t=>t;function N(t){return t()}function it(){return Object.create(null)}function b(t){t.forEach(N)}function w(t){return typeof t=="function"}function L(t,e){return t!=t?e==e:t!==e||t&&typeof t=="object"||typeof t=="function"}function ot(t){return Object.keys(t).length===0}function rt(t,...e){if(t==null)return p;let n=t.subscribe(...e);return n.unsubscribe?()=>n.unsubscribe():n}function st(t,e,n){t.$$.on_destroy.push(rt(e,n))}var ct=typeof window!="undefined",Ot=ct?()=>window.performance.now():()=>Date.now(),P=ct?t=>requestAnimationFrame(t):p;var x=new Set;function lt(t){x.forEach(e=>{e.c(t)||(x.delete(e),e.f())}),x.size!==0&&P(lt)}function Dt(t){let e;return x.size===0&&P(lt),{promise:new Promise(n=>{x.add(e={c:t,f:n})}),abort(){x.delete(e)}}}var ut=!1;function At(){ut=!0}function Lt(){ut=!1}function Bt(t,e){t.appendChild(e)}function at(t,e,n){let i=R(t);if(!i.getElementById(e)){let o=B("style");o.id=e,o.textContent=n,ft(i,o)}}function R(t){if(!t)return document;let e=t.getRootNode?t.getRootNode():t.ownerDocument;return e&&e.host?e:t.ownerDocument}function Tt(t){let e=B("style");return ft(R(t),e),e.sheet}function ft(t,e){return Bt(t.head||t,e),e.sheet}function W(t,e,n){t.insertBefore(e,n||null)}function S(t){t.parentNode.removeChild(t)}function B(t){return document.createElement(t)}function Jt(t){return document.createTextNode(t)}function dt(){return Jt("")}function ht(t,e,n){n==null?t.removeAttribute(e):t.getAttribute(e)!==n&&t.setAttribute(e,n)}function zt(t){return Array.from(t.childNodes)}function Ht(t,e,{bubbles:n=!1,cancelable:i=!1}={}){let o=document.createEvent("CustomEvent");return o.initCustomEvent(t,n,i,e),o}var T=new Map,J=0;function Gt(t){let e=5381,n=t.length;for(;n--;)e=(e<<5)-e^t.charCodeAt(n);return e>>>0}function qt(t,e){let n={stylesheet:Tt(e),rules:{}};return T.set(t,n),n}function _t(t,e,n,i,o,c,s,l=0){let f=16.666/i,r=`{ +`;for(let g=0;g<=1;g+=f){let F=e+(n-e)*c(g);r+=g*100+`%{${s(F,1-F)}} +`}let y=r+`100% {${s(n,1-n)}} +}`,a=`__svelte_${Gt(y)}_${l}`,u=R(t),{stylesheet:h,rules:_}=T.get(u)||qt(u,t);_[a]||(_[a]=!0,h.insertRule(`@keyframes ${a} ${y}`,h.cssRules.length));let v=t.style.animation||"";return t.style.animation=`${v?`${v}, `:""}${a} ${i}ms linear ${o}ms 1 both`,J+=1,a}function Kt(t,e){let n=(t.style.animation||"").split(", "),i=n.filter(e?c=>c.indexOf(e)<0:c=>c.indexOf("__svelte")===-1),o=n.length-i.length;o&&(t.style.animation=i.join(", "),J-=o,J||Nt())}function Nt(){P(()=>{J||(T.forEach(t=>{let{ownerNode:e}=t.stylesheet;e&&S(e)}),T.clear())})}var V;function C(t){V=t}var k=[];var pt=[],z=[],mt=[],Pt=Promise.resolve(),U=!1;function Rt(){U||(U=!0,Pt.then(yt))}function $(t){z.push(t)}var X=new Set,H=0;function yt(){let t=V;do{for(;H{E=null})),E}function Z(t,e,n){t.dispatchEvent(Ht(`${e?"intro":"outro"}${n}`))}var G=new Set,m;function gt(){m={r:0,c:[],p:m}}function bt(){m.r||b(m.c),m=m.p}function I(t,e){t&&t.i&&(G.delete(t),t.i(e))}function Q(t,e,n,i){if(t&&t.o){if(G.has(t))return;G.add(t),m.c.push(()=>{G.delete(t),i&&(n&&t.d(1),i())}),t.o(e)}else i&&i()}var Ut={duration:0};function Y(t,e,n,i){let o=e(t,n),c=i?0:1,s=null,l=null,f=null;function r(){f&&Kt(t,f)}function y(u,h){let _=u.b-c;return h*=Math.abs(_),{a:c,b:u.b,d:_,duration:h,start:u.start,end:u.start+h,group:u.group}}function a(u){let{delay:h=0,duration:_=300,easing:v=A,tick:g=p,css:F}=o||Ut,K={start:Ot()+h,b:u};u||(K.group=m,m.r+=1),s||l?l=K:(F&&(r(),f=_t(t,c,u,_,h,v,F)),u&&g(0,1),s=y(K,_),$(()=>Z(t,u,"start")),Dt(O=>{if(l&&O>l.start&&(s=y(l,_),l=null,Z(t,s.b,"start"),F&&(r(),f=_t(t,c,s.b,s.duration,0,v,o.css))),s){if(O>=s.end)g(c=s.b,1-c),Z(t,s.b,"end"),l||(s.b?r():--s.group.r||b(s.group.c)),s=null;else if(O>=s.start){let jt=O-s.start;c=s.a+s.d*v(jt/s.duration),g(c,1-c)}}return!!(s||l)}))}return{run(u){w(o)?Vt().then(()=>{o=o(),a(u)}):a(u)},end(){r(),s=l=null}}}var le=typeof window!="undefined"?window:typeof globalThis!="undefined"?globalThis:global;var ue=new Set(["allowfullscreen","allowpaymentrequest","async","autofocus","autoplay","checked","controls","default","defer","disabled","formnovalidate","hidden","inert","ismap","itemscope","loop","multiple","muted","nomodule","novalidate","open","playsinline","readonly","required","reversed","selected"]);function Xt(t,e,n,i){let{fragment:o,after_update:c}=t.$$;o&&o.m(e,n),i||$(()=>{let s=t.$$.on_mount.map(N).filter(w);t.$$.on_destroy?t.$$.on_destroy.push(...s):b(s),t.$$.on_mount=[]}),c.forEach($)}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 Zt(t,e){t.$$.dirty[0]===-1&&(k.push(t),Rt(),t.$$.dirty.fill(0)),t.$$.dirty[e/31|0]|=1<{let _=h.length?h[0]:u;return r.ctx&&o(r.ctx[a],r.ctx[a]=_)&&(!r.skip_bound&&r.bound[a]&&r.bound[a](_),y&&Zt(t,a)),u}):[],r.update(),y=!0,b(r.before_update),r.fragment=i?i(r.ctx):!1,e.target){if(e.hydrate){At();let a=zt(e.target);r.fragment&&r.fragment.l(a),a.forEach(S)}else r.fragment&&r.fragment.c();e.intro&&I(t.$$.fragment),Xt(t,e.target,e.anchor,e.customElement),Lt(),yt()}C(f)}var Qt;typeof HTMLElement=="function"&&(Qt=class extends HTMLElement{constructor(){super();this.attachShadow({mode:"open"})}connectedCallback(){let{on_mount:t}=this.$$;this.$$.on_disconnect=t.map(N).filter(w);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=p}$on(t,e){if(!w(e))return p;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&&!ot(t)&&(this.$$.skip_bound=!0,this.$$set(t),this.$$.skip_bound=!1)}});var tt=class{$destroy(){wt(this,1),this.$destroy=p}$on(e,n){if(!w(n))return p;let i=this.$$.callbacks[e]||(this.$$.callbacks[e]=[]);return i.push(n),()=>{let o=i.indexOf(n);o!==-1&&i.splice(o,1)}}$set(e){this.$$set&&!ot(e)&&(this.$$.skip_bound=!0,this.$$set(e),this.$$.skip_bound=!1)}};var M=[];function Ft(t,e=p){let n,i=new Set;function o(l){if(L(t,l)&&(t=l,n)){let f=!M.length;for(let r of i)r[1](),M.push(r,t);if(f){for(let r=0;r{i.delete(r),i.size===0&&(n(),n=null)}}return{set:o,update:c,subscribe:s}}var q=Ft(!1);function xt(){q.set(!0)}function $t(){q.set(!1)}function et(t,{delay:e=0,duration:n=400,easing:i=A}={}){let o=+getComputedStyle(t).opacity;return{delay:e,duration:n,easing:i,css:c=>`opacity: ${c*o}`}}function Yt(t){at(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,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);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 + }@keyframes svelte-181h7z-loadingspin{100%{transform:rotate(360deg)}}`)}function Mt(t){let e,n,i;return{c(){e=B("div"),e.innerHTML='
',ht(e,"class","wails-reconnect-overlay svelte-181h7z")},m(o,c){W(o,e,c),i=!0},i(o){i||($(()=>{n||(n=Y(e,et,{duration:300},!0)),n.run(1)}),i=!0)},o(o){n||(n=Y(e,et,{duration:300},!1)),n.run(0),i=!1},d(o){o&&S(e),o&&n&&n.end()}}}function te(t){let e,n,i=t[0]&&Mt(t);return{c(){i&&i.c(),e=dt()},m(o,c){i&&i.m(o,c),W(o,e,c),n=!0},p(o,[c]){o[0]?i?c&1&&I(i,1):(i=Mt(o),i.c(),I(i,1),i.m(e.parentNode,e)):i&&(gt(),Q(i,1,1,()=>{i=null}),bt())},i(o){n||(I(i),n=!0)},o(o){Q(i),n=!1},d(o){i&&i.d(o),o&&S(e)}}}function ee(t,e,n){let i;return st(t,q,o=>n(0,i=o)),[i]}var St=class extends tt{constructor(e){super();vt(this,e,ee,te,L,{},Yt)}},Ct=St;var ne={},nt=null,j=[];window.WailsInvoke=t=>{if(!nt){console.log("Queueing: "+t),j.push(t);return}nt(t)};window.addEventListener("DOMContentLoaded",()=>{ne.overlay=new Ct({target:document.body,anchor:document.querySelector("#wails-spinner")})});var d=null,kt;window.onbeforeunload=function(){d&&(d.onclose=function(){},d.close(),d=null)};It();function ie(){nt=t=>{d.send(t)};for(let t=0;t=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz", + "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@types/chai": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", + "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", + "dev": true + }, + "node_modules/@types/chai-subset": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz", + "integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==", + "dev": true, + "dependencies": { + "@types/chai": "*" + } + }, + "node_modules/@types/node": { + "version": "18.11.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", + "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/chai": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", + "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^4.1.2", + "get-func-name": "^2.0.0", + "loupe": "^2.3.1", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/esbuild": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", + "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.15.18", + "@esbuild/linux-loong64": "0.15.18", + "esbuild-android-64": "0.15.18", + "esbuild-android-arm64": "0.15.18", + "esbuild-darwin-64": "0.15.18", + "esbuild-darwin-arm64": "0.15.18", + "esbuild-freebsd-64": "0.15.18", + "esbuild-freebsd-arm64": "0.15.18", + "esbuild-linux-32": "0.15.18", + "esbuild-linux-64": "0.15.18", + "esbuild-linux-arm": "0.15.18", + "esbuild-linux-arm64": "0.15.18", + "esbuild-linux-mips64le": "0.15.18", + "esbuild-linux-ppc64le": "0.15.18", + "esbuild-linux-riscv64": "0.15.18", + "esbuild-linux-s390x": "0.15.18", + "esbuild-netbsd-64": "0.15.18", + "esbuild-openbsd-64": "0.15.18", + "esbuild-sunos-64": "0.15.18", + "esbuild-windows-32": "0.15.18", + "esbuild-windows-64": "0.15.18", + "esbuild-windows-arm64": "0.15.18" + } + }, + "node_modules/esbuild-android-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz", + "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-android-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz", + "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz", + "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz", + "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz", + "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz", + "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-32": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz", + "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz", + "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz", + "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz", + "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz", + "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz", + "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-riscv64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz", + "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-s390x": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz", + "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz", + "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz", + "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-sunos-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz", + "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-32": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz", + "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz", + "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", + "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/happy-dom": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-8.1.3.tgz", + "integrity": "sha512-XC0ZvAmMOfW56X7yw9IrBuVpHKRzVAMDbtoF4MmOHoe17r2zY6yTMhs+lrsz9KLGQUcFyDPianULPAOp1+OnVg==", + "dev": true, + "dependencies": { + "css.escape": "^1.5.1", + "he": "^1.2.0", + "node-fetch": "^2.x.x", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-core-module": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/local-pkg": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.2.tgz", + "integrity": "sha512-mlERgSPrbxU3BP4qBqAvvwlgW4MTg78iwJdGGnv7kibKjWcJksrG3t6LB5lXI93wXRDvG4NpUgJFmTG4T6rdrg==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/loupe": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", + "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.0" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/postcss": { + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rollup": { + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-literal": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-0.4.2.tgz", + "integrity": "sha512-pv48ybn4iE1O9RLgCAN0iU4Xv7RlBTiit6DKmMiErbs9x1wH6vXBs45tWc0H5wUIF6TLTrKweqkmYF/iraQKNw==", + "dev": true, + "dependencies": { + "acorn": "^8.8.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tinybench": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.3.1.tgz", + "integrity": "sha512-hGYWYBMPr7p4g5IarQE7XhlyWveh1EKhy4wUBS1LrHXCKYgvz+4/jCqgmJqZxxldesn05vccrtME2RLLZNW7iA==", + "dev": true + }, + "node_modules/tinypool": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.3.0.tgz", + "integrity": "sha512-NX5KeqHOBZU6Bc0xj9Vr5Szbb1j8tUHIeD18s41aDJaPeC5QTdEhK0SpdpUrZlj2nv5cctNcSjaKNanXlfcVEQ==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-1.0.2.tgz", + "integrity": "sha512-bSGlgwLBYf7PnUsQ6WOc6SJ3pGOcd+d8AA6EUnLDDM0kWEstC1JIlSZA3UNliDXhd9ABoS7hiRBDCu+XP/sf1Q==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/vite": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.5.tgz", + "integrity": "sha512-4mVEpXpSOgrssFZAOmGIr85wPHKvaDAcXqxVxVRZhljkJOMZi1ibLibzjLHzJvcok8BMguLc7g1W6W/GqZbLdQ==", + "dev": true, + "dependencies": { + "esbuild": "^0.15.9", + "postcss": "^8.4.18", + "resolve": "^1.22.1", + "rollup": "^2.79.1" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vitest": { + "version": "0.24.5", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.24.5.tgz", + "integrity": "sha512-zw6JhPUHtLILQDe5Q39b/SzoITkG+R7hcFjuthp4xsi6zpmfQPOZcHodZ+3bqoWl4EdGK/p1fuMiEwdxgbGLOA==", + "dev": true, + "dependencies": { + "@types/chai": "^4.3.3", + "@types/chai-subset": "^1.3.3", + "@types/node": "*", + "chai": "^4.3.6", + "debug": "^4.3.4", + "local-pkg": "^0.4.2", + "strip-literal": "^0.4.2", + "tinybench": "^2.3.1", + "tinypool": "^0.3.0", + "tinyspy": "^1.0.2", + "vite": "^3.0.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": ">=v14.16.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@vitest/browser": "*", + "@vitest/ui": "*", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/whatwg-url/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + } + }, + "dependencies": { + "@esbuild/android-arm": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz", + "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz", + "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==", + "dev": true, + "optional": true + }, + "@types/chai": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", + "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", + "dev": true + }, + "@types/chai-subset": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz", + "integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==", + "dev": true, + "requires": { + "@types/chai": "*" + } + }, + "@types/node": { + "version": "18.11.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", + "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==", + "dev": true + }, + "acorn": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "dev": true + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "chai": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", + "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^4.1.2", + "get-func-name": "^2.0.0", + "loupe": "^2.3.1", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", + "dev": true + }, + "css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } + }, + "esbuild": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", + "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.15.18", + "@esbuild/linux-loong64": "0.15.18", + "esbuild-android-64": "0.15.18", + "esbuild-android-arm64": "0.15.18", + "esbuild-darwin-64": "0.15.18", + "esbuild-darwin-arm64": "0.15.18", + "esbuild-freebsd-64": "0.15.18", + "esbuild-freebsd-arm64": "0.15.18", + "esbuild-linux-32": "0.15.18", + "esbuild-linux-64": "0.15.18", + "esbuild-linux-arm": "0.15.18", + "esbuild-linux-arm64": "0.15.18", + "esbuild-linux-mips64le": "0.15.18", + "esbuild-linux-ppc64le": "0.15.18", + "esbuild-linux-riscv64": "0.15.18", + "esbuild-linux-s390x": "0.15.18", + "esbuild-netbsd-64": "0.15.18", + "esbuild-openbsd-64": "0.15.18", + "esbuild-sunos-64": "0.15.18", + "esbuild-windows-32": "0.15.18", + "esbuild-windows-64": "0.15.18", + "esbuild-windows-arm64": "0.15.18" + } + }, + "esbuild-android-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz", + "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==", + "dev": true, + "optional": true + }, + "esbuild-android-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz", + "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==", + "dev": true, + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz", + "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==", + "dev": true, + "optional": true + }, + "esbuild-darwin-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz", + "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz", + "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz", + "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==", + "dev": true, + "optional": true + }, + "esbuild-linux-32": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz", + "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==", + "dev": true, + "optional": true + }, + "esbuild-linux-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz", + "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz", + "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz", + "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==", + "dev": true, + "optional": true + }, + "esbuild-linux-mips64le": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz", + "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-ppc64le": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz", + "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==", + "dev": true, + "optional": true + }, + "esbuild-linux-riscv64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz", + "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==", + "dev": true, + "optional": true + }, + "esbuild-linux-s390x": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz", + "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==", + "dev": true, + "optional": true + }, + "esbuild-netbsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz", + "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==", + "dev": true, + "optional": true + }, + "esbuild-openbsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz", + "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==", + "dev": true, + "optional": true + }, + "esbuild-sunos-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz", + "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==", + "dev": true, + "optional": true + }, + "esbuild-windows-32": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz", + "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==", + "dev": true, + "optional": true + }, + "esbuild-windows-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz", + "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==", + "dev": true, + "optional": true + }, + "esbuild-windows-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", + "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", + "dev": true, + "optional": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", + "dev": true + }, + "happy-dom": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-8.1.3.tgz", + "integrity": "sha512-XC0ZvAmMOfW56X7yw9IrBuVpHKRzVAMDbtoF4MmOHoe17r2zY6yTMhs+lrsz9KLGQUcFyDPianULPAOp1+OnVg==", + "dev": true, + "requires": { + "css.escape": "^1.5.1", + "he": "^1.2.0", + "node-fetch": "^2.x.x", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "is-core-module": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "local-pkg": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.2.tgz", + "integrity": "sha512-mlERgSPrbxU3BP4qBqAvvwlgW4MTg78iwJdGGnv7kibKjWcJksrG3t6LB5lXI93wXRDvG4NpUgJFmTG4T6rdrg==", + "dev": true + }, + "loupe": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", + "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "dev": true, + "requires": { + "get-func-name": "^2.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "postcss": { + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "dev": true, + "requires": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "rollup": { + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true + }, + "strip-literal": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-0.4.2.tgz", + "integrity": "sha512-pv48ybn4iE1O9RLgCAN0iU4Xv7RlBTiit6DKmMiErbs9x1wH6vXBs45tWc0H5wUIF6TLTrKweqkmYF/iraQKNw==", + "dev": true, + "requires": { + "acorn": "^8.8.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "tinybench": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.3.1.tgz", + "integrity": "sha512-hGYWYBMPr7p4g5IarQE7XhlyWveh1EKhy4wUBS1LrHXCKYgvz+4/jCqgmJqZxxldesn05vccrtME2RLLZNW7iA==", + "dev": true + }, + "tinypool": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.3.0.tgz", + "integrity": "sha512-NX5KeqHOBZU6Bc0xj9Vr5Szbb1j8tUHIeD18s41aDJaPeC5QTdEhK0SpdpUrZlj2nv5cctNcSjaKNanXlfcVEQ==", + "dev": true + }, + "tinyspy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-1.0.2.tgz", + "integrity": "sha512-bSGlgwLBYf7PnUsQ6WOc6SJ3pGOcd+d8AA6EUnLDDM0kWEstC1JIlSZA3UNliDXhd9ABoS7hiRBDCu+XP/sf1Q==", + "dev": true + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "vite": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.5.tgz", + "integrity": "sha512-4mVEpXpSOgrssFZAOmGIr85wPHKvaDAcXqxVxVRZhljkJOMZi1ibLibzjLHzJvcok8BMguLc7g1W6W/GqZbLdQ==", + "dev": true, + "requires": { + "esbuild": "^0.15.9", + "fsevents": "~2.3.2", + "postcss": "^8.4.18", + "resolve": "^1.22.1", + "rollup": "^2.79.1" + } + }, + "vitest": { + "version": "0.24.5", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.24.5.tgz", + "integrity": "sha512-zw6JhPUHtLILQDe5Q39b/SzoITkG+R7hcFjuthp4xsi6zpmfQPOZcHodZ+3bqoWl4EdGK/p1fuMiEwdxgbGLOA==", + "dev": true, + "requires": { + "@types/chai": "^4.3.3", + "@types/chai-subset": "^1.3.3", + "@types/node": "*", + "chai": "^4.3.6", + "debug": "^4.3.4", + "local-pkg": "^0.4.2", + "strip-literal": "^0.4.2", + "tinybench": "^2.3.1", + "tinypool": "^0.3.0", + "tinyspy": "^1.0.2", + "vite": "^3.0.0" + } + }, + "webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true + }, + "whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, + "requires": { + "iconv-lite": "0.6.3" + } + }, + "whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + }, + "dependencies": { + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + } + } + } + } +} diff --git a/exp/internal/runtime/package.json b/exp/internal/runtime/package.json new file mode 100644 index 000000000..2100ea70c --- /dev/null +++ b/exp/internal/runtime/package.json @@ -0,0 +1,14 @@ +{ + "name": "runtime", + "version": "3.0.0", + "description": "Wails JS Runtime", + "main": "index.js", + "scripts": {}, + "author": "Lea Anthony ", + "license": "ISC", + "devDependencies": { + "esbuild": "^0.15.6", + "happy-dom": "^8.1.3", + "vitest": "^0.24.3" + } +} diff --git a/exp/internal/runtime/runtime_debug_darwin.go b/exp/internal/runtime/runtime_debug_darwin.go new file mode 100644 index 000000000..14656126f --- /dev/null +++ b/exp/internal/runtime/runtime_debug_darwin.go @@ -0,0 +1,8 @@ +//go:build darwin && !production + +package runtime + +import _ "embed" + +//go:embed runtime_debug_desktop_darwin.js +var DesktopRuntime []byte diff --git a/exp/internal/runtime/runtime_debug_desktop_darwin.js b/exp/internal/runtime/runtime_debug_desktop_darwin.js new file mode 100644 index 000000000..d8fbf5def --- /dev/null +++ b/exp/internal/runtime/runtime_debug_desktop_darwin.js @@ -0,0 +1,420 @@ +(() => { + var __defProp = Object.defineProperty; + var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); + }; + + // desktop/ipc.js + (function() { + window.WailsInvoke = (message) => { + window.webkit.messageHandlers.wails.postMessage(message); + }; + })(); + + // desktop/calls.js + var callbacks = {}; + function cryptoRandom() { + var array = new Uint32Array(1); + return window.crypto.getRandomValues(array)[0]; + } + function basicRandom() { + return Math.random() * 9007199254740991; + } + var randomFunc; + if (window.crypto) { + randomFunc = cryptoRandom; + } else { + randomFunc = basicRandom; + } + function Call(name, args, timeout) { + if (timeout == null) { + timeout = 0; + } + let windowID2 = window.wails.window.ID(); + return new Promise(function(resolve, reject) { + var callbackID; + do { + callbackID = name + "-" + randomFunc(); + } while (callbacks[callbackID]); + var timeoutHandle; + if (timeout > 0) { + timeoutHandle = setTimeout(function() { + reject(Error("Call to " + name + " timed out. Request ID: " + callbackID)); + }, timeout); + } + callbacks[callbackID] = { + timeoutHandle, + reject, + resolve + }; + try { + const payload = { + name, + args, + callbackID, + windowID: windowID2 + }; + window.WailsInvoke("C" + JSON.stringify(payload)); + } catch (e) { + console.error(e); + } + }); + } + window.ObfuscatedCall = (id, args, timeout) => { + if (timeout == null) { + timeout = 0; + } + return new Promise(function(resolve, reject) { + var callbackID; + do { + callbackID = id + "-" + randomFunc(); + } while (callbacks[callbackID]); + var timeoutHandle; + if (timeout > 0) { + timeoutHandle = setTimeout(function() { + reject(Error("Call to method " + id + " timed out. Request ID: " + callbackID)); + }, timeout); + } + callbacks[callbackID] = { + timeoutHandle, + reject, + resolve + }; + try { + const payload = { + id, + args, + callbackID, + windowID: window.wails.window.ID() + }; + window.WailsInvoke("c" + JSON.stringify(payload)); + } catch (e) { + console.error(e); + } + }); + }; + function Callback(incomingMessage) { + let message; + try { + message = JSON.parse(incomingMessage); + } catch (e) { + const error = `Invalid JSON passed to callback: ${e.message}. Message: ${incomingMessage}`; + runtime.LogDebug(error); + throw new Error(error); + } + let callbackID = message.callbackid; + let callbackData = callbacks[callbackID]; + if (!callbackData) { + const error = `Callback '${callbackID}' not registered!!!`; + console.error(error); + throw new Error(error); + } + clearTimeout(callbackData.timeoutHandle); + delete callbacks[callbackID]; + if (message.error) { + callbackData.reject(message.error); + } else { + callbackData.resolve(message.result); + } + } + + // desktop/events.js + var eventListeners = {}; + function notifyListeners(eventData) { + let eventName = eventData.name; + if (eventListeners[eventName]) { + const newEventListenerList = eventListeners[eventName].slice(); + for (let count = 0; count < eventListeners[eventName].length; count += 1) { + const listener = eventListeners[eventName][count]; + let data = eventData.data; + const destroy = listener.Callback(data); + if (destroy) { + newEventListenerList.splice(count, 1); + } + } + if (newEventListenerList.length === 0) { + removeListener(eventName); + } else { + eventListeners[eventName] = newEventListenerList; + } + } + } + function EventsNotify(notifyMessage) { + let message; + try { + message = JSON.parse(notifyMessage); + } catch (e) { + const error = "Invalid JSON passed to Notify: " + notifyMessage; + throw new Error(error); + } + notifyListeners(message); + } + function removeListener(eventName) { + delete eventListeners[eventName]; + window.WailsInvoke("EX" + eventName); + } + + // desktop/bindings.js + window.go = {}; + function SetBindings(bindingsMap) { + try { + bindingsMap = JSON.parse(bindingsMap); + } catch (e) { + console.error(e); + } + window.go = window.go || {}; + Object.keys(bindingsMap).forEach((packageName) => { + window.go[packageName] = window.go[packageName] || {}; + Object.keys(bindingsMap[packageName]).forEach((structName) => { + window.go[packageName][structName] = window.go[packageName][structName] || {}; + Object.keys(bindingsMap[packageName][structName]).forEach((methodName) => { + window.go[packageName][structName][methodName] = function() { + let timeout = 0; + function dynamic() { + const args = [].slice.call(arguments); + return Call([packageName, structName, methodName].join("."), args, timeout); + } + dynamic.setTimeout = function(newTimeout) { + timeout = newTimeout; + }; + dynamic.getTimeout = function() { + return timeout; + }; + return dynamic; + }(); + }); + }); + }); + } + + // desktop/window.js + var window_exports = {}; + __export(window_exports, { + WindowCenter: () => WindowCenter, + WindowFullscreen: () => WindowFullscreen, + WindowGetPosition: () => WindowGetPosition, + WindowGetSize: () => WindowGetSize, + WindowHide: () => WindowHide, + WindowIsFullscreen: () => WindowIsFullscreen, + WindowIsMaximised: () => WindowIsMaximised, + WindowIsMinimised: () => WindowIsMinimised, + WindowIsNormal: () => WindowIsNormal, + WindowMaximise: () => WindowMaximise, + WindowMinimise: () => WindowMinimise, + WindowReload: () => WindowReload, + WindowReloadApp: () => WindowReloadApp, + WindowSetAlwaysOnTop: () => WindowSetAlwaysOnTop, + WindowSetBackgroundColour: () => WindowSetBackgroundColour, + WindowSetDarkTheme: () => WindowSetDarkTheme, + WindowSetLightTheme: () => WindowSetLightTheme, + WindowSetMaxSize: () => WindowSetMaxSize, + WindowSetMinSize: () => WindowSetMinSize, + WindowSetPosition: () => WindowSetPosition, + WindowSetSize: () => WindowSetSize, + WindowSetSystemDefaultTheme: () => WindowSetSystemDefaultTheme, + WindowSetTitle: () => WindowSetTitle, + WindowShow: () => WindowShow, + WindowToggleMaximise: () => WindowToggleMaximise, + WindowUnfullscreen: () => WindowUnfullscreen, + WindowUnmaximise: () => WindowUnmaximise, + WindowUnminimise: () => WindowUnminimise + }); + function WindowReload() { + window.location.reload(); + } + function WindowReloadApp() { + window.WailsInvoke("WR"); + } + function WindowSetSystemDefaultTheme() { + window.WailsInvoke("WASDT"); + } + function WindowSetLightTheme() { + window.WailsInvoke("WALT"); + } + function WindowSetDarkTheme() { + window.WailsInvoke("WADT"); + } + function WindowCenter() { + window.WailsInvoke("Wc"); + } + function WindowSetTitle(title) { + window.WailsInvoke("WT" + title); + } + function WindowFullscreen() { + window.WailsInvoke("WF"); + } + function WindowUnfullscreen() { + window.WailsInvoke("Wf"); + } + function WindowIsFullscreen() { + return Call(":wails:WindowIsFullscreen"); + } + function WindowSetSize(width, height) { + window.WailsInvoke("Ws:" + width + ":" + height); + } + function WindowGetSize() { + return Call(":wails:WindowGetSize"); + } + function WindowSetMaxSize(width, height) { + window.WailsInvoke("WZ:" + width + ":" + height); + } + 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); + } + function WindowGetPosition() { + return Call(":wails:WindowGetPos"); + } + function WindowHide() { + window.WailsInvoke("WH"); + } + function WindowShow() { + window.WailsInvoke("WS"); + } + function WindowMaximise() { + window.WailsInvoke("WM"); + } + function WindowToggleMaximise() { + window.WailsInvoke("Wt"); + } + function WindowUnmaximise() { + window.WailsInvoke("WU"); + } + function WindowIsMaximised() { + return Call(":wails:WindowIsMaximised"); + } + function WindowMinimise() { + window.WailsInvoke("Wm"); + } + function WindowUnminimise() { + window.WailsInvoke("Wu"); + } + function WindowIsMinimised() { + return Call(":wails:WindowIsMinimised"); + } + function WindowIsNormal() { + return Call(":wails:WindowIsNormal"); + } + 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); + } + + // desktop/screen.js + var screen_exports = {}; + __export(screen_exports, { + ScreenGetAll: () => ScreenGetAll + }); + function ScreenGetAll() { + return Call(":wails:ScreenGetAll"); + } + + // desktop/browser.js + var browser_exports = {}; + __export(browser_exports, { + BrowserOpenURL: () => BrowserOpenURL + }); + function BrowserOpenURL(url) { + window.WailsInvoke("BO:" + url); + } + + // desktop/log.js + var log_exports = {}; + __export(log_exports, { + LogDebug: () => LogDebug, + LogError: () => LogError, + LogFatal: () => LogFatal, + LogInfo: () => LogInfo, + LogLevel: () => LogLevel, + LogPrint: () => LogPrint, + LogTrace: () => LogTrace, + LogWarning: () => LogWarning, + SetLogLevel: () => SetLogLevel + }); + function sendLogMessage(level, message) { + window.WailsInvoke("L" + level + message); + } + function LogTrace(message) { + sendLogMessage("T", message); + } + function LogPrint(message) { + sendLogMessage("P", message); + } + function LogDebug(message) { + sendLogMessage("D", message); + } + function LogInfo(message) { + sendLogMessage("I", message); + } + function LogWarning(message) { + sendLogMessage("W", message); + } + function LogError(message) { + sendLogMessage("E", message); + } + function LogFatal(message) { + sendLogMessage("F", message); + } + function SetLogLevel(loglevel) { + sendLogMessage("S", loglevel); + } + var LogLevel = { + TRACE: 1, + DEBUG: 2, + INFO: 3, + WARNING: 4, + ERROR: 5 + }; + + // desktop/main.js + var windowID = -1; + function Quit() { + window.WailsInvoke("Q"); + } + function Show() { + window.WailsInvoke("S"); + } + function Hide() { + window.WailsInvoke("H"); + } + window.wails = { + Callback, + callbacks, + EventsNotify, + eventListeners, + SetBindings, + window: { + ID: () => { + return windowID; + } + } + }; + window.runtime = { + ...log_exports, + ...window_exports, + ...browser_exports, + ...screen_exports, + EventsOn, + EventsOnce, + EventsOnMultiple, + EventsEmit, + EventsOff, + Show, + Hide, + Quit + }; + if (window.wails_config) { + windowID = window.wails_config.windowID; + window.wails_config = null; + } + if (true) { + console.log("Wails v3.0.0 Debug Mode Enabled"); + } +})(); +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiZGVza3RvcC9pcGMuanMiLCAiZGVza3RvcC9jYWxscy5qcyIsICJkZXNrdG9wL2V2ZW50cy5qcyIsICJkZXNrdG9wL2JpbmRpbmdzLmpzIiwgImRlc2t0b3Avd2luZG93LmpzIiwgImRlc2t0b3Avc2NyZWVuLmpzIiwgImRlc2t0b3AvYnJvd3Nlci5qcyIsICJkZXNrdG9wL2xvZy5qcyIsICJkZXNrdG9wL21haW4uanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qXG4gXyAgICAgICBfXyAgICAgIF8gX19cbnwgfCAgICAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuLyoganNoaW50IGVzdmVyc2lvbjogNiAqL1xuXG4vKipcbiAqIFdhaWxzSW52b2tlIHNlbmRzIHRoZSBnaXZlbiBtZXNzYWdlIHRvIHRoZSBiYWNrZW5kXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcbiAqL1xuXG4oZnVuY3Rpb24gKCkge1xuXHR3aW5kb3cuV2FpbHNJbnZva2UgPSAobWVzc2FnZSkgPT4ge1xuXHRcdFdJTkRPV1MgJiYgd2luZG93LmNocm9tZS53ZWJ2aWV3LnBvc3RNZXNzYWdlKG1lc3NhZ2UpO1xuXHRcdChEQVJXSU4gfHwgTElOVVgpICYmIHdpbmRvdy53ZWJraXQubWVzc2FnZUhhbmRsZXJzLndhaWxzLnBvc3RNZXNzYWdlKG1lc3NhZ2UpO1xuXHR9XG59KSgpOyIsICIvKlxuIF8gICAgICAgX18gICAgICBfIF9fXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cbi8qIGpzaGludCBlc3ZlcnNpb246IDYgKi9cblxuZXhwb3J0IGNvbnN0IGNhbGxiYWNrcyA9IHt9O1xuXG4vKipcbiAqIFJldHVybnMgYSBudW1iZXIgZnJvbSB0aGUgbmF0aXZlIGJyb3dzZXIgcmFuZG9tIGZ1bmN0aW9uXG4gKlxuICogQHJldHVybnMgbnVtYmVyXG4gKi9cbmZ1bmN0aW9uIGNyeXB0b1JhbmRvbSgpIHtcblx0dmFyIGFycmF5ID0gbmV3IFVpbnQzMkFycmF5KDEpO1xuXHRyZXR1cm4gd2luZG93LmNyeXB0by5nZXRSYW5kb21WYWx1ZXMoYXJyYXkpWzBdO1xufVxuXG4vKipcbiAqIFJldHVybnMgYSBudW1iZXIgdXNpbmcgZGEgb2xkLXNrb29sIE1hdGguUmFuZG9tXG4gKiBJIGxpa2VzIHRvIGNhbGwgaXQgTE9MUmFuZG9tXG4gKlxuICogQHJldHVybnMgbnVtYmVyXG4gKi9cbmZ1bmN0aW9uIGJhc2ljUmFuZG9tKCkge1xuXHRyZXR1cm4gTWF0aC5yYW5kb20oKSAqIDkwMDcxOTkyNTQ3NDA5OTE7XG59XG5cbi8vIFBpY2sgYSByYW5kb20gbnVtYmVyIGZ1bmN0aW9uIGJhc2VkIG9uIGJyb3dzZXIgY2FwYWJpbGl0eVxudmFyIHJhbmRvbUZ1bmM7XG5pZiAod2luZG93LmNyeXB0bykge1xuXHRyYW5kb21GdW5jID0gY3J5cHRvUmFuZG9tO1xufSBlbHNlIHtcblx0cmFuZG9tRnVuYyA9IGJhc2ljUmFuZG9tO1xufVxuXG5cbi8qKlxuICogQ2FsbCBzZW5kcyBhIG1lc3NhZ2UgdG8gdGhlIGJhY2tlbmQgdG8gY2FsbCB0aGUgYmluZGluZyB3aXRoIHRoZVxuICogZ2l2ZW4gZGF0YS4gQSBwcm9taXNlIGlzIHJldHVybmVkIGFuZCB3aWxsIGJlIGNvbXBsZXRlZCB3aGVuIHRoZVxuICogYmFja2VuZCByZXNwb25kcy4gVGhpcyB3aWxsIGJlIHJlc29sdmVkIHdoZW4gdGhlIGNhbGwgd2FzIHN1Y2Nlc3NmdWxcbiAqIG9yIHJlamVjdGVkIGlmIGFuIGVycm9yIGlzIHBhc3NlZCBiYWNrLlxuICogVGhlcmUgaXMgYSB0aW1lb3V0IG1lY2hhbmlzbS4gSWYgdGhlIGNhbGwgZG9lc24ndCByZXNwb25kIGluIHRoZSBnaXZlblxuICogdGltZSAoaW4gbWlsbGlzZWNvbmRzKSB0aGVuIHRoZSBwcm9taXNlIGlzIHJlamVjdGVkLlxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gKiBAcGFyYW0ge2FueT19IGFyZ3NcbiAqIEBwYXJhbSB7bnVtYmVyPX0gdGltZW91dFxuICogQHJldHVybnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENhbGwobmFtZSwgYXJncywgdGltZW91dCkge1xuXG5cdC8vIFRpbWVvdXQgaW5maW5pdGUgYnkgZGVmYXVsdFxuXHRpZiAodGltZW91dCA9PSBudWxsKSB7XG5cdFx0dGltZW91dCA9IDA7XG5cdH1cblxuXHRsZXQgd2luZG93SUQgPSB3aW5kb3cud2FpbHMud2luZG93LklEKCk7XG5cblx0Ly8gQ3JlYXRlIGEgcHJvbWlzZVxuXHRyZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuXG5cdFx0Ly8gQ3JlYXRlIGEgdW5pcXVlIGNhbGxiYWNrSURcblx0XHR2YXIgY2FsbGJhY2tJRDtcblx0XHRkbyB7XG5cdFx0XHRjYWxsYmFja0lEID0gbmFtZSArICctJyArIHJhbmRvbUZ1bmMoKTtcblx0XHR9IHdoaWxlIChjYWxsYmFja3NbY2FsbGJhY2tJRF0pO1xuXG5cdFx0dmFyIHRpbWVvdXRIYW5kbGU7XG5cdFx0Ly8gU2V0IHRpbWVvdXRcblx0XHRpZiAodGltZW91dCA+IDApIHtcblx0XHRcdHRpbWVvdXRIYW5kbGUgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0cmVqZWN0KEVycm9yKCdDYWxsIHRvICcgKyBuYW1lICsgJyB0aW1lZCBvdXQuIFJlcXVlc3QgSUQ6ICcgKyBjYWxsYmFja0lEKSk7XG5cdFx0XHR9LCB0aW1lb3V0KTtcblx0XHR9XG5cblx0XHQvLyBTdG9yZSBjYWxsYmFja1xuXHRcdGNhbGxiYWNrc1tjYWxsYmFja0lEXSA9IHtcblx0XHRcdHRpbWVvdXRIYW5kbGU6IHRpbWVvdXRIYW5kbGUsXG5cdFx0XHRyZWplY3Q6IHJlamVjdCxcblx0XHRcdHJlc29sdmU6IHJlc29sdmVcblx0XHR9O1xuXG5cdFx0dHJ5IHtcblx0XHRcdGNvbnN0IHBheWxvYWQgPSB7XG5cdFx0XHRcdG5hbWUsXG5cdFx0XHRcdGFyZ3MsXG5cdFx0XHRcdGNhbGxiYWNrSUQsXG5cdFx0XHRcdHdpbmRvd0lELFxuXHRcdFx0fTtcblxuICAgICAgICAgICAgLy8gTWFrZSB0aGUgY2FsbFxuICAgICAgICAgICAgd2luZG93LldhaWxzSW52b2tlKCdDJyArIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbndpbmRvdy5PYmZ1c2NhdGVkQ2FsbCA9IChpZCwgYXJncywgdGltZW91dCkgPT4ge1xuXG4gICAgLy8gVGltZW91dCBpbmZpbml0ZSBieSBkZWZhdWx0XG4gICAgaWYgKHRpbWVvdXQgPT0gbnVsbCkge1xuICAgICAgICB0aW1lb3V0ID0gMDtcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgYSBwcm9taXNlXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcblxuICAgICAgICAvLyBDcmVhdGUgYSB1bmlxdWUgY2FsbGJhY2tJRFxuICAgICAgICB2YXIgY2FsbGJhY2tJRDtcbiAgICAgICAgZG8ge1xuICAgICAgICAgICAgY2FsbGJhY2tJRCA9IGlkICsgJy0nICsgcmFuZG9tRnVuYygpO1xuICAgICAgICB9IHdoaWxlIChjYWxsYmFja3NbY2FsbGJhY2tJRF0pO1xuXG4gICAgICAgIHZhciB0aW1lb3V0SGFuZGxlO1xuICAgICAgICAvLyBTZXQgdGltZW91dFxuICAgICAgICBpZiAodGltZW91dCA+IDApIHtcbiAgICAgICAgICAgIHRpbWVvdXRIYW5kbGUgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ0NhbGwgdG8gbWV0aG9kICcgKyBpZCArICcgdGltZWQgb3V0LiBSZXF1ZXN0IElEOiAnICsgY2FsbGJhY2tJRCkpO1xuICAgICAgICAgICAgfSwgdGltZW91dCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTdG9yZSBjYWxsYmFja1xuICAgICAgICBjYWxsYmFja3NbY2FsbGJhY2tJRF0gPSB7XG4gICAgICAgICAgICB0aW1lb3V0SGFuZGxlOiB0aW1lb3V0SGFuZGxlLFxuICAgICAgICAgICAgcmVqZWN0OiByZWplY3QsXG4gICAgICAgICAgICByZXNvbHZlOiByZXNvbHZlXG4gICAgICAgIH07XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSB7XG5cdFx0XHRcdGlkLFxuXHRcdFx0XHRhcmdzLFxuXHRcdFx0XHRjYWxsYmFja0lELFxuXHRcdFx0XHR3aW5kb3dJRDogd2luZG93LndhaWxzLndpbmRvdy5JRCgpLFxuXHRcdFx0fTtcblxuICAgICAgICAgICAgLy8gTWFrZSB0aGUgY2FsbFxuICAgICAgICAgICAgd2luZG93LldhaWxzSW52b2tlKCdjJyArIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfSk7XG59O1xuXG5cbi8qKlxuICogQ2FsbGVkIGJ5IHRoZSBiYWNrZW5kIHRvIHJldHVybiBkYXRhIHRvIGEgcHJldmlvdXNseSBjYWxsZWRcbiAqIGJpbmRpbmcgaW52b2NhdGlvblxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBpbmNvbWluZ01lc3NhZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENhbGxiYWNrKGluY29taW5nTWVzc2FnZSkge1xuXHQvLyBQYXJzZSB0aGUgbWVzc2FnZVxuXHRsZXQgbWVzc2FnZTtcblx0dHJ5IHtcblx0XHRtZXNzYWdlID0gSlNPTi5wYXJzZShpbmNvbWluZ01lc3NhZ2UpO1xuXHR9IGNhdGNoIChlKSB7XG5cdFx0Y29uc3QgZXJyb3IgPSBgSW52YWxpZCBKU09OIHBhc3NlZCB0byBjYWxsYmFjazogJHtlLm1lc3NhZ2V9LiBNZXNzYWdlOiAke2luY29taW5nTWVzc2FnZX1gO1xuXHRcdHJ1bnRpbWUuTG9nRGVidWcoZXJyb3IpO1xuXHRcdHRocm93IG5ldyBFcnJvcihlcnJvcik7XG5cdH1cblx0bGV0IGNhbGxiYWNrSUQgPSBtZXNzYWdlLmNhbGxiYWNraWQ7XG5cdGxldCBjYWxsYmFja0RhdGEgPSBjYWxsYmFja3NbY2FsbGJhY2tJRF07XG5cdGlmICghY2FsbGJhY2tEYXRhKSB7XG5cdFx0Y29uc3QgZXJyb3IgPSBgQ2FsbGJhY2sgJyR7Y2FsbGJhY2tJRH0nIG5vdCByZWdpc3RlcmVkISEhYDtcblx0XHRjb25zb2xlLmVycm9yKGVycm9yKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHRcdHRocm93IG5ldyBFcnJvcihlcnJvcik7XG5cdH1cblx0Y2xlYXJUaW1lb3V0KGNhbGxiYWNrRGF0YS50aW1lb3V0SGFuZGxlKTtcblxuXHRkZWxldGUgY2FsbGJhY2tzW2NhbGxiYWNrSURdO1xuXG5cdGlmIChtZXNzYWdlLmVycm9yKSB7XG5cdFx0Y2FsbGJhY2tEYXRhLnJlamVjdChtZXNzYWdlLmVycm9yKTtcblx0fSBlbHNlIHtcblx0XHRjYWxsYmFja0RhdGEucmVzb2x2ZShtZXNzYWdlLnJlc3VsdCk7XG5cdH1cbn1cbiIsICIvKlxuIF8gICAgICAgX18gICAgICBfIF9fXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cbi8qIGpzaGludCBlc3ZlcnNpb246IDYgKi9cblxuLy8gRGVmaW5lcyBhIHNpbmdsZSBsaXN0ZW5lciB3aXRoIGEgbWF4aW11bSBudW1iZXIgb2YgdGltZXMgdG8gY2FsbGJhY2tcblxuLyoqXG4gKiBUaGUgTGlzdGVuZXIgY2xhc3MgZGVmaW5lcyBhIGxpc3RlbmVyISA6LSlcbiAqXG4gKiBAY2xhc3MgTGlzdGVuZXJcbiAqL1xuY2xhc3MgTGlzdGVuZXIge1xuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgTGlzdGVuZXIuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG1heENhbGxiYWNrc1xuICAgICAqIEBtZW1iZXJvZiBMaXN0ZW5lclxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG1heENhbGxiYWNrcykge1xuICAgICAgICB0aGlzLmV2ZW50TmFtZSA9IGV2ZW50TmFtZTtcbiAgICAgICAgLy8gRGVmYXVsdCBvZiAtMSBtZWFucyBpbmZpbml0ZVxuICAgICAgICB0aGlzLm1heENhbGxiYWNrcyA9IG1heENhbGxiYWNrcyB8fCAtMTtcbiAgICAgICAgLy8gQ2FsbGJhY2sgaW52b2tlcyB0aGUgY2FsbGJhY2sgd2l0aCB0aGUgZ2l2ZW4gZGF0YVxuICAgICAgICAvLyBSZXR1cm5zIHRydWUgaWYgdGhpcyBsaXN0ZW5lciBzaG91bGQgYmUgZGVzdHJveWVkXG4gICAgICAgIHRoaXMuQ2FsbGJhY2sgPSAoZGF0YSkgPT4ge1xuICAgICAgICAgICAgY2FsbGJhY2suYXBwbHkobnVsbCwgZGF0YSk7XG4gICAgICAgICAgICAvLyBJZiBtYXhDYWxsYmFja3MgaXMgaW5maW5pdGUsIHJldHVybiBmYWxzZSAoZG8gbm90IGRlc3Ryb3kpXG4gICAgICAgICAgICBpZiAodGhpcy5tYXhDYWxsYmFja3MgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRGVjcmVtZW50IG1heENhbGxiYWNrcy4gUmV0dXJuIHRydWUgaWYgbm93IDAsIG90aGVyd2lzZSBmYWxzZVxuICAgICAgICAgICAgdGhpcy5tYXhDYWxsYmFja3MgLT0gMTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1heENhbGxiYWNrcyA9PT0gMDtcbiAgICAgICAgfTtcbiAgICB9XG59XG5cbmV4cG9ydCBjb25zdCBldmVudExpc3RlbmVycyA9IHt9O1xuXG4vKipcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBgbWF4Q2FsbGJhY2tzYCB0aW1lcyBiZWZvcmUgYmVpbmcgZGVzdHJveWVkXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhDYWxsYmFja3NcbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gQSBmdW5jdGlvbiB0byBjYW5jZWwgdGhlIGxpc3RlbmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG1heENhbGxiYWNrcykge1xuICAgIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0gPSBldmVudExpc3RlbmVyc1tldmVudE5hbWVdIHx8IFtdO1xuICAgIGNvbnN0IHRoaXNMaXN0ZW5lciA9IG5ldyBMaXN0ZW5lcihldmVudE5hbWUsIGNhbGxiYWNrLCBtYXhDYWxsYmFja3MpO1xuICAgIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0ucHVzaCh0aGlzTGlzdGVuZXIpO1xuICAgIHJldHVybiAoKSA9PiBsaXN0ZW5lck9mZih0aGlzTGlzdGVuZXIpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBldmVyeSB0aW1lIHRoZSBldmVudCBpcyBlbWl0dGVkXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gQSBmdW5jdGlvbiB0byBjYW5jZWwgdGhlIGxpc3RlbmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbihldmVudE5hbWUsIGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIEV2ZW50c09uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgLTEpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBvbmNlIHRoZW4gZGVzdHJveWVkXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gQSBmdW5jdGlvbiB0byBjYW5jZWwgdGhlIGxpc3RlbmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbmNlKGV2ZW50TmFtZSwgY2FsbGJhY2spIHtcbiAgICByZXR1cm4gRXZlbnRzT25NdWx0aXBsZShldmVudE5hbWUsIGNhbGxiYWNrLCAxKTtcbn1cblxuZnVuY3Rpb24gbm90aWZ5TGlzdGVuZXJzKGV2ZW50RGF0YSkge1xuXG4gICAgLy8gR2V0IHRoZSBldmVudCBuYW1lXG4gICAgbGV0IGV2ZW50TmFtZSA9IGV2ZW50RGF0YS5uYW1lO1xuXG4gICAgLy8gQ2hlY2sgaWYgd2UgaGF2ZSBhbnkgbGlzdGVuZXJzIGZvciB0aGlzIGV2ZW50XG4gICAgaWYgKGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0pIHtcblxuICAgICAgICAvLyBLZWVwIGEgbGlzdCBvZiBsaXN0ZW5lciBpbmRleGVzIHRvIGRlc3Ryb3lcbiAgICAgICAgY29uc3QgbmV3RXZlbnRMaXN0ZW5lckxpc3QgPSBldmVudExpc3RlbmVyc1tldmVudE5hbWVdLnNsaWNlKCk7XG5cbiAgICAgICAgLy8gSXRlcmF0ZSBsaXN0ZW5lcnNcbiAgICAgICAgZm9yIChsZXQgY291bnQgPSAwOyBjb3VudCA8IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0ubGVuZ3RoOyBjb3VudCArPSAxKSB7XG5cbiAgICAgICAgICAgIC8vIEdldCBuZXh0IGxpc3RlbmVyXG4gICAgICAgICAgICBjb25zdCBsaXN0ZW5lciA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV1bY291bnRdO1xuXG4gICAgICAgICAgICBsZXQgZGF0YSA9IGV2ZW50RGF0YS5kYXRhO1xuXG4gICAgICAgICAgICAvLyBEbyB0aGUgY2FsbGJhY2tcbiAgICAgICAgICAgIGNvbnN0IGRlc3Ryb3kgPSBsaXN0ZW5lci5DYWxsYmFjayhkYXRhKTtcbiAgICAgICAgICAgIGlmIChkZXN0cm95KSB7XG4gICAgICAgICAgICAgICAgLy8gaWYgdGhlIGxpc3RlbmVyIGluZGljYXRlZCB0byBkZXN0cm95IGl0c2VsZiwgYWRkIGl0IHRvIHRoZSBkZXN0cm95IGxpc3RcbiAgICAgICAgICAgICAgICBuZXdFdmVudExpc3RlbmVyTGlzdC5zcGxpY2UoY291bnQsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gVXBkYXRlIGNhbGxiYWNrcyB3aXRoIG5ldyBsaXN0IG9mIGxpc3RlbmVyc1xuICAgICAgICBpZiAobmV3RXZlbnRMaXN0ZW5lckxpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZW1vdmVMaXN0ZW5lcihldmVudE5hbWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSA9IG5ld0V2ZW50TGlzdGVuZXJMaXN0O1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqIE5vdGlmeSBpbmZvcm1zIGZyb250ZW5kIGxpc3RlbmVycyB0aGF0IGFuIGV2ZW50IHdhcyBlbWl0dGVkIHdpdGggdGhlIGdpdmVuIGRhdGFcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbm90aWZ5TWVzc2FnZSAtIGVuY29kZWQgbm90aWZpY2F0aW9uIG1lc3NhZ2VcblxuICovXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzTm90aWZ5KG5vdGlmeU1lc3NhZ2UpIHtcbiAgICAvLyBQYXJzZSB0aGUgbWVzc2FnZVxuICAgIGxldCBtZXNzYWdlO1xuICAgIHRyeSB7XG4gICAgICAgIG1lc3NhZ2UgPSBKU09OLnBhcnNlKG5vdGlmeU1lc3NhZ2UpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc3QgZXJyb3IgPSAnSW52YWxpZCBKU09OIHBhc3NlZCB0byBOb3RpZnk6ICcgKyBub3RpZnlNZXNzYWdlO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3IpO1xuICAgIH1cbiAgICBub3RpZnlMaXN0ZW5lcnMobWVzc2FnZSk7XG59XG5cbi8qKlxuICogRW1pdCBhbiBldmVudCB3aXRoIHRoZSBnaXZlbiBuYW1lIGFuZCBkYXRhXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICovXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzRW1pdChldmVudE5hbWUpIHtcblxuICAgIGNvbnN0IHBheWxvYWQgPSB7XG4gICAgICAgIG5hbWU6IGV2ZW50TmFtZSxcbiAgICAgICAgZGF0YTogW10uc2xpY2UuYXBwbHkoYXJndW1lbnRzKS5zbGljZSgxKSxcbiAgICB9O1xuXG4gICAgLy8gTm90aWZ5IEpTIGxpc3RlbmVyc1xuICAgIG5vdGlmeUxpc3RlbmVycyhwYXlsb2FkKTtcblxuICAgIC8vIE5vdGlmeSBHbyBsaXN0ZW5lcnNcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ0VFJyArIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcbn1cblxuZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIoZXZlbnROYW1lKSB7XG4gICAgLy8gUmVtb3ZlIGxvY2FsIGxpc3RlbmVyc1xuICAgIGRlbGV0ZSBldmVudExpc3RlbmVyc1tldmVudE5hbWVdO1xuXG4gICAgLy8gTm90aWZ5IEdvIGxpc3RlbmVyc1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnRVgnICsgZXZlbnROYW1lKTtcbn1cblxuLyoqXG4gKiBPZmYgdW5yZWdpc3RlcnMgYSBsaXN0ZW5lciBwcmV2aW91c2x5IHJlZ2lzdGVyZWQgd2l0aCBPbixcbiAqIG9wdGlvbmFsbHkgbXVsdGlwbGUgbGlzdGVuZXJlcyBjYW4gYmUgdW5yZWdpc3RlcmVkIHZpYSBgYWRkaXRpb25hbEV2ZW50TmFtZXNgXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtICB7Li4uc3RyaW5nfSBhZGRpdGlvbmFsRXZlbnROYW1lc1xuICovXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzT2ZmKGV2ZW50TmFtZSwgLi4uYWRkaXRpb25hbEV2ZW50TmFtZXMpIHtcbiAgICByZW1vdmVMaXN0ZW5lcihldmVudE5hbWUpXG5cbiAgICBpZiAoYWRkaXRpb25hbEV2ZW50TmFtZXMubGVuZ3RoID4gMCkge1xuICAgICAgICBhZGRpdGlvbmFsRXZlbnROYW1lcy5mb3JFYWNoKGV2ZW50TmFtZSA9PiB7XG4gICAgICAgICAgICByZW1vdmVMaXN0ZW5lcihldmVudE5hbWUpXG4gICAgICAgIH0pXG4gICAgfVxufVxuXG4vKipcbiAqIE9mZiB1bnJlZ2lzdGVycyBhbGwgZXZlbnQgbGlzdGVuZXJzIHByZXZpb3VzbHkgcmVnaXN0ZXJlZCB3aXRoIE9uXG4gKi9cbiBleHBvcnQgZnVuY3Rpb24gRXZlbnRzT2ZmQWxsKCkge1xuICAgIGNvbnN0IGV2ZW50TmFtZXMgPSBPYmplY3Qua2V5cyhldmVudExpc3RlbmVycyk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgIT09IGV2ZW50TmFtZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcmVtb3ZlTGlzdGVuZXIoZXZlbnROYW1lc1tpXSk7XG4gICAgfVxufVxuXG4vKipcbiAqIGxpc3RlbmVyT2ZmIHVucmVnaXN0ZXJzIGEgbGlzdGVuZXIgcHJldmlvdXNseSByZWdpc3RlcmVkIHdpdGggRXZlbnRzT25cbiAqXG4gKiBAcGFyYW0ge0xpc3RlbmVyfSBsaXN0ZW5lclxuICovXG4gZnVuY3Rpb24gbGlzdGVuZXJPZmYobGlzdGVuZXIpIHtcbiAgICBjb25zdCBldmVudE5hbWUgPSBsaXN0ZW5lci5ldmVudE5hbWU7XG4gICAgLy8gUmVtb3ZlIGxvY2FsIGxpc3RlbmVyXG4gICAgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0uZmlsdGVyKGwgPT4gbCAhPT0gbGlzdGVuZXIpO1xuXG4gICAgLy8gQ2xlYW4gdXAgaWYgdGhlcmUgYXJlIG5vIGV2ZW50IGxpc3RlbmVycyBsZWZ0XG4gICAgaWYgKGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0ubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJlbW92ZUxpc3RlbmVyKGV2ZW50TmFtZSk7XG4gICAgfVxufVxuIiwgIi8qXG4gXyAgICAgICBfXyAgICAgIF8gX18gICAgXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gICkgXG58X18vfF9fL1xcX18sXy9fL18vX19fXy8gIFxuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cbi8qIGpzaGludCBlc3ZlcnNpb246IDYgKi9cblxuaW1wb3J0IHtDYWxsfSBmcm9tICcuL2NhbGxzJztcblxuLy8gVGhpcyBpcyB3aGVyZSB3ZSBiaW5kIGdvIG1ldGhvZCB3cmFwcGVyc1xud2luZG93LmdvID0ge307XG5cbmV4cG9ydCBmdW5jdGlvbiBTZXRCaW5kaW5ncyhiaW5kaW5nc01hcCkge1xuXHR0cnkge1xuXHRcdGJpbmRpbmdzTWFwID0gSlNPTi5wYXJzZShiaW5kaW5nc01hcCk7XG5cdH0gY2F0Y2ggKGUpIHtcblx0XHRjb25zb2xlLmVycm9yKGUpO1xuXHR9XG5cblx0Ly8gSW5pdGlhbGlzZSB0aGUgYmluZGluZ3MgbWFwXG5cdHdpbmRvdy5nbyA9IHdpbmRvdy5nbyB8fCB7fTtcblxuXHQvLyBJdGVyYXRlIHBhY2thZ2UgbmFtZXNcblx0T2JqZWN0LmtleXMoYmluZGluZ3NNYXApLmZvckVhY2goKHBhY2thZ2VOYW1lKSA9PiB7XG5cblx0XHQvLyBDcmVhdGUgaW5uZXIgbWFwIGlmIGl0IGRvZXNuJ3QgZXhpc3Rcblx0XHR3aW5kb3cuZ29bcGFja2FnZU5hbWVdID0gd2luZG93LmdvW3BhY2thZ2VOYW1lXSB8fCB7fTtcblxuXHRcdC8vIEl0ZXJhdGUgc3RydWN0IG5hbWVzXG5cdFx0T2JqZWN0LmtleXMoYmluZGluZ3NNYXBbcGFja2FnZU5hbWVdKS5mb3JFYWNoKChzdHJ1Y3ROYW1lKSA9PiB7XG5cblx0XHRcdC8vIENyZWF0ZSBpbm5lciBtYXAgaWYgaXQgZG9lc24ndCBleGlzdFxuXHRcdFx0d2luZG93LmdvW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXSA9IHdpbmRvdy5nb1twYWNrYWdlTmFtZV1bc3RydWN0TmFtZV0gfHwge307XG5cblx0XHRcdE9iamVjdC5rZXlzKGJpbmRpbmdzTWFwW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXSkuZm9yRWFjaCgobWV0aG9kTmFtZSkgPT4ge1xuXG5cdFx0XHRcdHdpbmRvdy5nb1twYWNrYWdlTmFtZV1bc3RydWN0TmFtZV1bbWV0aG9kTmFtZV0gPSBmdW5jdGlvbiAoKSB7XG5cblx0XHRcdFx0XHQvLyBObyB0aW1lb3V0IGJ5IGRlZmF1bHRcblx0XHRcdFx0XHRsZXQgdGltZW91dCA9IDA7XG5cblx0XHRcdFx0XHQvLyBBY3R1YWwgZnVuY3Rpb25cblx0XHRcdFx0XHRmdW5jdGlvbiBkeW5hbWljKCkge1xuXHRcdFx0XHRcdFx0Y29uc3QgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcblx0XHRcdFx0XHRcdHJldHVybiBDYWxsKFtwYWNrYWdlTmFtZSwgc3RydWN0TmFtZSwgbWV0aG9kTmFtZV0uam9pbignLicpLCBhcmdzLCB0aW1lb3V0KTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBBbGxvdyBzZXR0aW5nIHRpbWVvdXQgdG8gZnVuY3Rpb25cblx0XHRcdFx0XHRkeW5hbWljLnNldFRpbWVvdXQgPSBmdW5jdGlvbiAobmV3VGltZW91dCkge1xuXHRcdFx0XHRcdFx0dGltZW91dCA9IG5ld1RpbWVvdXQ7XG5cdFx0XHRcdFx0fTtcblxuXHRcdFx0XHRcdC8vIEFsbG93IGdldHRpbmcgdGltZW91dCB0byBmdW5jdGlvblxuXHRcdFx0XHRcdGR5bmFtaWMuZ2V0VGltZW91dCA9IGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRcdHJldHVybiB0aW1lb3V0O1xuXHRcdFx0XHRcdH07XG5cblx0XHRcdFx0XHRyZXR1cm4gZHluYW1pYztcblx0XHRcdFx0fSgpO1xuXHRcdFx0fSk7XG5cdFx0fSk7XG5cdH0pO1xufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cblxuaW1wb3J0IHtDYWxsfSBmcm9tIFwiLi9jYWxsc1wiO1xuXG5leHBvcnQgZnVuY3Rpb24gV2luZG93UmVsb2FkKCkge1xuICAgIHdpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1JlbG9hZEFwcCgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dSJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRTeXN0ZW1EZWZhdWx0VGhlbWUoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXQVNEVCcpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0TGlnaHRUaGVtZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dBTFQnKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldERhcmtUaGVtZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dBRFQnKTtcbn1cblxuLyoqXG4gKiBQbGFjZSB0aGUgd2luZG93IGluIHRoZSBjZW50ZXIgb2YgdGhlIHNjcmVlblxuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0NlbnRlcigpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1djJyk7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgd2luZG93IHRpdGxlXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHRpdGxlXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRUaXRsZSh0aXRsZSkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV1QnICsgdGl0bGUpO1xufVxuXG4vKipcbiAqIE1ha2VzIHRoZSB3aW5kb3cgZ28gZnVsbHNjcmVlblxuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0Z1bGxzY3JlZW4oKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXRicpO1xufVxuXG4vKipcbiAqIFJldmVydHMgdGhlIHdpbmRvdyBmcm9tIGZ1bGxzY3JlZW5cbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dVbmZ1bGxzY3JlZW4oKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXZicpO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIHN0YXRlIG9mIHRoZSB3aW5kb3csIGkuZS4gd2hldGhlciB0aGUgd2luZG93IGlzIGluIGZ1bGwgc2NyZWVuIG1vZGUgb3Igbm90LlxuICpcbiAqIEBleHBvcnRcbiAqIEByZXR1cm4ge1Byb21pc2U8Ym9vbGVhbj59IFRoZSBzdGF0ZSBvZiB0aGUgd2luZG93XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dJc0Z1bGxzY3JlZW4oKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6V2luZG93SXNGdWxsc2NyZWVuXCIpO1xufVxuXG4vKipcbiAqIFNldCB0aGUgU2l6ZSBvZiB0aGUgd2luZG93XG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRTaXplKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dzOicgKyB3aWR0aCArICc6JyArIGhlaWdodCk7XG59XG5cbi8qKlxuICogR2V0IHRoZSBTaXplIG9mIHRoZSB3aW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcmV0dXJuIHtQcm9taXNlPHt3OiBudW1iZXIsIGg6IG51bWJlcn0+fSBUaGUgc2l6ZSBvZiB0aGUgd2luZG93XG5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0dldFNpemUoKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6V2luZG93R2V0U2l6ZVwiKTtcbn1cblxuLyoqXG4gKiBTZXQgdGhlIG1heGltdW0gc2l6ZSBvZiB0aGUgd2luZG93XG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRNYXhTaXplKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1daOicgKyB3aWR0aCArICc6JyArIGhlaWdodCk7XG59XG5cbi8qKlxuICogU2V0IHRoZSBtaW5pbXVtIHNpemUgb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aFxuICogQHBhcmFtIHtudW1iZXJ9IGhlaWdodFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0TWluU2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXejonICsgd2lkdGggKyAnOicgKyBoZWlnaHQpO1xufVxuXG5cblxuLyoqXG4gKiBTZXQgdGhlIHdpbmRvdyBBbHdheXNPblRvcCBvciBub3Qgb24gdG9wXG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0QWx3YXlzT25Ub3AoYikge1xuXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXQVRQOicgKyAoYiA/ICcxJyA6ICcwJykpO1xufVxuXG5cblxuXG4vKipcbiAqIFNldCB0aGUgUG9zaXRpb24gb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7bnVtYmVyfSB4XG4gKiBAcGFyYW0ge251bWJlcn0geVxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0UG9zaXRpb24oeCwgeSkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3A6JyArIHggKyAnOicgKyB5KTtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIFBvc2l0aW9uIG9mIHRoZSB3aW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcmV0dXJuIHtQcm9taXNlPHt4OiBudW1iZXIsIHk6IG51bWJlcn0+fSBUaGUgcG9zaXRpb24gb2YgdGhlIHdpbmRvd1xuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93R2V0UG9zaXRpb24oKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6V2luZG93R2V0UG9zXCIpO1xufVxuXG4vKipcbiAqIEhpZGUgdGhlIFdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0hpZGUoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXSCcpO1xufVxuXG4vKipcbiAqIFNob3cgdGhlIFdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1Nob3coKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXUycpO1xufVxuXG4vKipcbiAqIE1heGltaXNlIHRoZSBXaW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dNYXhpbWlzZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dNJyk7XG59XG5cbi8qKlxuICogVG9nZ2xlIHRoZSBNYXhpbWlzZSBvZiB0aGUgV2luZG93XG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93VG9nZ2xlTWF4aW1pc2UoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXdCcpO1xufVxuXG4vKipcbiAqIFVubWF4aW1pc2UgdGhlIFdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1VubWF4aW1pc2UoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXVScpO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIHN0YXRlIG9mIHRoZSB3aW5kb3csIGkuZS4gd2hldGhlciB0aGUgd2luZG93IGlzIG1heGltaXNlZCBvciBub3QuXG4gKlxuICogQGV4cG9ydFxuICogQHJldHVybiB7UHJvbWlzZTxib29sZWFuPn0gVGhlIHN0YXRlIG9mIHRoZSB3aW5kb3dcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0lzTWF4aW1pc2VkKCkge1xuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOldpbmRvd0lzTWF4aW1pc2VkXCIpO1xufVxuXG4vKipcbiAqIE1pbmltaXNlIHRoZSBXaW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dNaW5pbWlzZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dtJyk7XG59XG5cbi8qKlxuICogVW5taW5pbWlzZSB0aGUgV2luZG93XG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93VW5taW5pbWlzZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1d1Jyk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgc3RhdGUgb2YgdGhlIHdpbmRvdywgaS5lLiB3aGV0aGVyIHRoZSB3aW5kb3cgaXMgbWluaW1pc2VkIG9yIG5vdC5cbiAqXG4gKiBAZXhwb3J0XG4gKiBAcmV0dXJuIHtQcm9taXNlPGJvb2xlYW4+fSBUaGUgc3RhdGUgb2YgdGhlIHdpbmRvd1xuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93SXNNaW5pbWlzZWQoKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6V2luZG93SXNNaW5pbWlzZWRcIik7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgc3RhdGUgb2YgdGhlIHdpbmRvdywgaS5lLiB3aGV0aGVyIHRoZSB3aW5kb3cgaXMgbm9ybWFsIG9yIG5vdC5cbiAqXG4gKiBAZXhwb3J0XG4gKiBAcmV0dXJuIHtQcm9taXNlPGJvb2xlYW4+fSBUaGUgc3RhdGUgb2YgdGhlIHdpbmRvd1xuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93SXNOb3JtYWwoKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6V2luZG93SXNOb3JtYWxcIik7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgYmFja2dyb3VuZCBjb2xvdXIgb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7bnVtYmVyfSBSIFJlZFxuICogQHBhcmFtIHtudW1iZXJ9IEcgR3JlZW5cbiAqIEBwYXJhbSB7bnVtYmVyfSBCIEJsdWVcbiAqIEBwYXJhbSB7bnVtYmVyfSBBIEFscGhhXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRCYWNrZ3JvdW5kQ29sb3VyKFIsIEcsIEIsIEEpIHtcbiAgICBsZXQgcmdiYSA9IEpTT04uc3RyaW5naWZ5KHtyOiBSIHx8IDAsIGc6IEcgfHwgMCwgYjogQiB8fCAwLCBhOiBBIHx8IDI1NX0pO1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3I6JyArIHJnYmEpO1xufVxuXG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cblxuXG5pbXBvcnQge0NhbGx9IGZyb20gXCIuL2NhbGxzXCI7XG5cblxuLyoqXG4gKiBHZXRzIHRoZSBhbGwgc2NyZWVucy4gQ2FsbCB0aGlzIGFuZXcgZWFjaCB0aW1lIHlvdSB3YW50IHRvIHJlZnJlc2ggZGF0YSBmcm9tIHRoZSB1bmRlcmx5aW5nIHdpbmRvd2luZyBzeXN0ZW0uXG4gKiBAZXhwb3J0XG4gKiBAdHlwZWRlZiB7aW1wb3J0KCcuLi93cmFwcGVyL3J1bnRpbWUnKS5TY3JlZW59IFNjcmVlblxuICogQHJldHVybiB7UHJvbWlzZTx7U2NyZWVuW119Pn0gVGhlIHNjcmVlbnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNjcmVlbkdldEFsbCgpIHtcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpTY3JlZW5HZXRBbGxcIik7XG59XG4iLCAiLyoqXG4gKiBAZGVzY3JpcHRpb246IFVzZSB0aGUgc3lzdGVtIGRlZmF1bHQgYnJvd3NlciB0byBvcGVuIHRoZSB1cmxcbiAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gQnJvd3Nlck9wZW5VUkwodXJsKSB7XG4gIHdpbmRvdy5XYWlsc0ludm9rZSgnQk86JyArIHVybCk7XG59IiwgIi8qXG4gXyAgICAgICBfXyAgICAgIF8gX19cbnwgfCAgICAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA2ICovXG5cbi8qKlxuICogU2VuZHMgYSBsb2cgbWVzc2FnZSB0byB0aGUgYmFja2VuZCB3aXRoIHRoZSBnaXZlbiBsZXZlbCArIG1lc3NhZ2VcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbGV2ZWxcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmZ1bmN0aW9uIHNlbmRMb2dNZXNzYWdlKGxldmVsLCBtZXNzYWdlKSB7XG5cblx0Ly8gTG9nIE1lc3NhZ2UgZm9ybWF0OlxuXHQvLyBsW3R5cGVdW21lc3NhZ2VdXG5cdHdpbmRvdy5XYWlsc0ludm9rZSgnTCcgKyBsZXZlbCArIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIExvZyB0aGUgZ2l2ZW4gdHJhY2UgbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIExvZ1RyYWNlKG1lc3NhZ2UpIHtcblx0c2VuZExvZ01lc3NhZ2UoJ1QnLCBtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBMb2cgdGhlIGdpdmVuIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dQcmludChtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdQJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiBkZWJ1ZyBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nRGVidWcobWVzc2FnZSkge1xuXHRzZW5kTG9nTWVzc2FnZSgnRCcsIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIExvZyB0aGUgZ2l2ZW4gaW5mbyBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nSW5mbyhtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdJJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiB3YXJuaW5nIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dXYXJuaW5nKG1lc3NhZ2UpIHtcblx0c2VuZExvZ01lc3NhZ2UoJ1cnLCBtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBMb2cgdGhlIGdpdmVuIGVycm9yIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dFcnJvcihtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdFJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiBmYXRhbCBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nRmF0YWwobWVzc2FnZSkge1xuXHRzZW5kTG9nTWVzc2FnZSgnRicsIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIExvZyBsZXZlbCB0byB0aGUgZ2l2ZW4gbG9nIGxldmVsXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtudW1iZXJ9IGxvZ2xldmVsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRMb2dMZXZlbChsb2dsZXZlbCkge1xuXHRzZW5kTG9nTWVzc2FnZSgnUycsIGxvZ2xldmVsKTtcbn1cblxuLy8gTG9nIGxldmVsc1xuZXhwb3J0IGNvbnN0IExvZ0xldmVsID0ge1xuXHRUUkFDRTogMSxcblx0REVCVUc6IDIsXG5cdElORk86IDMsXG5cdFdBUk5JTkc6IDQsXG5cdEVSUk9SOiA1LFxufTtcbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cblxuaW1wb3J0IFwiLi9pcGMuanNcIjtcbmltcG9ydCB7Q2FsbGJhY2ssIGNhbGxiYWNrc30gZnJvbSAnLi9jYWxscyc7XG5pbXBvcnQge0V2ZW50c05vdGlmeSwgZXZlbnRMaXN0ZW5lcnN9IGZyb20gXCIuL2V2ZW50c1wiO1xuaW1wb3J0IHtTZXRCaW5kaW5nc30gZnJvbSBcIi4vYmluZGluZ3NcIjtcblxuaW1wb3J0ICogYXMgV2luZG93IGZyb20gXCIuL3dpbmRvd1wiO1xuaW1wb3J0ICogYXMgU2NyZWVuIGZyb20gXCIuL3NjcmVlblwiO1xuaW1wb3J0ICogYXMgQnJvd3NlciBmcm9tIFwiLi9icm93c2VyXCI7XG5pbXBvcnQgKiBhcyBMb2cgZnJvbSAnLi9sb2cnO1xuXG5sZXQgd2luZG93SUQgPSAtMTtcblxuXG5leHBvcnQgZnVuY3Rpb24gUXVpdCgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1EnKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIFNob3coKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdTJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBIaWRlKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnSCcpO1xufVxuXG4vLyBleHBvcnQgZnVuY3Rpb24gRW52aXJvbm1lbnQoKSB7XG4vLyAgICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6RW52aXJvbm1lbnRcIik7XG4vLyB9XG5cbi8vIEludGVybmFsIHdhaWxzIGVuZHBvaW50c1xud2luZG93LndhaWxzID0ge1xuICAgIENhbGxiYWNrLFxuICAgIGNhbGxiYWNrcyxcbiAgICBFdmVudHNOb3RpZnksXG4gICAgZXZlbnRMaXN0ZW5lcnMsXG4gICAgU2V0QmluZGluZ3MsXG4gICAgd2luZG93OiB7XG4gICAgICAgIElEOiAoKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gd2luZG93SURcbiAgICAgICAgfSxcbiAgICB9XG59O1xuXG53aW5kb3cucnVudGltZSA9IHtcbiAgICAuLi5Mb2csXG4gICAgLi4uV2luZG93LFxuICAgIC4uLkJyb3dzZXIsXG4gICAgLi4uU2NyZWVuLFxuICAgIEV2ZW50c09uLFxuICAgIEV2ZW50c09uY2UsXG4gICAgRXZlbnRzT25NdWx0aXBsZSxcbiAgICBFdmVudHNFbWl0LFxuICAgIEV2ZW50c09mZixcbiAgICAvLyBFbnZpcm9ubWVudCxcbiAgICBTaG93LFxuICAgIEhpZGUsXG4gICAgUXVpdCxcbn1cblxuLy8gUHJvY2VzcyB0aGUgZXhwZWN0ZWQgcnVudGltZSBjb25maWcgZnJvbSB0aGUgYmFja2VuZFxuaWYoIHdpbmRvdy53YWlsc19jb25maWcgKSB7XG4gICAgd2luZG93SUQgPSB3aW5kb3cud2FpbHNfY29uZmlnLndpbmRvd0lEO1xuICAgIHdpbmRvdy53YWlsc19jb25maWcgPSBudWxsO1xufVxuXG5pZiAoREVCVUcpIHtcbiAgICBjb25zb2xlLmxvZyhcIldhaWxzIHYzLjAuMCBEZWJ1ZyBNb2RlIEVuYWJsZWRcIik7XG59XG5cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7O0FBaUJBLEdBQUMsV0FBWTtBQUNaLFdBQU8sY0FBYyxDQUFDLFlBQVk7QUFFakMsTUFBcUIsT0FBTyxPQUFPLGdCQUFnQixNQUFNLFlBQVksT0FBTztBQUFBLElBQzdFO0FBQUEsRUFDRCxHQUFHOzs7QUNYSSxNQUFNLFlBQVksQ0FBQztBQU8xQixXQUFTLGVBQWU7QUFDdkIsUUFBSSxRQUFRLElBQUksWUFBWSxDQUFDO0FBQzdCLFdBQU8sT0FBTyxPQUFPLGdCQUFnQixLQUFLLEVBQUU7QUFBQSxFQUM3QztBQVFBLFdBQVMsY0FBYztBQUN0QixXQUFPLEtBQUssT0FBTyxJQUFJO0FBQUEsRUFDeEI7QUFHQSxNQUFJO0FBQ0osTUFBSSxPQUFPLFFBQVE7QUFDbEIsaUJBQWE7QUFBQSxFQUNkLE9BQU87QUFDTixpQkFBYTtBQUFBLEVBQ2Q7QUFpQk8sV0FBUyxLQUFLLE1BQU0sTUFBTSxTQUFTO0FBR3pDLFFBQUksV0FBVyxNQUFNO0FBQ3BCLGdCQUFVO0FBQUEsSUFDWDtBQUVBLFFBQUlBLFlBQVcsT0FBTyxNQUFNLE9BQU8sR0FBRztBQUd0QyxXQUFPLElBQUksUUFBUSxTQUFVLFNBQVMsUUFBUTtBQUc3QyxVQUFJO0FBQ0osU0FBRztBQUNGLHFCQUFhLE9BQU8sTUFBTSxXQUFXO0FBQUEsTUFDdEMsU0FBUyxVQUFVO0FBRW5CLFVBQUk7QUFFSixVQUFJLFVBQVUsR0FBRztBQUNoQix3QkFBZ0IsV0FBVyxXQUFZO0FBQ3RDLGlCQUFPLE1BQU0sYUFBYSxPQUFPLDZCQUE2QixVQUFVLENBQUM7QUFBQSxRQUMxRSxHQUFHLE9BQU87QUFBQSxNQUNYO0FBR0EsZ0JBQVUsY0FBYztBQUFBLFFBQ3ZCO0FBQUEsUUFDQTtBQUFBLFFBQ0E7QUFBQSxN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 diff --git a/exp/internal/runtime/runtime_debug_desktop_linux.js b/exp/internal/runtime/runtime_debug_desktop_linux.js new file mode 100644 index 000000000..d8fbf5def --- /dev/null +++ b/exp/internal/runtime/runtime_debug_desktop_linux.js @@ -0,0 +1,420 @@ +(() => { + var __defProp = Object.defineProperty; + var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); + }; + + // desktop/ipc.js + (function() { + window.WailsInvoke = (message) => { + window.webkit.messageHandlers.wails.postMessage(message); + }; + })(); + + // desktop/calls.js + var callbacks = {}; + function cryptoRandom() { + var array = new Uint32Array(1); + return window.crypto.getRandomValues(array)[0]; + } + function basicRandom() { + return Math.random() * 9007199254740991; + } + var randomFunc; + if (window.crypto) { + randomFunc = cryptoRandom; + } else { + randomFunc = basicRandom; + } + function Call(name, args, timeout) { + if (timeout == null) { + timeout = 0; + } + let windowID2 = window.wails.window.ID(); + return new Promise(function(resolve, reject) { + var callbackID; + do { + callbackID = name + "-" + randomFunc(); + } while (callbacks[callbackID]); + var timeoutHandle; + if (timeout > 0) { + timeoutHandle = setTimeout(function() { + reject(Error("Call to " + name + " timed out. Request ID: " + callbackID)); + }, timeout); + } + callbacks[callbackID] = { + timeoutHandle, + reject, + resolve + }; + try { + const payload = { + name, + args, + callbackID, + windowID: windowID2 + }; + window.WailsInvoke("C" + JSON.stringify(payload)); + } catch (e) { + console.error(e); + } + }); + } + window.ObfuscatedCall = (id, args, timeout) => { + if (timeout == null) { + timeout = 0; + } + return new Promise(function(resolve, reject) { + var callbackID; + do { + callbackID = id + "-" + randomFunc(); + } while (callbacks[callbackID]); + var timeoutHandle; + if (timeout > 0) { + timeoutHandle = setTimeout(function() { + reject(Error("Call to method " + id + " timed out. Request ID: " + callbackID)); + }, timeout); + } + callbacks[callbackID] = { + timeoutHandle, + reject, + resolve + }; + try { + const payload = { + id, + args, + callbackID, + windowID: window.wails.window.ID() + }; + window.WailsInvoke("c" + JSON.stringify(payload)); + } catch (e) { + console.error(e); + } + }); + }; + function Callback(incomingMessage) { + let message; + try { + message = JSON.parse(incomingMessage); + } catch (e) { + const error = `Invalid JSON passed to callback: ${e.message}. Message: ${incomingMessage}`; + runtime.LogDebug(error); + throw new Error(error); + } + let callbackID = message.callbackid; + let callbackData = callbacks[callbackID]; + if (!callbackData) { + const error = `Callback '${callbackID}' not registered!!!`; + console.error(error); + throw new Error(error); + } + clearTimeout(callbackData.timeoutHandle); + delete callbacks[callbackID]; + if (message.error) { + callbackData.reject(message.error); + } else { + callbackData.resolve(message.result); + } + } + + // desktop/events.js + var eventListeners = {}; + function notifyListeners(eventData) { + let eventName = eventData.name; + if (eventListeners[eventName]) { + const newEventListenerList = eventListeners[eventName].slice(); + for (let count = 0; count < eventListeners[eventName].length; count += 1) { + const listener = eventListeners[eventName][count]; + let data = eventData.data; + const destroy = listener.Callback(data); + if (destroy) { + newEventListenerList.splice(count, 1); + } + } + if (newEventListenerList.length === 0) { + removeListener(eventName); + } else { + eventListeners[eventName] = newEventListenerList; + } + } + } + function EventsNotify(notifyMessage) { + let message; + try { + message = JSON.parse(notifyMessage); + } catch (e) { + const error = "Invalid JSON passed to Notify: " + notifyMessage; + throw new Error(error); + } + notifyListeners(message); + } + function removeListener(eventName) { + delete eventListeners[eventName]; + window.WailsInvoke("EX" + eventName); + } + + // desktop/bindings.js + window.go = {}; + function SetBindings(bindingsMap) { + try { + bindingsMap = JSON.parse(bindingsMap); + } catch (e) { + console.error(e); + } + window.go = window.go || {}; + Object.keys(bindingsMap).forEach((packageName) => { + window.go[packageName] = window.go[packageName] || {}; + Object.keys(bindingsMap[packageName]).forEach((structName) => { + window.go[packageName][structName] = window.go[packageName][structName] || {}; + Object.keys(bindingsMap[packageName][structName]).forEach((methodName) => { + window.go[packageName][structName][methodName] = function() { + let timeout = 0; + function dynamic() { + const args = [].slice.call(arguments); + return Call([packageName, structName, methodName].join("."), args, timeout); + } + dynamic.setTimeout = function(newTimeout) { + timeout = newTimeout; + }; + dynamic.getTimeout = function() { + return timeout; + }; + return dynamic; + }(); + }); + }); + }); + } + + // desktop/window.js + var window_exports = {}; + __export(window_exports, { + WindowCenter: () => WindowCenter, + WindowFullscreen: () => WindowFullscreen, + WindowGetPosition: () => WindowGetPosition, + WindowGetSize: () => WindowGetSize, + WindowHide: () => WindowHide, + WindowIsFullscreen: () => WindowIsFullscreen, + WindowIsMaximised: () => WindowIsMaximised, + WindowIsMinimised: () => WindowIsMinimised, + WindowIsNormal: () => WindowIsNormal, + WindowMaximise: () => WindowMaximise, + WindowMinimise: () => WindowMinimise, + WindowReload: () => WindowReload, + WindowReloadApp: () => WindowReloadApp, + WindowSetAlwaysOnTop: () => WindowSetAlwaysOnTop, + WindowSetBackgroundColour: () => WindowSetBackgroundColour, + WindowSetDarkTheme: () => WindowSetDarkTheme, + WindowSetLightTheme: () => WindowSetLightTheme, + WindowSetMaxSize: () => WindowSetMaxSize, + WindowSetMinSize: () => WindowSetMinSize, + WindowSetPosition: () => WindowSetPosition, + WindowSetSize: () => WindowSetSize, + WindowSetSystemDefaultTheme: () => WindowSetSystemDefaultTheme, + WindowSetTitle: () => WindowSetTitle, + WindowShow: () => WindowShow, + WindowToggleMaximise: () => WindowToggleMaximise, + WindowUnfullscreen: () => WindowUnfullscreen, + WindowUnmaximise: () => WindowUnmaximise, + WindowUnminimise: () => WindowUnminimise + }); + function WindowReload() { + window.location.reload(); + } + function WindowReloadApp() { + window.WailsInvoke("WR"); + } + function WindowSetSystemDefaultTheme() { + window.WailsInvoke("WASDT"); + } + function WindowSetLightTheme() { + window.WailsInvoke("WALT"); + } + function WindowSetDarkTheme() { + window.WailsInvoke("WADT"); + } + function WindowCenter() { + window.WailsInvoke("Wc"); + } + function WindowSetTitle(title) { + window.WailsInvoke("WT" + title); + } + function WindowFullscreen() { + window.WailsInvoke("WF"); + } + function WindowUnfullscreen() { + window.WailsInvoke("Wf"); + } + function WindowIsFullscreen() { + return Call(":wails:WindowIsFullscreen"); + } + function WindowSetSize(width, height) { + window.WailsInvoke("Ws:" + width + ":" + height); + } + function WindowGetSize() { + return Call(":wails:WindowGetSize"); + } + function WindowSetMaxSize(width, height) { + window.WailsInvoke("WZ:" + width + ":" + height); + } + 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); + } + function WindowGetPosition() { + return Call(":wails:WindowGetPos"); + } + function WindowHide() { + window.WailsInvoke("WH"); + } + function WindowShow() { + window.WailsInvoke("WS"); + } + function WindowMaximise() { + window.WailsInvoke("WM"); + } + function WindowToggleMaximise() { + window.WailsInvoke("Wt"); + } + function WindowUnmaximise() { + window.WailsInvoke("WU"); + } + function WindowIsMaximised() { + return Call(":wails:WindowIsMaximised"); + } + function WindowMinimise() { + window.WailsInvoke("Wm"); + } + function WindowUnminimise() { + window.WailsInvoke("Wu"); + } + function WindowIsMinimised() { + return Call(":wails:WindowIsMinimised"); + } + function WindowIsNormal() { + return Call(":wails:WindowIsNormal"); + } + 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); + } + + // desktop/screen.js + var screen_exports = {}; + __export(screen_exports, { + ScreenGetAll: () => ScreenGetAll + }); + function ScreenGetAll() { + return Call(":wails:ScreenGetAll"); + } + + // desktop/browser.js + var browser_exports = {}; + __export(browser_exports, { + BrowserOpenURL: () => BrowserOpenURL + }); + function BrowserOpenURL(url) { + window.WailsInvoke("BO:" + url); + } + + // desktop/log.js + var log_exports = {}; + __export(log_exports, { + LogDebug: () => LogDebug, + LogError: () => LogError, + LogFatal: () => LogFatal, + LogInfo: () => LogInfo, + LogLevel: () => LogLevel, + LogPrint: () => LogPrint, + LogTrace: () => LogTrace, + LogWarning: () => LogWarning, + SetLogLevel: () => SetLogLevel + }); + function sendLogMessage(level, message) { + window.WailsInvoke("L" + level + message); + } + function LogTrace(message) { + sendLogMessage("T", message); + } + function LogPrint(message) { + sendLogMessage("P", message); + } + function LogDebug(message) { + sendLogMessage("D", message); + } + function LogInfo(message) { + sendLogMessage("I", message); + } + function LogWarning(message) { + sendLogMessage("W", message); + } + function LogError(message) { + sendLogMessage("E", message); + } + function LogFatal(message) { + sendLogMessage("F", message); + } + function SetLogLevel(loglevel) { + sendLogMessage("S", loglevel); + } + var LogLevel = { + TRACE: 1, + DEBUG: 2, + INFO: 3, + WARNING: 4, + ERROR: 5 + }; + + // desktop/main.js + var windowID = -1; + function Quit() { + window.WailsInvoke("Q"); + } + function Show() { + window.WailsInvoke("S"); + } + function Hide() { + window.WailsInvoke("H"); + } + window.wails = { + Callback, + callbacks, + EventsNotify, + eventListeners, + SetBindings, + window: { + ID: () => { + return windowID; + } + } + }; + window.runtime = { + ...log_exports, + ...window_exports, + ...browser_exports, + ...screen_exports, + EventsOn, + EventsOnce, + EventsOnMultiple, + EventsEmit, + EventsOff, + Show, + Hide, + Quit + }; + if (window.wails_config) { + windowID = window.wails_config.windowID; + window.wails_config = null; + } + if (true) { + console.log("Wails v3.0.0 Debug Mode Enabled"); + } +})(); +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiZGVza3RvcC9pcGMuanMiLCAiZGVza3RvcC9jYWxscy5qcyIsICJkZXNrdG9wL2V2ZW50cy5qcyIsICJkZXNrdG9wL2JpbmRpbmdzLmpzIiwgImRlc2t0b3Avd2luZG93LmpzIiwgImRlc2t0b3Avc2NyZWVuLmpzIiwgImRlc2t0b3AvYnJvd3Nlci5qcyIsICJkZXNrdG9wL2xvZy5qcyIsICJkZXNrdG9wL21haW4uanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qXG4gXyAgICAgICBfXyAgICAgIF8gX19cbnwgfCAgICAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuLyoganNoaW50IGVzdmVyc2lvbjogNiAqL1xuXG4vKipcbiAqIFdhaWxzSW52b2tlIHNlbmRzIHRoZSBnaXZlbiBtZXNzYWdlIHRvIHRoZSBiYWNrZW5kXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcbiAqL1xuXG4oZnVuY3Rpb24gKCkge1xuXHR3aW5kb3cuV2FpbHNJbnZva2UgPSAobWVzc2FnZSkgPT4ge1xuXHRcdFdJTkRPV1MgJiYgd2luZG93LmNocm9tZS53ZWJ2aWV3LnBvc3RNZXNzYWdlKG1lc3NhZ2UpO1xuXHRcdChEQVJXSU4gfHwgTElOVVgpICYmIHdpbmRvdy53ZWJraXQubWVzc2FnZUhhbmRsZXJzLndhaWxzLnBvc3RNZXNzYWdlKG1lc3NhZ2UpO1xuXHR9XG59KSgpOyIsICIvKlxuIF8gICAgICAgX18gICAgICBfIF9fXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cbi8qIGpzaGludCBlc3ZlcnNpb246IDYgKi9cblxuZXhwb3J0IGNvbnN0IGNhbGxiYWNrcyA9IHt9O1xuXG4vKipcbiAqIFJldHVybnMgYSBudW1iZXIgZnJvbSB0aGUgbmF0aXZlIGJyb3dzZXIgcmFuZG9tIGZ1bmN0aW9uXG4gKlxuICogQHJldHVybnMgbnVtYmVyXG4gKi9cbmZ1bmN0aW9uIGNyeXB0b1JhbmRvbSgpIHtcblx0dmFyIGFycmF5ID0gbmV3IFVpbnQzMkFycmF5KDEpO1xuXHRyZXR1cm4gd2luZG93LmNyeXB0by5nZXRSYW5kb21WYWx1ZXMoYXJyYXkpWzBdO1xufVxuXG4vKipcbiAqIFJldHVybnMgYSBudW1iZXIgdXNpbmcgZGEgb2xkLXNrb29sIE1hdGguUmFuZG9tXG4gKiBJIGxpa2VzIHRvIGNhbGwgaXQgTE9MUmFuZG9tXG4gKlxuICogQHJldHVybnMgbnVtYmVyXG4gKi9cbmZ1bmN0aW9uIGJhc2ljUmFuZG9tKCkge1xuXHRyZXR1cm4gTWF0aC5yYW5kb20oKSAqIDkwMDcxOTkyNTQ3NDA5OTE7XG59XG5cbi8vIFBpY2sgYSByYW5kb20gbnVtYmVyIGZ1bmN0aW9uIGJhc2VkIG9uIGJyb3dzZXIgY2FwYWJpbGl0eVxudmFyIHJhbmRvbUZ1bmM7XG5pZiAod2luZG93LmNyeXB0bykge1xuXHRyYW5kb21GdW5jID0gY3J5cHRvUmFuZG9tO1xufSBlbHNlIHtcblx0cmFuZG9tRnVuYyA9IGJhc2ljUmFuZG9tO1xufVxuXG5cbi8qKlxuICogQ2FsbCBzZW5kcyBhIG1lc3NhZ2UgdG8gdGhlIGJhY2tlbmQgdG8gY2FsbCB0aGUgYmluZGluZyB3aXRoIHRoZVxuICogZ2l2ZW4gZGF0YS4gQSBwcm9taXNlIGlzIHJldHVybmVkIGFuZCB3aWxsIGJlIGNvbXBsZXRlZCB3aGVuIHRoZVxuICogYmFja2VuZCByZXNwb25kcy4gVGhpcyB3aWxsIGJlIHJlc29sdmVkIHdoZW4gdGhlIGNhbGwgd2FzIHN1Y2Nlc3NmdWxcbiAqIG9yIHJlamVjdGVkIGlmIGFuIGVycm9yIGlzIHBhc3NlZCBiYWNrLlxuICogVGhlcmUgaXMgYSB0aW1lb3V0IG1lY2hhbmlzbS4gSWYgdGhlIGNhbGwgZG9lc24ndCByZXNwb25kIGluIHRoZSBnaXZlblxuICogdGltZSAoaW4gbWlsbGlzZWNvbmRzKSB0aGVuIHRoZSBwcm9taXNlIGlzIHJlamVjdGVkLlxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gKiBAcGFyYW0ge2FueT19IGFyZ3NcbiAqIEBwYXJhbSB7bnVtYmVyPX0gdGltZW91dFxuICogQHJldHVybnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENhbGwobmFtZSwgYXJncywgdGltZW91dCkge1xuXG5cdC8vIFRpbWVvdXQgaW5maW5pdGUgYnkgZGVmYXVsdFxuXHRpZiAodGltZW91dCA9PSBudWxsKSB7XG5cdFx0dGltZW91dCA9IDA7XG5cdH1cblxuXHRsZXQgd2luZG93SUQgPSB3aW5kb3cud2FpbHMud2luZG93LklEKCk7XG5cblx0Ly8gQ3JlYXRlIGEgcHJvbWlzZVxuXHRyZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuXG5cdFx0Ly8gQ3JlYXRlIGEgdW5pcXVlIGNhbGxiYWNrSURcblx0XHR2YXIgY2FsbGJhY2tJRDtcblx0XHRkbyB7XG5cdFx0XHRjYWxsYmFja0lEID0gbmFtZSArICctJyArIHJhbmRvbUZ1bmMoKTtcblx0XHR9IHdoaWxlIChjYWxsYmFja3NbY2FsbGJhY2tJRF0pO1xuXG5cdFx0dmFyIHRpbWVvdXRIYW5kbGU7XG5cdFx0Ly8gU2V0IHRpbWVvdXRcblx0XHRpZiAodGltZW91dCA+IDApIHtcblx0XHRcdHRpbWVvdXRIYW5kbGUgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0cmVqZWN0KEVycm9yKCdDYWxsIHRvICcgKyBuYW1lICsgJyB0aW1lZCBvdXQuIFJlcXVlc3QgSUQ6ICcgKyBjYWxsYmFja0lEKSk7XG5cdFx0XHR9LCB0aW1lb3V0KTtcblx0XHR9XG5cblx0XHQvLyBTdG9yZSBjYWxsYmFja1xuXHRcdGNhbGxiYWNrc1tjYWxsYmFja0lEXSA9IHtcblx0XHRcdHRpbWVvdXRIYW5kbGU6IHRpbWVvdXRIYW5kbGUsXG5cdFx0XHRyZWplY3Q6IHJlamVjdCxcblx0XHRcdHJlc29sdmU6IHJlc29sdmVcblx0XHR9O1xuXG5cdFx0dHJ5IHtcblx0XHRcdGNvbnN0IHBheWxvYWQgPSB7XG5cdFx0XHRcdG5hbWUsXG5cdFx0XHRcdGFyZ3MsXG5cdFx0XHRcdGNhbGxiYWNrSUQsXG5cdFx0XHRcdHdpbmRvd0lELFxuXHRcdFx0fTtcblxuICAgICAgICAgICAgLy8gTWFrZSB0aGUgY2FsbFxuICAgICAgICAgICAgd2luZG93LldhaWxzSW52b2tlKCdDJyArIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbndpbmRvdy5PYmZ1c2NhdGVkQ2FsbCA9IChpZCwgYXJncywgdGltZW91dCkgPT4ge1xuXG4gICAgLy8gVGltZW91dCBpbmZpbml0ZSBieSBkZWZhdWx0XG4gICAgaWYgKHRpbWVvdXQgPT0gbnVsbCkge1xuICAgICAgICB0aW1lb3V0ID0gMDtcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgYSBwcm9taXNlXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcblxuICAgICAgICAvLyBDcmVhdGUgYSB1bmlxdWUgY2FsbGJhY2tJRFxuICAgICAgICB2YXIgY2FsbGJhY2tJRDtcbiAgICAgICAgZG8ge1xuICAgICAgICAgICAgY2FsbGJhY2tJRCA9IGlkICsgJy0nICsgcmFuZG9tRnVuYygpO1xuICAgICAgICB9IHdoaWxlIChjYWxsYmFja3NbY2FsbGJhY2tJRF0pO1xuXG4gICAgICAgIHZhciB0aW1lb3V0SGFuZGxlO1xuICAgICAgICAvLyBTZXQgdGltZW91dFxuICAgICAgICBpZiAodGltZW91dCA+IDApIHtcbiAgICAgICAgICAgIHRpbWVvdXRIYW5kbGUgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ0NhbGwgdG8gbWV0aG9kICcgKyBpZCArICcgdGltZWQgb3V0LiBSZXF1ZXN0IElEOiAnICsgY2FsbGJhY2tJRCkpO1xuICAgICAgICAgICAgfSwgdGltZW91dCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTdG9yZSBjYWxsYmFja1xuICAgICAgICBjYWxsYmFja3NbY2FsbGJhY2tJRF0gPSB7XG4gICAgICAgICAgICB0aW1lb3V0SGFuZGxlOiB0aW1lb3V0SGFuZGxlLFxuICAgICAgICAgICAgcmVqZWN0OiByZWplY3QsXG4gICAgICAgICAgICByZXNvbHZlOiByZXNvbHZlXG4gICAgICAgIH07XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSB7XG5cdFx0XHRcdGlkLFxuXHRcdFx0XHRhcmdzLFxuXHRcdFx0XHRjYWxsYmFja0lELFxuXHRcdFx0XHR3aW5kb3dJRDogd2luZG93LndhaWxzLndpbmRvdy5JRCgpLFxuXHRcdFx0fTtcblxuICAgICAgICAgICAgLy8gTWFrZSB0aGUgY2FsbFxuICAgICAgICAgICAgd2luZG93LldhaWxzSW52b2tlKCdjJyArIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfSk7XG59O1xuXG5cbi8qKlxuICogQ2FsbGVkIGJ5IHRoZSBiYWNrZW5kIHRvIHJldHVybiBkYXRhIHRvIGEgcHJldmlvdXNseSBjYWxsZWRcbiAqIGJpbmRpbmcgaW52b2NhdGlvblxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBpbmNvbWluZ01lc3NhZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENhbGxiYWNrKGluY29taW5nTWVzc2FnZSkge1xuXHQvLyBQYXJzZSB0aGUgbWVzc2FnZVxuXHRsZXQgbWVzc2FnZTtcblx0dHJ5IHtcblx0XHRtZXNzYWdlID0gSlNPTi5wYXJzZShpbmNvbWluZ01lc3NhZ2UpO1xuXHR9IGNhdGNoIChlKSB7XG5cdFx0Y29uc3QgZXJyb3IgPSBgSW52YWxpZCBKU09OIHBhc3NlZCB0byBjYWxsYmFjazogJHtlLm1lc3NhZ2V9LiBNZXNzYWdlOiAke2luY29taW5nTWVzc2FnZX1gO1xuXHRcdHJ1bnRpbWUuTG9nRGVidWcoZXJyb3IpO1xuXHRcdHRocm93IG5ldyBFcnJvcihlcnJvcik7XG5cdH1cblx0bGV0IGNhbGxiYWNrSUQgPSBtZXNzYWdlLmNhbGxiYWNraWQ7XG5cdGxldCBjYWxsYmFja0RhdGEgPSBjYWxsYmFja3NbY2FsbGJhY2tJRF07XG5cdGlmICghY2FsbGJhY2tEYXRhKSB7XG5cdFx0Y29uc3QgZXJyb3IgPSBgQ2FsbGJhY2sgJyR7Y2FsbGJhY2tJRH0nIG5vdCByZWdpc3RlcmVkISEhYDtcblx0XHRjb25zb2xlLmVycm9yKGVycm9yKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHRcdHRocm93IG5ldyBFcnJvcihlcnJvcik7XG5cdH1cblx0Y2xlYXJUaW1lb3V0KGNhbGxiYWNrRGF0YS50aW1lb3V0SGFuZGxlKTtcblxuXHRkZWxldGUgY2FsbGJhY2tzW2NhbGxiYWNrSURdO1xuXG5cdGlmIChtZXNzYWdlLmVycm9yKSB7XG5cdFx0Y2FsbGJhY2tEYXRhLnJlamVjdChtZXNzYWdlLmVycm9yKTtcblx0fSBlbHNlIHtcblx0XHRjYWxsYmFja0RhdGEucmVzb2x2ZShtZXNzYWdlLnJlc3VsdCk7XG5cdH1cbn1cbiIsICIvKlxuIF8gICAgICAgX18gICAgICBfIF9fXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cbi8qIGpzaGludCBlc3ZlcnNpb246IDYgKi9cblxuLy8gRGVmaW5lcyBhIHNpbmdsZSBsaXN0ZW5lciB3aXRoIGEgbWF4aW11bSBudW1iZXIgb2YgdGltZXMgdG8gY2FsbGJhY2tcblxuLyoqXG4gKiBUaGUgTGlzdGVuZXIgY2xhc3MgZGVmaW5lcyBhIGxpc3RlbmVyISA6LSlcbiAqXG4gKiBAY2xhc3MgTGlzdGVuZXJcbiAqL1xuY2xhc3MgTGlzdGVuZXIge1xuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgTGlzdGVuZXIuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG1heENhbGxiYWNrc1xuICAgICAqIEBtZW1iZXJvZiBMaXN0ZW5lclxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG1heENhbGxiYWNrcykge1xuICAgICAgICB0aGlzLmV2ZW50TmFtZSA9IGV2ZW50TmFtZTtcbiAgICAgICAgLy8gRGVmYXVsdCBvZiAtMSBtZWFucyBpbmZpbml0ZVxuICAgICAgICB0aGlzLm1heENhbGxiYWNrcyA9IG1heENhbGxiYWNrcyB8fCAtMTtcbiAgICAgICAgLy8gQ2FsbGJhY2sgaW52b2tlcyB0aGUgY2FsbGJhY2sgd2l0aCB0aGUgZ2l2ZW4gZGF0YVxuICAgICAgICAvLyBSZXR1cm5zIHRydWUgaWYgdGhpcyBsaXN0ZW5lciBzaG91bGQgYmUgZGVzdHJveWVkXG4gICAgICAgIHRoaXMuQ2FsbGJhY2sgPSAoZGF0YSkgPT4ge1xuICAgICAgICAgICAgY2FsbGJhY2suYXBwbHkobnVsbCwgZGF0YSk7XG4gICAgICAgICAgICAvLyBJZiBtYXhDYWxsYmFja3MgaXMgaW5maW5pdGUsIHJldHVybiBmYWxzZSAoZG8gbm90IGRlc3Ryb3kpXG4gICAgICAgICAgICBpZiAodGhpcy5tYXhDYWxsYmFja3MgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRGVjcmVtZW50IG1heENhbGxiYWNrcy4gUmV0dXJuIHRydWUgaWYgbm93IDAsIG90aGVyd2lzZSBmYWxzZVxuICAgICAgICAgICAgdGhpcy5tYXhDYWxsYmFja3MgLT0gMTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1heENhbGxiYWNrcyA9PT0gMDtcbiAgICAgICAgfTtcbiAgICB9XG59XG5cbmV4cG9ydCBjb25zdCBldmVudExpc3RlbmVycyA9IHt9O1xuXG4vKipcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBgbWF4Q2FsbGJhY2tzYCB0aW1lcyBiZWZvcmUgYmVpbmcgZGVzdHJveWVkXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhDYWxsYmFja3NcbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gQSBmdW5jdGlvbiB0byBjYW5jZWwgdGhlIGxpc3RlbmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG1heENhbGxiYWNrcykge1xuICAgIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0gPSBldmVudExpc3RlbmVyc1tldmVudE5hbWVdIHx8IFtdO1xuICAgIGNvbnN0IHRoaXNMaXN0ZW5lciA9IG5ldyBMaXN0ZW5lcihldmVudE5hbWUsIGNhbGxiYWNrLCBtYXhDYWxsYmFja3MpO1xuICAgIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0ucHVzaCh0aGlzTGlzdGVuZXIpO1xuICAgIHJldHVybiAoKSA9PiBsaXN0ZW5lck9mZih0aGlzTGlzdGVuZXIpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBldmVyeSB0aW1lIHRoZSBldmVudCBpcyBlbWl0dGVkXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gQSBmdW5jdGlvbiB0byBjYW5jZWwgdGhlIGxpc3RlbmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbihldmVudE5hbWUsIGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIEV2ZW50c09uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgLTEpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBvbmNlIHRoZW4gZGVzdHJveWVkXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gQSBmdW5jdGlvbiB0byBjYW5jZWwgdGhlIGxpc3RlbmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbmNlKGV2ZW50TmFtZSwgY2FsbGJhY2spIHtcbiAgICByZXR1cm4gRXZlbnRzT25NdWx0aXBsZShldmVudE5hbWUsIGNhbGxiYWNrLCAxKTtcbn1cblxuZnVuY3Rpb24gbm90aWZ5TGlzdGVuZXJzKGV2ZW50RGF0YSkge1xuXG4gICAgLy8gR2V0IHRoZSBldmVudCBuYW1lXG4gICAgbGV0IGV2ZW50TmFtZSA9IGV2ZW50RGF0YS5uYW1lO1xuXG4gICAgLy8gQ2hlY2sgaWYgd2UgaGF2ZSBhbnkgbGlzdGVuZXJzIGZvciB0aGlzIGV2ZW50XG4gICAgaWYgKGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0pIHtcblxuICAgICAgICAvLyBLZWVwIGEgbGlzdCBvZiBsaXN0ZW5lciBpbmRleGVzIHRvIGRlc3Ryb3lcbiAgICAgICAgY29uc3QgbmV3RXZlbnRMaXN0ZW5lckxpc3QgPSBldmVudExpc3RlbmVyc1tldmVudE5hbWVdLnNsaWNlKCk7XG5cbiAgICAgICAgLy8gSXRlcmF0ZSBsaXN0ZW5lcnNcbiAgICAgICAgZm9yIChsZXQgY291bnQgPSAwOyBjb3VudCA8IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0ubGVuZ3RoOyBjb3VudCArPSAxKSB7XG5cbiAgICAgICAgICAgIC8vIEdldCBuZXh0IGxpc3RlbmVyXG4gICAgICAgICAgICBjb25zdCBsaXN0ZW5lciA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV1bY291bnRdO1xuXG4gICAgICAgICAgICBsZXQgZGF0YSA9IGV2ZW50RGF0YS5kYXRhO1xuXG4gICAgICAgICAgICAvLyBEbyB0aGUgY2FsbGJhY2tcbiAgICAgICAgICAgIGNvbnN0IGRlc3Ryb3kgPSBsaXN0ZW5lci5DYWxsYmFjayhkYXRhKTtcbiAgICAgICAgICAgIGlmIChkZXN0cm95KSB7XG4gICAgICAgICAgICAgICAgLy8gaWYgdGhlIGxpc3RlbmVyIGluZGljYXRlZCB0byBkZXN0cm95IGl0c2VsZiwgYWRkIGl0IHRvIHRoZSBkZXN0cm95IGxpc3RcbiAgICAgICAgICAgICAgICBuZXdFdmVudExpc3RlbmVyTGlzdC5zcGxpY2UoY291bnQsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gVXBkYXRlIGNhbGxiYWNrcyB3aXRoIG5ldyBsaXN0IG9mIGxpc3RlbmVyc1xuICAgICAgICBpZiAobmV3RXZlbnRMaXN0ZW5lckxpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZW1vdmVMaXN0ZW5lcihldmVudE5hbWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSA9IG5ld0V2ZW50TGlzdGVuZXJMaXN0O1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqIE5vdGlmeSBpbmZvcm1zIGZyb250ZW5kIGxpc3RlbmVycyB0aGF0IGFuIGV2ZW50IHdhcyBlbWl0dGVkIHdpdGggdGhlIGdpdmVuIGRhdGFcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbm90aWZ5TWVzc2FnZSAtIGVuY29kZWQgbm90aWZpY2F0aW9uIG1lc3NhZ2VcblxuICovXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzTm90aWZ5KG5vdGlmeU1lc3NhZ2UpIHtcbiAgICAvLyBQYXJzZSB0aGUgbWVzc2FnZVxuICAgIGxldCBtZXNzYWdlO1xuICAgIHRyeSB7XG4gICAgICAgIG1lc3NhZ2UgPSBKU09OLnBhcnNlKG5vdGlmeU1lc3NhZ2UpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc3QgZXJyb3IgPSAnSW52YWxpZCBKU09OIHBhc3NlZCB0byBOb3RpZnk6ICcgKyBub3RpZnlNZXNzYWdlO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3IpO1xuICAgIH1cbiAgICBub3RpZnlMaXN0ZW5lcnMobWVzc2FnZSk7XG59XG5cbi8qKlxuICogRW1pdCBhbiBldmVudCB3aXRoIHRoZSBnaXZlbiBuYW1lIGFuZCBkYXRhXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICovXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzRW1pdChldmVudE5hbWUpIHtcblxuICAgIGNvbnN0IHBheWxvYWQgPSB7XG4gICAgICAgIG5hbWU6IGV2ZW50TmFtZSxcbiAgICAgICAgZGF0YTogW10uc2xpY2UuYXBwbHkoYXJndW1lbnRzKS5zbGljZSgxKSxcbiAgICB9O1xuXG4gICAgLy8gTm90aWZ5IEpTIGxpc3RlbmVyc1xuICAgIG5vdGlmeUxpc3RlbmVycyhwYXlsb2FkKTtcblxuICAgIC8vIE5vdGlmeSBHbyBsaXN0ZW5lcnNcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ0VFJyArIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcbn1cblxuZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIoZXZlbnROYW1lKSB7XG4gICAgLy8gUmVtb3ZlIGxvY2FsIGxpc3RlbmVyc1xuICAgIGRlbGV0ZSBldmVudExpc3RlbmVyc1tldmVudE5hbWVdO1xuXG4gICAgLy8gTm90aWZ5IEdvIGxpc3RlbmVyc1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnRVgnICsgZXZlbnROYW1lKTtcbn1cblxuLyoqXG4gKiBPZmYgdW5yZWdpc3RlcnMgYSBsaXN0ZW5lciBwcmV2aW91c2x5IHJlZ2lzdGVyZWQgd2l0aCBPbixcbiAqIG9wdGlvbmFsbHkgbXVsdGlwbGUgbGlzdGVuZXJlcyBjYW4gYmUgdW5yZWdpc3RlcmVkIHZpYSBgYWRkaXRpb25hbEV2ZW50TmFtZXNgXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtICB7Li4uc3RyaW5nfSBhZGRpdGlvbmFsRXZlbnROYW1lc1xuICovXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzT2ZmKGV2ZW50TmFtZSwgLi4uYWRkaXRpb25hbEV2ZW50TmFtZXMpIHtcbiAgICByZW1vdmVMaXN0ZW5lcihldmVudE5hbWUpXG5cbiAgICBpZiAoYWRkaXRpb25hbEV2ZW50TmFtZXMubGVuZ3RoID4gMCkge1xuICAgICAgICBhZGRpdGlvbmFsRXZlbnROYW1lcy5mb3JFYWNoKGV2ZW50TmFtZSA9PiB7XG4gICAgICAgICAgICByZW1vdmVMaXN0ZW5lcihldmVudE5hbWUpXG4gICAgICAgIH0pXG4gICAgfVxufVxuXG4vKipcbiAqIE9mZiB1bnJlZ2lzdGVycyBhbGwgZXZlbnQgbGlzdGVuZXJzIHByZXZpb3VzbHkgcmVnaXN0ZXJlZCB3aXRoIE9uXG4gKi9cbiBleHBvcnQgZnVuY3Rpb24gRXZlbnRzT2ZmQWxsKCkge1xuICAgIGNvbnN0IGV2ZW50TmFtZXMgPSBPYmplY3Qua2V5cyhldmVudExpc3RlbmVycyk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgIT09IGV2ZW50TmFtZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcmVtb3ZlTGlzdGVuZXIoZXZlbnROYW1lc1tpXSk7XG4gICAgfVxufVxuXG4vKipcbiAqIGxpc3RlbmVyT2ZmIHVucmVnaXN0ZXJzIGEgbGlzdGVuZXIgcHJldmlvdXNseSByZWdpc3RlcmVkIHdpdGggRXZlbnRzT25cbiAqXG4gKiBAcGFyYW0ge0xpc3RlbmVyfSBsaXN0ZW5lclxuICovXG4gZnVuY3Rpb24gbGlzdGVuZXJPZmYobGlzdGVuZXIpIHtcbiAgICBjb25zdCBldmVudE5hbWUgPSBsaXN0ZW5lci5ldmVudE5hbWU7XG4gICAgLy8gUmVtb3ZlIGxvY2FsIGxpc3RlbmVyXG4gICAgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0uZmlsdGVyKGwgPT4gbCAhPT0gbGlzdGVuZXIpO1xuXG4gICAgLy8gQ2xlYW4gdXAgaWYgdGhlcmUgYXJlIG5vIGV2ZW50IGxpc3RlbmVycyBsZWZ0XG4gICAgaWYgKGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0ubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJlbW92ZUxpc3RlbmVyKGV2ZW50TmFtZSk7XG4gICAgfVxufVxuIiwgIi8qXG4gXyAgICAgICBfXyAgICAgIF8gX18gICAgXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gICkgXG58X18vfF9fL1xcX18sXy9fL18vX19fXy8gIFxuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cbi8qIGpzaGludCBlc3ZlcnNpb246IDYgKi9cblxuaW1wb3J0IHtDYWxsfSBmcm9tICcuL2NhbGxzJztcblxuLy8gVGhpcyBpcyB3aGVyZSB3ZSBiaW5kIGdvIG1ldGhvZCB3cmFwcGVyc1xud2luZG93LmdvID0ge307XG5cbmV4cG9ydCBmdW5jdGlvbiBTZXRCaW5kaW5ncyhiaW5kaW5nc01hcCkge1xuXHR0cnkge1xuXHRcdGJpbmRpbmdzTWFwID0gSlNPTi5wYXJzZShiaW5kaW5nc01hcCk7XG5cdH0gY2F0Y2ggKGUpIHtcblx0XHRjb25zb2xlLmVycm9yKGUpO1xuXHR9XG5cblx0Ly8gSW5pdGlhbGlzZSB0aGUgYmluZGluZ3MgbWFwXG5cdHdpbmRvdy5nbyA9IHdpbmRvdy5nbyB8fCB7fTtcblxuXHQvLyBJdGVyYXRlIHBhY2thZ2UgbmFtZXNcblx0T2JqZWN0LmtleXMoYmluZGluZ3NNYXApLmZvckVhY2goKHBhY2thZ2VOYW1lKSA9PiB7XG5cblx0XHQvLyBDcmVhdGUgaW5uZXIgbWFwIGlmIGl0IGRvZXNuJ3QgZXhpc3Rcblx0XHR3aW5kb3cuZ29bcGFja2FnZU5hbWVdID0gd2luZG93LmdvW3BhY2thZ2VOYW1lXSB8fCB7fTtcblxuXHRcdC8vIEl0ZXJhdGUgc3RydWN0IG5hbWVzXG5cdFx0T2JqZWN0LmtleXMoYmluZGluZ3NNYXBbcGFja2FnZU5hbWVdKS5mb3JFYWNoKChzdHJ1Y3ROYW1lKSA9PiB7XG5cblx0XHRcdC8vIENyZWF0ZSBpbm5lciBtYXAgaWYgaXQgZG9lc24ndCBleGlzdFxuXHRcdFx0d2luZG93LmdvW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXSA9IHdpbmRvdy5nb1twYWNrYWdlTmFtZV1bc3RydWN0TmFtZV0gfHwge307XG5cblx0XHRcdE9iamVjdC5rZXlzKGJpbmRpbmdzTWFwW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXSkuZm9yRWFjaCgobWV0aG9kTmFtZSkgPT4ge1xuXG5cdFx0XHRcdHdpbmRvdy5nb1twYWNrYWdlTmFtZV1bc3RydWN0TmFtZV1bbWV0aG9kTmFtZV0gPSBmdW5jdGlvbiAoKSB7XG5cblx0XHRcdFx0XHQvLyBObyB0aW1lb3V0IGJ5IGRlZmF1bHRcblx0XHRcdFx0XHRsZXQgdGltZW91dCA9IDA7XG5cblx0XHRcdFx0XHQvLyBBY3R1YWwgZnVuY3Rpb25cblx0XHRcdFx0XHRmdW5jdGlvbiBkeW5hbWljKCkge1xuXHRcdFx0XHRcdFx0Y29uc3QgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcblx0XHRcdFx0XHRcdHJldHVybiBDYWxsKFtwYWNrYWdlTmFtZSwgc3RydWN0TmFtZSwgbWV0aG9kTmFtZV0uam9pbignLicpLCBhcmdzLCB0aW1lb3V0KTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBBbGxvdyBzZXR0aW5nIHRpbWVvdXQgdG8gZnVuY3Rpb25cblx0XHRcdFx0XHRkeW5hbWljLnNldFRpbWVvdXQgPSBmdW5jdGlvbiAobmV3VGltZW91dCkge1xuXHRcdFx0XHRcdFx0dGltZW91dCA9IG5ld1RpbWVvdXQ7XG5cdFx0XHRcdFx0fTtcblxuXHRcdFx0XHRcdC8vIEFsbG93IGdldHRpbmcgdGltZW91dCB0byBmdW5jdGlvblxuXHRcdFx0XHRcdGR5bmFtaWMuZ2V0VGltZW91dCA9IGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRcdHJldHVybiB0aW1lb3V0O1xuXHRcdFx0XHRcdH07XG5cblx0XHRcdFx0XHRyZXR1cm4gZHluYW1pYztcblx0XHRcdFx0fSgpO1xuXHRcdFx0fSk7XG5cdFx0fSk7XG5cdH0pO1xufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cblxuaW1wb3J0IHtDYWxsfSBmcm9tIFwiLi9jYWxsc1wiO1xuXG5leHBvcnQgZnVuY3Rpb24gV2luZG93UmVsb2FkKCkge1xuICAgIHdpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1JlbG9hZEFwcCgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dSJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRTeXN0ZW1EZWZhdWx0VGhlbWUoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXQVNEVCcpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0TGlnaHRUaGVtZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dBTFQnKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldERhcmtUaGVtZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dBRFQnKTtcbn1cblxuLyoqXG4gKiBQbGFjZSB0aGUgd2luZG93IGluIHRoZSBjZW50ZXIgb2YgdGhlIHNjcmVlblxuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0NlbnRlcigpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1djJyk7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgd2luZG93IHRpdGxlXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHRpdGxlXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRUaXRsZSh0aXRsZSkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV1QnICsgdGl0bGUpO1xufVxuXG4vKipcbiAqIE1ha2VzIHRoZSB3aW5kb3cgZ28gZnVsbHNjcmVlblxuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0Z1bGxzY3JlZW4oKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXRicpO1xufVxuXG4vKipcbiAqIFJldmVydHMgdGhlIHdpbmRvdyBmcm9tIGZ1bGxzY3JlZW5cbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dVbmZ1bGxzY3JlZW4oKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXZicpO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIHN0YXRlIG9mIHRoZSB3aW5kb3csIGkuZS4gd2hldGhlciB0aGUgd2luZG93IGlzIGluIGZ1bGwgc2NyZWVuIG1vZGUgb3Igbm90LlxuICpcbiAqIEBleHBvcnRcbiAqIEByZXR1cm4ge1Byb21pc2U8Ym9vbGVhbj59IFRoZSBzdGF0ZSBvZiB0aGUgd2luZG93XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dJc0Z1bGxzY3JlZW4oKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6V2luZG93SXNGdWxsc2NyZWVuXCIpO1xufVxuXG4vKipcbiAqIFNldCB0aGUgU2l6ZSBvZiB0aGUgd2luZG93XG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRTaXplKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dzOicgKyB3aWR0aCArICc6JyArIGhlaWdodCk7XG59XG5cbi8qKlxuICogR2V0IHRoZSBTaXplIG9mIHRoZSB3aW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcmV0dXJuIHtQcm9taXNlPHt3OiBudW1iZXIsIGg6IG51bWJlcn0+fSBUaGUgc2l6ZSBvZiB0aGUgd2luZG93XG5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0dldFNpemUoKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6V2luZG93R2V0U2l6ZVwiKTtcbn1cblxuLyoqXG4gKiBTZXQgdGhlIG1heGltdW0gc2l6ZSBvZiB0aGUgd2luZG93XG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRNYXhTaXplKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1daOicgKyB3aWR0aCArICc6JyArIGhlaWdodCk7XG59XG5cbi8qKlxuICogU2V0IHRoZSBtaW5pbXVtIHNpemUgb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aFxuICogQHBhcmFtIHtudW1iZXJ9IGhlaWdodFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0TWluU2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXejonICsgd2lkdGggKyAnOicgKyBoZWlnaHQpO1xufVxuXG5cblxuLyoqXG4gKiBTZXQgdGhlIHdpbmRvdyBBbHdheXNPblRvcCBvciBub3Qgb24gdG9wXG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0QWx3YXlzT25Ub3AoYikge1xuXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXQVRQOicgKyAoYiA/ICcxJyA6ICcwJykpO1xufVxuXG5cblxuXG4vKipcbiAqIFNldCB0aGUgUG9zaXRpb24gb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7bnVtYmVyfSB4XG4gKiBAcGFyYW0ge251bWJlcn0geVxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0UG9zaXRpb24oeCwgeSkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3A6JyArIHggKyAnOicgKyB5KTtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIFBvc2l0aW9uIG9mIHRoZSB3aW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcmV0dXJuIHtQcm9taXNlPHt4OiBudW1iZXIsIHk6IG51bWJlcn0+fSBUaGUgcG9zaXRpb24gb2YgdGhlIHdpbmRvd1xuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93R2V0UG9zaXRpb24oKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6V2luZG93R2V0UG9zXCIpO1xufVxuXG4vKipcbiAqIEhpZGUgdGhlIFdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0hpZGUoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXSCcpO1xufVxuXG4vKipcbiAqIFNob3cgdGhlIFdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1Nob3coKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXUycpO1xufVxuXG4vKipcbiAqIE1heGltaXNlIHRoZSBXaW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dNYXhpbWlzZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dNJyk7XG59XG5cbi8qKlxuICogVG9nZ2xlIHRoZSBNYXhpbWlzZSBvZiB0aGUgV2luZG93XG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93VG9nZ2xlTWF4aW1pc2UoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXdCcpO1xufVxuXG4vKipcbiAqIFVubWF4aW1pc2UgdGhlIFdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1VubWF4aW1pc2UoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXVScpO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIHN0YXRlIG9mIHRoZSB3aW5kb3csIGkuZS4gd2hldGhlciB0aGUgd2luZG93IGlzIG1heGltaXNlZCBvciBub3QuXG4gKlxuICogQGV4cG9ydFxuICogQHJldHVybiB7UHJvbWlzZTxib29sZWFuPn0gVGhlIHN0YXRlIG9mIHRoZSB3aW5kb3dcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0lzTWF4aW1pc2VkKCkge1xuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOldpbmRvd0lzTWF4aW1pc2VkXCIpO1xufVxuXG4vKipcbiAqIE1pbmltaXNlIHRoZSBXaW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dNaW5pbWlzZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dtJyk7XG59XG5cbi8qKlxuICogVW5taW5pbWlzZSB0aGUgV2luZG93XG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93VW5taW5pbWlzZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1d1Jyk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgc3RhdGUgb2YgdGhlIHdpbmRvdywgaS5lLiB3aGV0aGVyIHRoZSB3aW5kb3cgaXMgbWluaW1pc2VkIG9yIG5vdC5cbiAqXG4gKiBAZXhwb3J0XG4gKiBAcmV0dXJuIHtQcm9taXNlPGJvb2xlYW4+fSBUaGUgc3RhdGUgb2YgdGhlIHdpbmRvd1xuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93SXNNaW5pbWlzZWQoKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6V2luZG93SXNNaW5pbWlzZWRcIik7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgc3RhdGUgb2YgdGhlIHdpbmRvdywgaS5lLiB3aGV0aGVyIHRoZSB3aW5kb3cgaXMgbm9ybWFsIG9yIG5vdC5cbiAqXG4gKiBAZXhwb3J0XG4gKiBAcmV0dXJuIHtQcm9taXNlPGJvb2xlYW4+fSBUaGUgc3RhdGUgb2YgdGhlIHdpbmRvd1xuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93SXNOb3JtYWwoKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6V2luZG93SXNOb3JtYWxcIik7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgYmFja2dyb3VuZCBjb2xvdXIgb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7bnVtYmVyfSBSIFJlZFxuICogQHBhcmFtIHtudW1iZXJ9IEcgR3JlZW5cbiAqIEBwYXJhbSB7bnVtYmVyfSBCIEJsdWVcbiAqIEBwYXJhbSB7bnVtYmVyfSBBIEFscGhhXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRCYWNrZ3JvdW5kQ29sb3VyKFIsIEcsIEIsIEEpIHtcbiAgICBsZXQgcmdiYSA9IEpTT04uc3RyaW5naWZ5KHtyOiBSIHx8IDAsIGc6IEcgfHwgMCwgYjogQiB8fCAwLCBhOiBBIHx8IDI1NX0pO1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3I6JyArIHJnYmEpO1xufVxuXG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cblxuXG5pbXBvcnQge0NhbGx9IGZyb20gXCIuL2NhbGxzXCI7XG5cblxuLyoqXG4gKiBHZXRzIHRoZSBhbGwgc2NyZWVucy4gQ2FsbCB0aGlzIGFuZXcgZWFjaCB0aW1lIHlvdSB3YW50IHRvIHJlZnJlc2ggZGF0YSBmcm9tIHRoZSB1bmRlcmx5aW5nIHdpbmRvd2luZyBzeXN0ZW0uXG4gKiBAZXhwb3J0XG4gKiBAdHlwZWRlZiB7aW1wb3J0KCcuLi93cmFwcGVyL3J1bnRpbWUnKS5TY3JlZW59IFNjcmVlblxuICogQHJldHVybiB7UHJvbWlzZTx7U2NyZWVuW119Pn0gVGhlIHNjcmVlbnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNjcmVlbkdldEFsbCgpIHtcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpTY3JlZW5HZXRBbGxcIik7XG59XG4iLCAiLyoqXG4gKiBAZGVzY3JpcHRpb246IFVzZSB0aGUgc3lzdGVtIGRlZmF1bHQgYnJvd3NlciB0byBvcGVuIHRoZSB1cmxcbiAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gQnJvd3Nlck9wZW5VUkwodXJsKSB7XG4gIHdpbmRvdy5XYWlsc0ludm9rZSgnQk86JyArIHVybCk7XG59IiwgIi8qXG4gXyAgICAgICBfXyAgICAgIF8gX19cbnwgfCAgICAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA2ICovXG5cbi8qKlxuICogU2VuZHMgYSBsb2cgbWVzc2FnZSB0byB0aGUgYmFja2VuZCB3aXRoIHRoZSBnaXZlbiBsZXZlbCArIG1lc3NhZ2VcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbGV2ZWxcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmZ1bmN0aW9uIHNlbmRMb2dNZXNzYWdlKGxldmVsLCBtZXNzYWdlKSB7XG5cblx0Ly8gTG9nIE1lc3NhZ2UgZm9ybWF0OlxuXHQvLyBsW3R5cGVdW21lc3NhZ2VdXG5cdHdpbmRvdy5XYWlsc0ludm9rZSgnTCcgKyBsZXZlbCArIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIExvZyB0aGUgZ2l2ZW4gdHJhY2UgbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIExvZ1RyYWNlKG1lc3NhZ2UpIHtcblx0c2VuZExvZ01lc3NhZ2UoJ1QnLCBtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBMb2cgdGhlIGdpdmVuIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dQcmludChtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdQJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiBkZWJ1ZyBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nRGVidWcobWVzc2FnZSkge1xuXHRzZW5kTG9nTWVzc2FnZSgnRCcsIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIExvZyB0aGUgZ2l2ZW4gaW5mbyBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nSW5mbyhtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdJJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiB3YXJuaW5nIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dXYXJuaW5nKG1lc3NhZ2UpIHtcblx0c2VuZExvZ01lc3NhZ2UoJ1cnLCBtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBMb2cgdGhlIGdpdmVuIGVycm9yIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dFcnJvcihtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdFJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiBmYXRhbCBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nRmF0YWwobWVzc2FnZSkge1xuXHRzZW5kTG9nTWVzc2FnZSgnRicsIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIExvZyBsZXZlbCB0byB0aGUgZ2l2ZW4gbG9nIGxldmVsXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtudW1iZXJ9IGxvZ2xldmVsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRMb2dMZXZlbChsb2dsZXZlbCkge1xuXHRzZW5kTG9nTWVzc2FnZSgnUycsIGxvZ2xldmVsKTtcbn1cblxuLy8gTG9nIGxldmVsc1xuZXhwb3J0IGNvbnN0IExvZ0xldmVsID0ge1xuXHRUUkFDRTogMSxcblx0REVCVUc6IDIsXG5cdElORk86IDMsXG5cdFdBUk5JTkc6IDQsXG5cdEVSUk9SOiA1LFxufTtcbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cblxuaW1wb3J0IFwiLi9pcGMuanNcIjtcbmltcG9ydCB7Q2FsbGJhY2ssIGNhbGxiYWNrc30gZnJvbSAnLi9jYWxscyc7XG5pbXBvcnQge0V2ZW50c05vdGlmeSwgZXZlbnRMaXN0ZW5lcnN9IGZyb20gXCIuL2V2ZW50c1wiO1xuaW1wb3J0IHtTZXRCaW5kaW5nc30gZnJvbSBcIi4vYmluZGluZ3NcIjtcblxuaW1wb3J0ICogYXMgV2luZG93IGZyb20gXCIuL3dpbmRvd1wiO1xuaW1wb3J0ICogYXMgU2NyZWVuIGZyb20gXCIuL3NjcmVlblwiO1xuaW1wb3J0ICogYXMgQnJvd3NlciBmcm9tIFwiLi9icm93c2VyXCI7XG5pbXBvcnQgKiBhcyBMb2cgZnJvbSAnLi9sb2cnO1xuXG5sZXQgd2luZG93SUQgPSAtMTtcblxuXG5leHBvcnQgZnVuY3Rpb24gUXVpdCgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1EnKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIFNob3coKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdTJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBIaWRlKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnSCcpO1xufVxuXG4vLyBleHBvcnQgZnVuY3Rpb24gRW52aXJvbm1lbnQoKSB7XG4vLyAgICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6RW52aXJvbm1lbnRcIik7XG4vLyB9XG5cbi8vIEludGVybmFsIHdhaWxzIGVuZHBvaW50c1xud2luZG93LndhaWxzID0ge1xuICAgIENhbGxiYWNrLFxuICAgIGNhbGxiYWNrcyxcbiAgICBFdmVudHNOb3RpZnksXG4gICAgZXZlbnRMaXN0ZW5lcnMsXG4gICAgU2V0QmluZGluZ3MsXG4gICAgd2luZG93OiB7XG4gICAgICAgIElEOiAoKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gd2luZG93SURcbiAgICAgICAgfSxcbiAgICB9XG59O1xuXG53aW5kb3cucnVudGltZSA9IHtcbiAgICAuLi5Mb2csXG4gICAgLi4uV2luZG93LFxuICAgIC4uLkJyb3dzZXIsXG4gICAgLi4uU2NyZWVuLFxuICAgIEV2ZW50c09uLFxuICAgIEV2ZW50c09uY2UsXG4gICAgRXZlbnRzT25NdWx0aXBsZSxcbiAgICBFdmVudHNFbWl0LFxuICAgIEV2ZW50c09mZixcbiAgICAvLyBFbnZpcm9ubWVudCxcbiAgICBTaG93LFxuICAgIEhpZGUsXG4gICAgUXVpdCxcbn1cblxuLy8gUHJvY2VzcyB0aGUgZXhwZWN0ZWQgcnVudGltZSBjb25maWcgZnJvbSB0aGUgYmFja2VuZFxuaWYoIHdpbmRvdy53YWlsc19jb25maWcgKSB7XG4gICAgd2luZG93SUQgPSB3aW5kb3cud2FpbHNfY29uZmlnLndpbmRvd0lEO1xuICAgIHdpbmRvdy53YWlsc19jb25maWcgPSBudWxsO1xufVxuXG5pZiAoREVCVUcpIHtcbiAgICBjb25zb2xlLmxvZyhcIldhaWxzIHYzLjAuMCBEZWJ1ZyBNb2RlIEVuYWJsZWRcIik7XG59XG5cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7O0FBaUJBLEdBQUMsV0FBWTtBQUNaLFdBQU8sY0FBYyxDQUFDLFlBQVk7QUFFakMsTUFBcUIsT0FBTyxPQUFPLGdCQUFnQixNQUFNLFlBQVksT0FBTztBQUFBLElBQzdFO0FBQUEsRUFDRCxHQUFHOzs7QUNYSSxNQUFNLFlBQVksQ0FBQztBQU8xQixXQUFTLGVBQWU7QUFDdkIsUUFBSSxRQUFRLElBQUksWUFBWSxDQUFDO0FBQzdCLFdBQU8sT0FBTyxPQUFPLGdCQUFnQixLQUFLLEVBQUU7QUFBQSxFQUM3QztBQVFBLFdBQVMsY0FBYztBQUN0QixXQUFPLEtBQUssT0FBTyxJQUFJO0FBQUEsRUFDeEI7QUFHQSxNQUFJO0FBQ0osTUFBSSxPQUFPLFFBQVE7QUFDbEIsaUJBQWE7QUFBQSxFQUNkLE9BQU87QUFDTixpQkFBYTtBQUFBLEVBQ2Q7QUFpQk8sV0FBUyxLQUFLLE1BQU0sTUFBTSxTQUFTO0FBR3pDLFFBQUksV0FBVyxNQUFNO0FBQ3BCLGdCQUFVO0FBQUEsSUFDWDtBQUVBLFFBQUlBLFlBQVcsT0FBTyxNQUFNLE9BQU8sR0FBRztBQUd0QyxXQUFPLElBQUksUUFBUSxTQUFVLFNBQVMsUUFBUTtBQUc3QyxVQUFJO0FBQ0osU0FBRztBQUNGLHFCQUFhLE9BQU8sTUFBTSxXQUFXO0FBQUEsTUFDdEMsU0FBUyxVQUFVO0FBRW5CLFVBQUk7QUFFSixVQUFJLFVBQVUsR0FBRztBQUNoQix3QkFBZ0IsV0FBVyxXQUFZO0FBQ3RDLGlCQUFPLE1BQU0sYUFBYSxPQUFPLDZCQUE2QixVQUFVLENBQUM7QUFBQSxRQUMxRSxHQUFHLE9BQU87QUFBQSxNQUNYO0FBR0EsZ0JBQVUsY0FBYztBQUFBLFFBQ3ZCO0FBQUEsUUFDQTtBQUFBLFFBQ0E7QUFBQSxN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 diff --git a/exp/internal/runtime/runtime_debug_desktop_windows.js b/exp/internal/runtime/runtime_debug_desktop_windows.js new file mode 100644 index 000000000..66edb9574 --- /dev/null +++ b/exp/internal/runtime/runtime_debug_desktop_windows.js @@ -0,0 +1,420 @@ +(() => { + var __defProp = Object.defineProperty; + var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); + }; + + // desktop/ipc.js + (function() { + window.WailsInvoke = (message) => { + window.chrome.webview.postMessage(message); + }; + })(); + + // desktop/calls.js + var callbacks = {}; + function cryptoRandom() { + var array = new Uint32Array(1); + return window.crypto.getRandomValues(array)[0]; + } + function basicRandom() { + return Math.random() * 9007199254740991; + } + var randomFunc; + if (window.crypto) { + randomFunc = cryptoRandom; + } else { + randomFunc = basicRandom; + } + function Call(name, args, timeout) { + if (timeout == null) { + timeout = 0; + } + let windowID2 = window.wails.window.ID(); + return new Promise(function(resolve, reject) { + var callbackID; + do { + callbackID = name + "-" + randomFunc(); + } while (callbacks[callbackID]); + var timeoutHandle; + if (timeout > 0) { + timeoutHandle = setTimeout(function() { + reject(Error("Call to " + name + " timed out. Request ID: " + callbackID)); + }, timeout); + } + callbacks[callbackID] = { + timeoutHandle, + reject, + resolve + }; + try { + const payload = { + name, + args, + callbackID, + windowID: windowID2 + }; + window.WailsInvoke("C" + JSON.stringify(payload)); + } catch (e) { + console.error(e); + } + }); + } + window.ObfuscatedCall = (id, args, timeout) => { + if (timeout == null) { + timeout = 0; + } + return new Promise(function(resolve, reject) { + var callbackID; + do { + callbackID = id + "-" + randomFunc(); + } while (callbacks[callbackID]); + var timeoutHandle; + if (timeout > 0) { + timeoutHandle = setTimeout(function() { + reject(Error("Call to method " + id + " timed out. Request ID: " + callbackID)); + }, timeout); + } + callbacks[callbackID] = { + timeoutHandle, + reject, + resolve + }; + try { + const payload = { + id, + args, + callbackID, + windowID: window.wails.window.ID() + }; + window.WailsInvoke("c" + JSON.stringify(payload)); + } catch (e) { + console.error(e); + } + }); + }; + function Callback(incomingMessage) { + let message; + try { + message = JSON.parse(incomingMessage); + } catch (e) { + const error = `Invalid JSON passed to callback: ${e.message}. Message: ${incomingMessage}`; + runtime.LogDebug(error); + throw new Error(error); + } + let callbackID = message.callbackid; + let callbackData = callbacks[callbackID]; + if (!callbackData) { + const error = `Callback '${callbackID}' not registered!!!`; + console.error(error); + throw new Error(error); + } + clearTimeout(callbackData.timeoutHandle); + delete callbacks[callbackID]; + if (message.error) { + callbackData.reject(message.error); + } else { + callbackData.resolve(message.result); + } + } + + // desktop/events.js + var eventListeners = {}; + function notifyListeners(eventData) { + let eventName = eventData.name; + if (eventListeners[eventName]) { + const newEventListenerList = eventListeners[eventName].slice(); + for (let count = 0; count < eventListeners[eventName].length; count += 1) { + const listener = eventListeners[eventName][count]; + let data = eventData.data; + const destroy = listener.Callback(data); + if (destroy) { + newEventListenerList.splice(count, 1); + } + } + if (newEventListenerList.length === 0) { + removeListener(eventName); + } else { + eventListeners[eventName] = newEventListenerList; + } + } + } + function EventsNotify(notifyMessage) { + let message; + try { + message = JSON.parse(notifyMessage); + } catch (e) { + const error = "Invalid JSON passed to Notify: " + notifyMessage; + throw new Error(error); + } + notifyListeners(message); + } + function removeListener(eventName) { + delete eventListeners[eventName]; + window.WailsInvoke("EX" + eventName); + } + + // desktop/bindings.js + window.go = {}; + function SetBindings(bindingsMap) { + try { + bindingsMap = JSON.parse(bindingsMap); + } catch (e) { + console.error(e); + } + window.go = window.go || {}; + Object.keys(bindingsMap).forEach((packageName) => { + window.go[packageName] = window.go[packageName] || {}; + Object.keys(bindingsMap[packageName]).forEach((structName) => { + window.go[packageName][structName] = window.go[packageName][structName] || {}; + Object.keys(bindingsMap[packageName][structName]).forEach((methodName) => { + window.go[packageName][structName][methodName] = function() { + let timeout = 0; + function dynamic() { + const args = [].slice.call(arguments); + return Call([packageName, structName, methodName].join("."), args, timeout); + } + dynamic.setTimeout = function(newTimeout) { + timeout = newTimeout; + }; + dynamic.getTimeout = function() { + return timeout; + }; + return dynamic; + }(); + }); + }); + }); + } + + // desktop/window.js + var window_exports = {}; + __export(window_exports, { + WindowCenter: () => WindowCenter, + WindowFullscreen: () => WindowFullscreen, + WindowGetPosition: () => WindowGetPosition, + WindowGetSize: () => WindowGetSize, + WindowHide: () => WindowHide, + WindowIsFullscreen: () => WindowIsFullscreen, + WindowIsMaximised: () => WindowIsMaximised, + WindowIsMinimised: () => WindowIsMinimised, + WindowIsNormal: () => WindowIsNormal, + WindowMaximise: () => WindowMaximise, + WindowMinimise: () => WindowMinimise, + WindowReload: () => WindowReload, + WindowReloadApp: () => WindowReloadApp, + WindowSetAlwaysOnTop: () => WindowSetAlwaysOnTop, + WindowSetBackgroundColour: () => WindowSetBackgroundColour, + WindowSetDarkTheme: () => WindowSetDarkTheme, + WindowSetLightTheme: () => WindowSetLightTheme, + WindowSetMaxSize: () => WindowSetMaxSize, + WindowSetMinSize: () => WindowSetMinSize, + WindowSetPosition: () => WindowSetPosition, + WindowSetSize: () => WindowSetSize, + WindowSetSystemDefaultTheme: () => WindowSetSystemDefaultTheme, + WindowSetTitle: () => WindowSetTitle, + WindowShow: () => WindowShow, + WindowToggleMaximise: () => WindowToggleMaximise, + WindowUnfullscreen: () => WindowUnfullscreen, + WindowUnmaximise: () => WindowUnmaximise, + WindowUnminimise: () => WindowUnminimise + }); + function WindowReload() { + window.location.reload(); + } + function WindowReloadApp() { + window.WailsInvoke("WR"); + } + function WindowSetSystemDefaultTheme() { + window.WailsInvoke("WASDT"); + } + function WindowSetLightTheme() { + window.WailsInvoke("WALT"); + } + function WindowSetDarkTheme() { + window.WailsInvoke("WADT"); + } + function WindowCenter() { + window.WailsInvoke("Wc"); + } + function WindowSetTitle(title) { + window.WailsInvoke("WT" + title); + } + function WindowFullscreen() { + window.WailsInvoke("WF"); + } + function WindowUnfullscreen() { + window.WailsInvoke("Wf"); + } + function WindowIsFullscreen() { + return Call(":wails:WindowIsFullscreen"); + } + function WindowSetSize(width, height) { + window.WailsInvoke("Ws:" + width + ":" + height); + } + function WindowGetSize() { + return Call(":wails:WindowGetSize"); + } + function WindowSetMaxSize(width, height) { + window.WailsInvoke("WZ:" + width + ":" + height); + } + 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); + } + function WindowGetPosition() { + return Call(":wails:WindowGetPos"); + } + function WindowHide() { + window.WailsInvoke("WH"); + } + function WindowShow() { + window.WailsInvoke("WS"); + } + function WindowMaximise() { + window.WailsInvoke("WM"); + } + function WindowToggleMaximise() { + window.WailsInvoke("Wt"); + } + function WindowUnmaximise() { + window.WailsInvoke("WU"); + } + function WindowIsMaximised() { + return Call(":wails:WindowIsMaximised"); + } + function WindowMinimise() { + window.WailsInvoke("Wm"); + } + function WindowUnminimise() { + window.WailsInvoke("Wu"); + } + function WindowIsMinimised() { + return Call(":wails:WindowIsMinimised"); + } + function WindowIsNormal() { + return Call(":wails:WindowIsNormal"); + } + 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); + } + + // desktop/screen.js + var screen_exports = {}; + __export(screen_exports, { + ScreenGetAll: () => ScreenGetAll + }); + function ScreenGetAll() { + return Call(":wails:ScreenGetAll"); + } + + // desktop/browser.js + var browser_exports = {}; + __export(browser_exports, { + BrowserOpenURL: () => BrowserOpenURL + }); + function BrowserOpenURL(url) { + window.WailsInvoke("BO:" + url); + } + + // desktop/log.js + var log_exports = {}; + __export(log_exports, { + LogDebug: () => LogDebug, + LogError: () => LogError, + LogFatal: () => LogFatal, + LogInfo: () => LogInfo, + LogLevel: () => LogLevel, + LogPrint: () => LogPrint, + LogTrace: () => LogTrace, + LogWarning: () => LogWarning, + SetLogLevel: () => SetLogLevel + }); + function sendLogMessage(level, message) { + window.WailsInvoke("L" + level + message); + } + function LogTrace(message) { + sendLogMessage("T", message); + } + function LogPrint(message) { + sendLogMessage("P", message); + } + function LogDebug(message) { + sendLogMessage("D", message); + } + function LogInfo(message) { + sendLogMessage("I", message); + } + function LogWarning(message) { + sendLogMessage("W", message); + } + function LogError(message) { + sendLogMessage("E", message); + } + function LogFatal(message) { + sendLogMessage("F", message); + } + function SetLogLevel(loglevel) { + sendLogMessage("S", loglevel); + } + var LogLevel = { + TRACE: 1, + DEBUG: 2, + INFO: 3, + WARNING: 4, + ERROR: 5 + }; + + // desktop/main.js + var windowID = -1; + function Quit() { + window.WailsInvoke("Q"); + } + function Show() { + window.WailsInvoke("S"); + } + function Hide() { + window.WailsInvoke("H"); + } + window.wails = { + Callback, + callbacks, + EventsNotify, + eventListeners, + SetBindings, + window: { + ID: () => { + return windowID; + } + } + }; + window.runtime = { + ...log_exports, + ...window_exports, + ...browser_exports, + ...screen_exports, + EventsOn, + EventsOnce, + EventsOnMultiple, + EventsEmit, + EventsOff, + Show, + Hide, + Quit + }; + if (window.wails_config) { + windowID = window.wails_config.windowID; + window.wails_config = null; + } + if (true) { + console.log("Wails v3.0.0 Debug Mode Enabled"); + } +})(); +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiZGVza3RvcC9pcGMuanMiLCAiZGVza3RvcC9jYWxscy5qcyIsICJkZXNrdG9wL2V2ZW50cy5qcyIsICJkZXNrdG9wL2JpbmRpbmdzLmpzIiwgImRlc2t0b3Avd2luZG93LmpzIiwgImRlc2t0b3Avc2NyZWVuLmpzIiwgImRlc2t0b3AvYnJvd3Nlci5qcyIsICJkZXNrdG9wL2xvZy5qcyIsICJkZXNrdG9wL21haW4uanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qXG4gXyAgICAgICBfXyAgICAgIF8gX19cbnwgfCAgICAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuLyoganNoaW50IGVzdmVyc2lvbjogNiAqL1xuXG4vKipcbiAqIFdhaWxzSW52b2tlIHNlbmRzIHRoZSBnaXZlbiBtZXNzYWdlIHRvIHRoZSBiYWNrZW5kXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcbiAqL1xuXG4oZnVuY3Rpb24gKCkge1xuXHR3aW5kb3cuV2FpbHNJbnZva2UgPSAobWVzc2FnZSkgPT4ge1xuXHRcdFdJTkRPV1MgJiYgd2luZG93LmNocm9tZS53ZWJ2aWV3LnBvc3RNZXNzYWdlKG1lc3NhZ2UpO1xuXHRcdChEQVJXSU4gfHwgTElOVVgpICYmIHdpbmRvdy53ZWJraXQubWVzc2FnZUhhbmRsZXJzLndhaWxzLnBvc3RNZXNzYWdlKG1lc3NhZ2UpO1xuXHR9XG59KSgpOyIsICIvKlxuIF8gICAgICAgX18gICAgICBfIF9fXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cbi8qIGpzaGludCBlc3ZlcnNpb246IDYgKi9cblxuZXhwb3J0IGNvbnN0IGNhbGxiYWNrcyA9IHt9O1xuXG4vKipcbiAqIFJldHVybnMgYSBudW1iZXIgZnJvbSB0aGUgbmF0aXZlIGJyb3dzZXIgcmFuZG9tIGZ1bmN0aW9uXG4gKlxuICogQHJldHVybnMgbnVtYmVyXG4gKi9cbmZ1bmN0aW9uIGNyeXB0b1JhbmRvbSgpIHtcblx0dmFyIGFycmF5ID0gbmV3IFVpbnQzMkFycmF5KDEpO1xuXHRyZXR1cm4gd2luZG93LmNyeXB0by5nZXRSYW5kb21WYWx1ZXMoYXJyYXkpWzBdO1xufVxuXG4vKipcbiAqIFJldHVybnMgYSBudW1iZXIgdXNpbmcgZGEgb2xkLXNrb29sIE1hdGguUmFuZG9tXG4gKiBJIGxpa2VzIHRvIGNhbGwgaXQgTE9MUmFuZG9tXG4gKlxuICogQHJldHVybnMgbnVtYmVyXG4gKi9cbmZ1bmN0aW9uIGJhc2ljUmFuZG9tKCkge1xuXHRyZXR1cm4gTWF0aC5yYW5kb20oKSAqIDkwMDcxOTkyNTQ3NDA5OTE7XG59XG5cbi8vIFBpY2sgYSByYW5kb20gbnVtYmVyIGZ1bmN0aW9uIGJhc2VkIG9uIGJyb3dzZXIgY2FwYWJpbGl0eVxudmFyIHJhbmRvbUZ1bmM7XG5pZiAod2luZG93LmNyeXB0bykge1xuXHRyYW5kb21GdW5jID0gY3J5cHRvUmFuZG9tO1xufSBlbHNlIHtcblx0cmFuZG9tRnVuYyA9IGJhc2ljUmFuZG9tO1xufVxuXG5cbi8qKlxuICogQ2FsbCBzZW5kcyBhIG1lc3NhZ2UgdG8gdGhlIGJhY2tlbmQgdG8gY2FsbCB0aGUgYmluZGluZyB3aXRoIHRoZVxuICogZ2l2ZW4gZGF0YS4gQSBwcm9taXNlIGlzIHJldHVybmVkIGFuZCB3aWxsIGJlIGNvbXBsZXRlZCB3aGVuIHRoZVxuICogYmFja2VuZCByZXNwb25kcy4gVGhpcyB3aWxsIGJlIHJlc29sdmVkIHdoZW4gdGhlIGNhbGwgd2FzIHN1Y2Nlc3NmdWxcbiAqIG9yIHJlamVjdGVkIGlmIGFuIGVycm9yIGlzIHBhc3NlZCBiYWNrLlxuICogVGhlcmUgaXMgYSB0aW1lb3V0IG1lY2hhbmlzbS4gSWYgdGhlIGNhbGwgZG9lc24ndCByZXNwb25kIGluIHRoZSBnaXZlblxuICogdGltZSAoaW4gbWlsbGlzZWNvbmRzKSB0aGVuIHRoZSBwcm9taXNlIGlzIHJlamVjdGVkLlxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gKiBAcGFyYW0ge2FueT19IGFyZ3NcbiAqIEBwYXJhbSB7bnVtYmVyPX0gdGltZW91dFxuICogQHJldHVybnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENhbGwobmFtZSwgYXJncywgdGltZW91dCkge1xuXG5cdC8vIFRpbWVvdXQgaW5maW5pdGUgYnkgZGVmYXVsdFxuXHRpZiAodGltZW91dCA9PSBudWxsKSB7XG5cdFx0dGltZW91dCA9IDA7XG5cdH1cblxuXHRsZXQgd2luZG93SUQgPSB3aW5kb3cud2FpbHMud2luZG93LklEKCk7XG5cblx0Ly8gQ3JlYXRlIGEgcHJvbWlzZVxuXHRyZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuXG5cdFx0Ly8gQ3JlYXRlIGEgdW5pcXVlIGNhbGxiYWNrSURcblx0XHR2YXIgY2FsbGJhY2tJRDtcblx0XHRkbyB7XG5cdFx0XHRjYWxsYmFja0lEID0gbmFtZSArICctJyArIHJhbmRvbUZ1bmMoKTtcblx0XHR9IHdoaWxlIChjYWxsYmFja3NbY2FsbGJhY2tJRF0pO1xuXG5cdFx0dmFyIHRpbWVvdXRIYW5kbGU7XG5cdFx0Ly8gU2V0IHRpbWVvdXRcblx0XHRpZiAodGltZW91dCA+IDApIHtcblx0XHRcdHRpbWVvdXRIYW5kbGUgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0cmVqZWN0KEVycm9yKCdDYWxsIHRvICcgKyBuYW1lICsgJyB0aW1lZCBvdXQuIFJlcXVlc3QgSUQ6ICcgKyBjYWxsYmFja0lEKSk7XG5cdFx0XHR9LCB0aW1lb3V0KTtcblx0XHR9XG5cblx0XHQvLyBTdG9yZSBjYWxsYmFja1xuXHRcdGNhbGxiYWNrc1tjYWxsYmFja0lEXSA9IHtcblx0XHRcdHRpbWVvdXRIYW5kbGU6IHRpbWVvdXRIYW5kbGUsXG5cdFx0XHRyZWplY3Q6IHJlamVjdCxcblx0XHRcdHJlc29sdmU6IHJlc29sdmVcblx0XHR9O1xuXG5cdFx0dHJ5IHtcblx0XHRcdGNvbnN0IHBheWxvYWQgPSB7XG5cdFx0XHRcdG5hbWUsXG5cdFx0XHRcdGFyZ3MsXG5cdFx0XHRcdGNhbGxiYWNrSUQsXG5cdFx0XHRcdHdpbmRvd0lELFxuXHRcdFx0fTtcblxuICAgICAgICAgICAgLy8gTWFrZSB0aGUgY2FsbFxuICAgICAgICAgICAgd2luZG93LldhaWxzSW52b2tlKCdDJyArIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbndpbmRvdy5PYmZ1c2NhdGVkQ2FsbCA9IChpZCwgYXJncywgdGltZW91dCkgPT4ge1xuXG4gICAgLy8gVGltZW91dCBpbmZpbml0ZSBieSBkZWZhdWx0XG4gICAgaWYgKHRpbWVvdXQgPT0gbnVsbCkge1xuICAgICAgICB0aW1lb3V0ID0gMDtcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgYSBwcm9taXNlXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcblxuICAgICAgICAvLyBDcmVhdGUgYSB1bmlxdWUgY2FsbGJhY2tJRFxuICAgICAgICB2YXIgY2FsbGJhY2tJRDtcbiAgICAgICAgZG8ge1xuICAgICAgICAgICAgY2FsbGJhY2tJRCA9IGlkICsgJy0nICsgcmFuZG9tRnVuYygpO1xuICAgICAgICB9IHdoaWxlIChjYWxsYmFja3NbY2FsbGJhY2tJRF0pO1xuXG4gICAgICAgIHZhciB0aW1lb3V0SGFuZGxlO1xuICAgICAgICAvLyBTZXQgdGltZW91dFxuICAgICAgICBpZiAodGltZW91dCA+IDApIHtcbiAgICAgICAgICAgIHRpbWVvdXRIYW5kbGUgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ0NhbGwgdG8gbWV0aG9kICcgKyBpZCArICcgdGltZWQgb3V0LiBSZXF1ZXN0IElEOiAnICsgY2FsbGJhY2tJRCkpO1xuICAgICAgICAgICAgfSwgdGltZW91dCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTdG9yZSBjYWxsYmFja1xuICAgICAgICBjYWxsYmFja3NbY2FsbGJhY2tJRF0gPSB7XG4gICAgICAgICAgICB0aW1lb3V0SGFuZGxlOiB0aW1lb3V0SGFuZGxlLFxuICAgICAgICAgICAgcmVqZWN0OiByZWplY3QsXG4gICAgICAgICAgICByZXNvbHZlOiByZXNvbHZlXG4gICAgICAgIH07XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSB7XG5cdFx0XHRcdGlkLFxuXHRcdFx0XHRhcmdzLFxuXHRcdFx0XHRjYWxsYmFja0lELFxuXHRcdFx0XHR3aW5kb3dJRDogd2luZG93LndhaWxzLndpbmRvdy5JRCgpLFxuXHRcdFx0fTtcblxuICAgICAgICAgICAgLy8gTWFrZSB0aGUgY2FsbFxuICAgICAgICAgICAgd2luZG93LldhaWxzSW52b2tlKCdjJyArIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfSk7XG59O1xuXG5cbi8qKlxuICogQ2FsbGVkIGJ5IHRoZSBiYWNrZW5kIHRvIHJldHVybiBkYXRhIHRvIGEgcHJldmlvdXNseSBjYWxsZWRcbiAqIGJpbmRpbmcgaW52b2NhdGlvblxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBpbmNvbWluZ01lc3NhZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENhbGxiYWNrKGluY29taW5nTWVzc2FnZSkge1xuXHQvLyBQYXJzZSB0aGUgbWVzc2FnZVxuXHRsZXQgbWVzc2FnZTtcblx0dHJ5IHtcblx0XHRtZXNzYWdlID0gSlNPTi5wYXJzZShpbmNvbWluZ01lc3NhZ2UpO1xuXHR9IGNhdGNoIChlKSB7XG5cdFx0Y29uc3QgZXJyb3IgPSBgSW52YWxpZCBKU09OIHBhc3NlZCB0byBjYWxsYmFjazogJHtlLm1lc3NhZ2V9LiBNZXNzYWdlOiAke2luY29taW5nTWVzc2FnZX1gO1xuXHRcdHJ1bnRpbWUuTG9nRGVidWcoZXJyb3IpO1xuXHRcdHRocm93IG5ldyBFcnJvcihlcnJvcik7XG5cdH1cblx0bGV0IGNhbGxiYWNrSUQgPSBtZXNzYWdlLmNhbGxiYWNraWQ7XG5cdGxldCBjYWxsYmFja0RhdGEgPSBjYWxsYmFja3NbY2FsbGJhY2tJRF07XG5cdGlmICghY2FsbGJhY2tEYXRhKSB7XG5cdFx0Y29uc3QgZXJyb3IgPSBgQ2FsbGJhY2sgJyR7Y2FsbGJhY2tJRH0nIG5vdCByZWdpc3RlcmVkISEhYDtcblx0XHRjb25zb2xlLmVycm9yKGVycm9yKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHRcdHRocm93IG5ldyBFcnJvcihlcnJvcik7XG5cdH1cblx0Y2xlYXJUaW1lb3V0KGNhbGxiYWNrRGF0YS50aW1lb3V0SGFuZGxlKTtcblxuXHRkZWxldGUgY2FsbGJhY2tzW2NhbGxiYWNrSURdO1xuXG5cdGlmIChtZXNzYWdlLmVycm9yKSB7XG5cdFx0Y2FsbGJhY2tEYXRhLnJlamVjdChtZXNzYWdlLmVycm9yKTtcblx0fSBlbHNlIHtcblx0XHRjYWxsYmFja0RhdGEucmVzb2x2ZShtZXNzYWdlLnJlc3VsdCk7XG5cdH1cbn1cbiIsICIvKlxuIF8gICAgICAgX18gICAgICBfIF9fXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cbi8qIGpzaGludCBlc3ZlcnNpb246IDYgKi9cblxuLy8gRGVmaW5lcyBhIHNpbmdsZSBsaXN0ZW5lciB3aXRoIGEgbWF4aW11bSBudW1iZXIgb2YgdGltZXMgdG8gY2FsbGJhY2tcblxuLyoqXG4gKiBUaGUgTGlzdGVuZXIgY2xhc3MgZGVmaW5lcyBhIGxpc3RlbmVyISA6LSlcbiAqXG4gKiBAY2xhc3MgTGlzdGVuZXJcbiAqL1xuY2xhc3MgTGlzdGVuZXIge1xuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgTGlzdGVuZXIuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG1heENhbGxiYWNrc1xuICAgICAqIEBtZW1iZXJvZiBMaXN0ZW5lclxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG1heENhbGxiYWNrcykge1xuICAgICAgICB0aGlzLmV2ZW50TmFtZSA9IGV2ZW50TmFtZTtcbiAgICAgICAgLy8gRGVmYXVsdCBvZiAtMSBtZWFucyBpbmZpbml0ZVxuICAgICAgICB0aGlzLm1heENhbGxiYWNrcyA9IG1heENhbGxiYWNrcyB8fCAtMTtcbiAgICAgICAgLy8gQ2FsbGJhY2sgaW52b2tlcyB0aGUgY2FsbGJhY2sgd2l0aCB0aGUgZ2l2ZW4gZGF0YVxuICAgICAgICAvLyBSZXR1cm5zIHRydWUgaWYgdGhpcyBsaXN0ZW5lciBzaG91bGQgYmUgZGVzdHJveWVkXG4gICAgICAgIHRoaXMuQ2FsbGJhY2sgPSAoZGF0YSkgPT4ge1xuICAgICAgICAgICAgY2FsbGJhY2suYXBwbHkobnVsbCwgZGF0YSk7XG4gICAgICAgICAgICAvLyBJZiBtYXhDYWxsYmFja3MgaXMgaW5maW5pdGUsIHJldHVybiBmYWxzZSAoZG8gbm90IGRlc3Ryb3kpXG4gICAgICAgICAgICBpZiAodGhpcy5tYXhDYWxsYmFja3MgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRGVjcmVtZW50IG1heENhbGxiYWNrcy4gUmV0dXJuIHRydWUgaWYgbm93IDAsIG90aGVyd2lzZSBmYWxzZVxuICAgICAgICAgICAgdGhpcy5tYXhDYWxsYmFja3MgLT0gMTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1heENhbGxiYWNrcyA9PT0gMDtcbiAgICAgICAgfTtcbiAgICB9XG59XG5cbmV4cG9ydCBjb25zdCBldmVudExpc3RlbmVycyA9IHt9O1xuXG4vKipcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBgbWF4Q2FsbGJhY2tzYCB0aW1lcyBiZWZvcmUgYmVpbmcgZGVzdHJveWVkXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhDYWxsYmFja3NcbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gQSBmdW5jdGlvbiB0byBjYW5jZWwgdGhlIGxpc3RlbmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG1heENhbGxiYWNrcykge1xuICAgIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0gPSBldmVudExpc3RlbmVyc1tldmVudE5hbWVdIHx8IFtdO1xuICAgIGNvbnN0IHRoaXNMaXN0ZW5lciA9IG5ldyBMaXN0ZW5lcihldmVudE5hbWUsIGNhbGxiYWNrLCBtYXhDYWxsYmFja3MpO1xuICAgIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0ucHVzaCh0aGlzTGlzdGVuZXIpO1xuICAgIHJldHVybiAoKSA9PiBsaXN0ZW5lck9mZih0aGlzTGlzdGVuZXIpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBldmVyeSB0aW1lIHRoZSBldmVudCBpcyBlbWl0dGVkXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gQSBmdW5jdGlvbiB0byBjYW5jZWwgdGhlIGxpc3RlbmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbihldmVudE5hbWUsIGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIEV2ZW50c09uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgLTEpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBvbmNlIHRoZW4gZGVzdHJveWVkXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gQSBmdW5jdGlvbiB0byBjYW5jZWwgdGhlIGxpc3RlbmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbmNlKGV2ZW50TmFtZSwgY2FsbGJhY2spIHtcbiAgICByZXR1cm4gRXZlbnRzT25NdWx0aXBsZShldmVudE5hbWUsIGNhbGxiYWNrLCAxKTtcbn1cblxuZnVuY3Rpb24gbm90aWZ5TGlzdGVuZXJzKGV2ZW50RGF0YSkge1xuXG4gICAgLy8gR2V0IHRoZSBldmVudCBuYW1lXG4gICAgbGV0IGV2ZW50TmFtZSA9IGV2ZW50RGF0YS5uYW1lO1xuXG4gICAgLy8gQ2hlY2sgaWYgd2UgaGF2ZSBhbnkgbGlzdGVuZXJzIGZvciB0aGlzIGV2ZW50XG4gICAgaWYgKGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0pIHtcblxuICAgICAgICAvLyBLZWVwIGEgbGlzdCBvZiBsaXN0ZW5lciBpbmRleGVzIHRvIGRlc3Ryb3lcbiAgICAgICAgY29uc3QgbmV3RXZlbnRMaXN0ZW5lckxpc3QgPSBldmVudExpc3RlbmVyc1tldmVudE5hbWVdLnNsaWNlKCk7XG5cbiAgICAgICAgLy8gSXRlcmF0ZSBsaXN0ZW5lcnNcbiAgICAgICAgZm9yIChsZXQgY291bnQgPSAwOyBjb3VudCA8IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0ubGVuZ3RoOyBjb3VudCArPSAxKSB7XG5cbiAgICAgICAgICAgIC8vIEdldCBuZXh0IGxpc3RlbmVyXG4gICAgICAgICAgICBjb25zdCBsaXN0ZW5lciA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV1bY291bnRdO1xuXG4gICAgICAgICAgICBsZXQgZGF0YSA9IGV2ZW50RGF0YS5kYXRhO1xuXG4gICAgICAgICAgICAvLyBEbyB0aGUgY2FsbGJhY2tcbiAgICAgICAgICAgIGNvbnN0IGRlc3Ryb3kgPSBsaXN0ZW5lci5DYWxsYmFjayhkYXRhKTtcbiAgICAgICAgICAgIGlmIChkZXN0cm95KSB7XG4gICAgICAgICAgICAgICAgLy8gaWYgdGhlIGxpc3RlbmVyIGluZGljYXRlZCB0byBkZXN0cm95IGl0c2VsZiwgYWRkIGl0IHRvIHRoZSBkZXN0cm95IGxpc3RcbiAgICAgICAgICAgICAgICBuZXdFdmVudExpc3RlbmVyTGlzdC5zcGxpY2UoY291bnQsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gVXBkYXRlIGNhbGxiYWNrcyB3aXRoIG5ldyBsaXN0IG9mIGxpc3RlbmVyc1xuICAgICAgICBpZiAobmV3RXZlbnRMaXN0ZW5lckxpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZW1vdmVMaXN0ZW5lcihldmVudE5hbWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSA9IG5ld0V2ZW50TGlzdGVuZXJMaXN0O1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqIE5vdGlmeSBpbmZvcm1zIGZyb250ZW5kIGxpc3RlbmVycyB0aGF0IGFuIGV2ZW50IHdhcyBlbWl0dGVkIHdpdGggdGhlIGdpdmVuIGRhdGFcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbm90aWZ5TWVzc2FnZSAtIGVuY29kZWQgbm90aWZpY2F0aW9uIG1lc3NhZ2VcblxuICovXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzTm90aWZ5KG5vdGlmeU1lc3NhZ2UpIHtcbiAgICAvLyBQYXJzZSB0aGUgbWVzc2FnZVxuICAgIGxldCBtZXNzYWdlO1xuICAgIHRyeSB7XG4gICAgICAgIG1lc3NhZ2UgPSBKU09OLnBhcnNlKG5vdGlmeU1lc3NhZ2UpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc3QgZXJyb3IgPSAnSW52YWxpZCBKU09OIHBhc3NlZCB0byBOb3RpZnk6ICcgKyBub3RpZnlNZXNzYWdlO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3IpO1xuICAgIH1cbiAgICBub3RpZnlMaXN0ZW5lcnMobWVzc2FnZSk7XG59XG5cbi8qKlxuICogRW1pdCBhbiBldmVudCB3aXRoIHRoZSBnaXZlbiBuYW1lIGFuZCBkYXRhXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICovXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzRW1pdChldmVudE5hbWUpIHtcblxuICAgIGNvbnN0IHBheWxvYWQgPSB7XG4gICAgICAgIG5hbWU6IGV2ZW50TmFtZSxcbiAgICAgICAgZGF0YTogW10uc2xpY2UuYXBwbHkoYXJndW1lbnRzKS5zbGljZSgxKSxcbiAgICB9O1xuXG4gICAgLy8gTm90aWZ5IEpTIGxpc3RlbmVyc1xuICAgIG5vdGlmeUxpc3RlbmVycyhwYXlsb2FkKTtcblxuICAgIC8vIE5vdGlmeSBHbyBsaXN0ZW5lcnNcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ0VFJyArIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcbn1cblxuZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIoZXZlbnROYW1lKSB7XG4gICAgLy8gUmVtb3ZlIGxvY2FsIGxpc3RlbmVyc1xuICAgIGRlbGV0ZSBldmVudExpc3RlbmVyc1tldmVudE5hbWVdO1xuXG4gICAgLy8gTm90aWZ5IEdvIGxpc3RlbmVyc1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnRVgnICsgZXZlbnROYW1lKTtcbn1cblxuLyoqXG4gKiBPZmYgdW5yZWdpc3RlcnMgYSBsaXN0ZW5lciBwcmV2aW91c2x5IHJlZ2lzdGVyZWQgd2l0aCBPbixcbiAqIG9wdGlvbmFsbHkgbXVsdGlwbGUgbGlzdGVuZXJlcyBjYW4gYmUgdW5yZWdpc3RlcmVkIHZpYSBgYWRkaXRpb25hbEV2ZW50TmFtZXNgXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtICB7Li4uc3RyaW5nfSBhZGRpdGlvbmFsRXZlbnROYW1lc1xuICovXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzT2ZmKGV2ZW50TmFtZSwgLi4uYWRkaXRpb25hbEV2ZW50TmFtZXMpIHtcbiAgICByZW1vdmVMaXN0ZW5lcihldmVudE5hbWUpXG5cbiAgICBpZiAoYWRkaXRpb25hbEV2ZW50TmFtZXMubGVuZ3RoID4gMCkge1xuICAgICAgICBhZGRpdGlvbmFsRXZlbnROYW1lcy5mb3JFYWNoKGV2ZW50TmFtZSA9PiB7XG4gICAgICAgICAgICByZW1vdmVMaXN0ZW5lcihldmVudE5hbWUpXG4gICAgICAgIH0pXG4gICAgfVxufVxuXG4vKipcbiAqIE9mZiB1bnJlZ2lzdGVycyBhbGwgZXZlbnQgbGlzdGVuZXJzIHByZXZpb3VzbHkgcmVnaXN0ZXJlZCB3aXRoIE9uXG4gKi9cbiBleHBvcnQgZnVuY3Rpb24gRXZlbnRzT2ZmQWxsKCkge1xuICAgIGNvbnN0IGV2ZW50TmFtZXMgPSBPYmplY3Qua2V5cyhldmVudExpc3RlbmVycyk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgIT09IGV2ZW50TmFtZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcmVtb3ZlTGlzdGVuZXIoZXZlbnROYW1lc1tpXSk7XG4gICAgfVxufVxuXG4vKipcbiAqIGxpc3RlbmVyT2ZmIHVucmVnaXN0ZXJzIGEgbGlzdGVuZXIgcHJldmlvdXNseSByZWdpc3RlcmVkIHdpdGggRXZlbnRzT25cbiAqXG4gKiBAcGFyYW0ge0xpc3RlbmVyfSBsaXN0ZW5lclxuICovXG4gZnVuY3Rpb24gbGlzdGVuZXJPZmYobGlzdGVuZXIpIHtcbiAgICBjb25zdCBldmVudE5hbWUgPSBsaXN0ZW5lci5ldmVudE5hbWU7XG4gICAgLy8gUmVtb3ZlIGxvY2FsIGxpc3RlbmVyXG4gICAgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0uZmlsdGVyKGwgPT4gbCAhPT0gbGlzdGVuZXIpO1xuXG4gICAgLy8gQ2xlYW4gdXAgaWYgdGhlcmUgYXJlIG5vIGV2ZW50IGxpc3RlbmVycyBsZWZ0XG4gICAgaWYgKGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0ubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJlbW92ZUxpc3RlbmVyKGV2ZW50TmFtZSk7XG4gICAgfVxufVxuIiwgIi8qXG4gXyAgICAgICBfXyAgICAgIF8gX18gICAgXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gICkgXG58X18vfF9fL1xcX18sXy9fL18vX19fXy8gIFxuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cbi8qIGpzaGludCBlc3ZlcnNpb246IDYgKi9cblxuaW1wb3J0IHtDYWxsfSBmcm9tICcuL2NhbGxzJztcblxuLy8gVGhpcyBpcyB3aGVyZSB3ZSBiaW5kIGdvIG1ldGhvZCB3cmFwcGVyc1xud2luZG93LmdvID0ge307XG5cbmV4cG9ydCBmdW5jdGlvbiBTZXRCaW5kaW5ncyhiaW5kaW5nc01hcCkge1xuXHR0cnkge1xuXHRcdGJpbmRpbmdzTWFwID0gSlNPTi5wYXJzZShiaW5kaW5nc01hcCk7XG5cdH0gY2F0Y2ggKGUpIHtcblx0XHRjb25zb2xlLmVycm9yKGUpO1xuXHR9XG5cblx0Ly8gSW5pdGlhbGlzZSB0aGUgYmluZGluZ3MgbWFwXG5cdHdpbmRvdy5nbyA9IHdpbmRvdy5nbyB8fCB7fTtcblxuXHQvLyBJdGVyYXRlIHBhY2thZ2UgbmFtZXNcblx0T2JqZWN0LmtleXMoYmluZGluZ3NNYXApLmZvckVhY2goKHBhY2thZ2VOYW1lKSA9PiB7XG5cblx0XHQvLyBDcmVhdGUgaW5uZXIgbWFwIGlmIGl0IGRvZXNuJ3QgZXhpc3Rcblx0XHR3aW5kb3cuZ29bcGFja2FnZU5hbWVdID0gd2luZG93LmdvW3BhY2thZ2VOYW1lXSB8fCB7fTtcblxuXHRcdC8vIEl0ZXJhdGUgc3RydWN0IG5hbWVzXG5cdFx0T2JqZWN0LmtleXMoYmluZGluZ3NNYXBbcGFja2FnZU5hbWVdKS5mb3JFYWNoKChzdHJ1Y3ROYW1lKSA9PiB7XG5cblx0XHRcdC8vIENyZWF0ZSBpbm5lciBtYXAgaWYgaXQgZG9lc24ndCBleGlzdFxuXHRcdFx0d2luZG93LmdvW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXSA9IHdpbmRvdy5nb1twYWNrYWdlTmFtZV1bc3RydWN0TmFtZV0gfHwge307XG5cblx0XHRcdE9iamVjdC5rZXlzKGJpbmRpbmdzTWFwW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXSkuZm9yRWFjaCgobWV0aG9kTmFtZSkgPT4ge1xuXG5cdFx0XHRcdHdpbmRvdy5nb1twYWNrYWdlTmFtZV1bc3RydWN0TmFtZV1bbWV0aG9kTmFtZV0gPSBmdW5jdGlvbiAoKSB7XG5cblx0XHRcdFx0XHQvLyBObyB0aW1lb3V0IGJ5IGRlZmF1bHRcblx0XHRcdFx0XHRsZXQgdGltZW91dCA9IDA7XG5cblx0XHRcdFx0XHQvLyBBY3R1YWwgZnVuY3Rpb25cblx0XHRcdFx0XHRmdW5jdGlvbiBkeW5hbWljKCkge1xuXHRcdFx0XHRcdFx0Y29uc3QgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcblx0XHRcdFx0XHRcdHJldHVybiBDYWxsKFtwYWNrYWdlTmFtZSwgc3RydWN0TmFtZSwgbWV0aG9kTmFtZV0uam9pbignLicpLCBhcmdzLCB0aW1lb3V0KTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBBbGxvdyBzZXR0aW5nIHRpbWVvdXQgdG8gZnVuY3Rpb25cblx0XHRcdFx0XHRkeW5hbWljLnNldFRpbWVvdXQgPSBmdW5jdGlvbiAobmV3VGltZW91dCkge1xuXHRcdFx0XHRcdFx0dGltZW91dCA9IG5ld1RpbWVvdXQ7XG5cdFx0XHRcdFx0fTtcblxuXHRcdFx0XHRcdC8vIEFsbG93IGdldHRpbmcgdGltZW91dCB0byBmdW5jdGlvblxuXHRcdFx0XHRcdGR5bmFtaWMuZ2V0VGltZW91dCA9IGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRcdHJldHVybiB0aW1lb3V0O1xuXHRcdFx0XHRcdH07XG5cblx0XHRcdFx0XHRyZXR1cm4gZHluYW1pYztcblx0XHRcdFx0fSgpO1xuXHRcdFx0fSk7XG5cdFx0fSk7XG5cdH0pO1xufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cblxuaW1wb3J0IHtDYWxsfSBmcm9tIFwiLi9jYWxsc1wiO1xuXG5leHBvcnQgZnVuY3Rpb24gV2luZG93UmVsb2FkKCkge1xuICAgIHdpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1JlbG9hZEFwcCgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dSJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRTeXN0ZW1EZWZhdWx0VGhlbWUoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXQVNEVCcpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0TGlnaHRUaGVtZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dBTFQnKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldERhcmtUaGVtZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dBRFQnKTtcbn1cblxuLyoqXG4gKiBQbGFjZSB0aGUgd2luZG93IGluIHRoZSBjZW50ZXIgb2YgdGhlIHNjcmVlblxuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0NlbnRlcigpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1djJyk7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgd2luZG93IHRpdGxlXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHRpdGxlXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRUaXRsZSh0aXRsZSkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV1QnICsgdGl0bGUpO1xufVxuXG4vKipcbiAqIE1ha2VzIHRoZSB3aW5kb3cgZ28gZnVsbHNjcmVlblxuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0Z1bGxzY3JlZW4oKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXRicpO1xufVxuXG4vKipcbiAqIFJldmVydHMgdGhlIHdpbmRvdyBmcm9tIGZ1bGxzY3JlZW5cbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dVbmZ1bGxzY3JlZW4oKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXZicpO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIHN0YXRlIG9mIHRoZSB3aW5kb3csIGkuZS4gd2hldGhlciB0aGUgd2luZG93IGlzIGluIGZ1bGwgc2NyZWVuIG1vZGUgb3Igbm90LlxuICpcbiAqIEBleHBvcnRcbiAqIEByZXR1cm4ge1Byb21pc2U8Ym9vbGVhbj59IFRoZSBzdGF0ZSBvZiB0aGUgd2luZG93XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dJc0Z1bGxzY3JlZW4oKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6V2luZG93SXNGdWxsc2NyZWVuXCIpO1xufVxuXG4vKipcbiAqIFNldCB0aGUgU2l6ZSBvZiB0aGUgd2luZG93XG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRTaXplKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dzOicgKyB3aWR0aCArICc6JyArIGhlaWdodCk7XG59XG5cbi8qKlxuICogR2V0IHRoZSBTaXplIG9mIHRoZSB3aW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcmV0dXJuIHtQcm9taXNlPHt3OiBudW1iZXIsIGg6IG51bWJlcn0+fSBUaGUgc2l6ZSBvZiB0aGUgd2luZG93XG5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0dldFNpemUoKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6V2luZG93R2V0U2l6ZVwiKTtcbn1cblxuLyoqXG4gKiBTZXQgdGhlIG1heGltdW0gc2l6ZSBvZiB0aGUgd2luZG93XG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRNYXhTaXplKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1daOicgKyB3aWR0aCArICc6JyArIGhlaWdodCk7XG59XG5cbi8qKlxuICogU2V0IHRoZSBtaW5pbXVtIHNpemUgb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aFxuICogQHBhcmFtIHtudW1iZXJ9IGhlaWdodFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0TWluU2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXejonICsgd2lkdGggKyAnOicgKyBoZWlnaHQpO1xufVxuXG5cblxuLyoqXG4gKiBTZXQgdGhlIHdpbmRvdyBBbHdheXNPblRvcCBvciBub3Qgb24gdG9wXG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0QWx3YXlzT25Ub3AoYikge1xuXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXQVRQOicgKyAoYiA/ICcxJyA6ICcwJykpO1xufVxuXG5cblxuXG4vKipcbiAqIFNldCB0aGUgUG9zaXRpb24gb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7bnVtYmVyfSB4XG4gKiBAcGFyYW0ge251bWJlcn0geVxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0UG9zaXRpb24oeCwgeSkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3A6JyArIHggKyAnOicgKyB5KTtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIFBvc2l0aW9uIG9mIHRoZSB3aW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcmV0dXJuIHtQcm9taXNlPHt4OiBudW1iZXIsIHk6IG51bWJlcn0+fSBUaGUgcG9zaXRpb24gb2YgdGhlIHdpbmRvd1xuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93R2V0UG9zaXRpb24oKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6V2luZG93R2V0UG9zXCIpO1xufVxuXG4vKipcbiAqIEhpZGUgdGhlIFdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0hpZGUoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXSCcpO1xufVxuXG4vKipcbiAqIFNob3cgdGhlIFdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1Nob3coKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXUycpO1xufVxuXG4vKipcbiAqIE1heGltaXNlIHRoZSBXaW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dNYXhpbWlzZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dNJyk7XG59XG5cbi8qKlxuICogVG9nZ2xlIHRoZSBNYXhpbWlzZSBvZiB0aGUgV2luZG93XG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93VG9nZ2xlTWF4aW1pc2UoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXdCcpO1xufVxuXG4vKipcbiAqIFVubWF4aW1pc2UgdGhlIFdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1VubWF4aW1pc2UoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXVScpO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIHN0YXRlIG9mIHRoZSB3aW5kb3csIGkuZS4gd2hldGhlciB0aGUgd2luZG93IGlzIG1heGltaXNlZCBvciBub3QuXG4gKlxuICogQGV4cG9ydFxuICogQHJldHVybiB7UHJvbWlzZTxib29sZWFuPn0gVGhlIHN0YXRlIG9mIHRoZSB3aW5kb3dcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0lzTWF4aW1pc2VkKCkge1xuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOldpbmRvd0lzTWF4aW1pc2VkXCIpO1xufVxuXG4vKipcbiAqIE1pbmltaXNlIHRoZSBXaW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dNaW5pbWlzZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dtJyk7XG59XG5cbi8qKlxuICogVW5taW5pbWlzZSB0aGUgV2luZG93XG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93VW5taW5pbWlzZSgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1d1Jyk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgc3RhdGUgb2YgdGhlIHdpbmRvdywgaS5lLiB3aGV0aGVyIHRoZSB3aW5kb3cgaXMgbWluaW1pc2VkIG9yIG5vdC5cbiAqXG4gKiBAZXhwb3J0XG4gKiBAcmV0dXJuIHtQcm9taXNlPGJvb2xlYW4+fSBUaGUgc3RhdGUgb2YgdGhlIHdpbmRvd1xuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93SXNNaW5pbWlzZWQoKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6V2luZG93SXNNaW5pbWlzZWRcIik7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgc3RhdGUgb2YgdGhlIHdpbmRvdywgaS5lLiB3aGV0aGVyIHRoZSB3aW5kb3cgaXMgbm9ybWFsIG9yIG5vdC5cbiAqXG4gKiBAZXhwb3J0XG4gKiBAcmV0dXJuIHtQcm9taXNlPGJvb2xlYW4+fSBUaGUgc3RhdGUgb2YgdGhlIHdpbmRvd1xuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93SXNOb3JtYWwoKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6V2luZG93SXNOb3JtYWxcIik7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgYmFja2dyb3VuZCBjb2xvdXIgb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7bnVtYmVyfSBSIFJlZFxuICogQHBhcmFtIHtudW1iZXJ9IEcgR3JlZW5cbiAqIEBwYXJhbSB7bnVtYmVyfSBCIEJsdWVcbiAqIEBwYXJhbSB7bnVtYmVyfSBBIEFscGhhXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRCYWNrZ3JvdW5kQ29sb3VyKFIsIEcsIEIsIEEpIHtcbiAgICBsZXQgcmdiYSA9IEpTT04uc3RyaW5naWZ5KHtyOiBSIHx8IDAsIGc6IEcgfHwgMCwgYjogQiB8fCAwLCBhOiBBIHx8IDI1NX0pO1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3I6JyArIHJnYmEpO1xufVxuXG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cblxuXG5pbXBvcnQge0NhbGx9IGZyb20gXCIuL2NhbGxzXCI7XG5cblxuLyoqXG4gKiBHZXRzIHRoZSBhbGwgc2NyZWVucy4gQ2FsbCB0aGlzIGFuZXcgZWFjaCB0aW1lIHlvdSB3YW50IHRvIHJlZnJlc2ggZGF0YSBmcm9tIHRoZSB1bmRlcmx5aW5nIHdpbmRvd2luZyBzeXN0ZW0uXG4gKiBAZXhwb3J0XG4gKiBAdHlwZWRlZiB7aW1wb3J0KCcuLi93cmFwcGVyL3J1bnRpbWUnKS5TY3JlZW59IFNjcmVlblxuICogQHJldHVybiB7UHJvbWlzZTx7U2NyZWVuW119Pn0gVGhlIHNjcmVlbnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNjcmVlbkdldEFsbCgpIHtcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpTY3JlZW5HZXRBbGxcIik7XG59XG4iLCAiLyoqXG4gKiBAZGVzY3JpcHRpb246IFVzZSB0aGUgc3lzdGVtIGRlZmF1bHQgYnJvd3NlciB0byBvcGVuIHRoZSB1cmxcbiAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gQnJvd3Nlck9wZW5VUkwodXJsKSB7XG4gIHdpbmRvdy5XYWlsc0ludm9rZSgnQk86JyArIHVybCk7XG59IiwgIi8qXG4gXyAgICAgICBfXyAgICAgIF8gX19cbnwgfCAgICAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA2ICovXG5cbi8qKlxuICogU2VuZHMgYSBsb2cgbWVzc2FnZSB0byB0aGUgYmFja2VuZCB3aXRoIHRoZSBnaXZlbiBsZXZlbCArIG1lc3NhZ2VcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbGV2ZWxcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmZ1bmN0aW9uIHNlbmRMb2dNZXNzYWdlKGxldmVsLCBtZXNzYWdlKSB7XG5cblx0Ly8gTG9nIE1lc3NhZ2UgZm9ybWF0OlxuXHQvLyBsW3R5cGVdW21lc3NhZ2VdXG5cdHdpbmRvdy5XYWlsc0ludm9rZSgnTCcgKyBsZXZlbCArIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIExvZyB0aGUgZ2l2ZW4gdHJhY2UgbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIExvZ1RyYWNlKG1lc3NhZ2UpIHtcblx0c2VuZExvZ01lc3NhZ2UoJ1QnLCBtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBMb2cgdGhlIGdpdmVuIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dQcmludChtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdQJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiBkZWJ1ZyBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nRGVidWcobWVzc2FnZSkge1xuXHRzZW5kTG9nTWVzc2FnZSgnRCcsIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIExvZyB0aGUgZ2l2ZW4gaW5mbyBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nSW5mbyhtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdJJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiB3YXJuaW5nIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dXYXJuaW5nKG1lc3NhZ2UpIHtcblx0c2VuZExvZ01lc3NhZ2UoJ1cnLCBtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBMb2cgdGhlIGdpdmVuIGVycm9yIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dFcnJvcihtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdFJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiBmYXRhbCBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nRmF0YWwobWVzc2FnZSkge1xuXHRzZW5kTG9nTWVzc2FnZSgnRicsIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIExvZyBsZXZlbCB0byB0aGUgZ2l2ZW4gbG9nIGxldmVsXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtudW1iZXJ9IGxvZ2xldmVsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRMb2dMZXZlbChsb2dsZXZlbCkge1xuXHRzZW5kTG9nTWVzc2FnZSgnUycsIGxvZ2xldmVsKTtcbn1cblxuLy8gTG9nIGxldmVsc1xuZXhwb3J0IGNvbnN0IExvZ0xldmVsID0ge1xuXHRUUkFDRTogMSxcblx0REVCVUc6IDIsXG5cdElORk86IDMsXG5cdFdBUk5JTkc6IDQsXG5cdEVSUk9SOiA1LFxufTtcbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cblxuaW1wb3J0IFwiLi9pcGMuanNcIjtcbmltcG9ydCB7Q2FsbGJhY2ssIGNhbGxiYWNrc30gZnJvbSAnLi9jYWxscyc7XG5pbXBvcnQge0V2ZW50c05vdGlmeSwgZXZlbnRMaXN0ZW5lcnN9IGZyb20gXCIuL2V2ZW50c1wiO1xuaW1wb3J0IHtTZXRCaW5kaW5nc30gZnJvbSBcIi4vYmluZGluZ3NcIjtcblxuaW1wb3J0ICogYXMgV2luZG93IGZyb20gXCIuL3dpbmRvd1wiO1xuaW1wb3J0ICogYXMgU2NyZWVuIGZyb20gXCIuL3NjcmVlblwiO1xuaW1wb3J0ICogYXMgQnJvd3NlciBmcm9tIFwiLi9icm93c2VyXCI7XG5pbXBvcnQgKiBhcyBMb2cgZnJvbSAnLi9sb2cnO1xuXG5sZXQgd2luZG93SUQgPSAtMTtcblxuXG5leHBvcnQgZnVuY3Rpb24gUXVpdCgpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1EnKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIFNob3coKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdTJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBIaWRlKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnSCcpO1xufVxuXG4vLyBleHBvcnQgZnVuY3Rpb24gRW52aXJvbm1lbnQoKSB7XG4vLyAgICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6RW52aXJvbm1lbnRcIik7XG4vLyB9XG5cbi8vIEludGVybmFsIHdhaWxzIGVuZHBvaW50c1xud2luZG93LndhaWxzID0ge1xuICAgIENhbGxiYWNrLFxuICAgIGNhbGxiYWNrcyxcbiAgICBFdmVudHNOb3RpZnksXG4gICAgZXZlbnRMaXN0ZW5lcnMsXG4gICAgU2V0QmluZGluZ3MsXG4gICAgd2luZG93OiB7XG4gICAgICAgIElEOiAoKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gd2luZG93SURcbiAgICAgICAgfSxcbiAgICB9XG59O1xuXG53aW5kb3cucnVudGltZSA9IHtcbiAgICAuLi5Mb2csXG4gICAgLi4uV2luZG93LFxuICAgIC4uLkJyb3dzZXIsXG4gICAgLi4uU2NyZWVuLFxuICAgIEV2ZW50c09uLFxuICAgIEV2ZW50c09uY2UsXG4gICAgRXZlbnRzT25NdWx0aXBsZSxcbiAgICBFdmVudHNFbWl0LFxuICAgIEV2ZW50c09mZixcbiAgICAvLyBFbnZpcm9ubWVudCxcbiAgICBTaG93LFxuICAgIEhpZGUsXG4gICAgUXVpdCxcbn1cblxuLy8gUHJvY2VzcyB0aGUgZXhwZWN0ZWQgcnVudGltZSBjb25maWcgZnJvbSB0aGUgYmFja2VuZFxuaWYoIHdpbmRvdy53YWlsc19jb25maWcgKSB7XG4gICAgd2luZG93SUQgPSB3aW5kb3cud2FpbHNfY29uZmlnLndpbmRvd0lEO1xuICAgIHdpbmRvdy53YWlsc19jb25maWcgPSBudWxsO1xufVxuXG5pZiAoREVCVUcpIHtcbiAgICBjb25zb2xlLmxvZyhcIldhaWxzIHYzLjAuMCBEZWJ1ZyBNb2RlIEVuYWJsZWRcIik7XG59XG5cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7O0FBaUJBLEdBQUMsV0FBWTtBQUNaLFdBQU8sY0FBYyxDQUFDLFlBQVk7QUFDakMsTUFBVyxPQUFPLE9BQU8sUUFBUSxZQUFZLE9BQU87QUFBQSxJQUVyRDtBQUFBLEVBQ0QsR0FBRzs7O0FDWEksTUFBTSxZQUFZLENBQUM7QUFPMUIsV0FBUyxlQUFlO0FBQ3ZCLFFBQUksUUFBUSxJQUFJLFlBQVksQ0FBQztBQUM3QixXQUFPLE9BQU8sT0FBTyxnQkFBZ0IsS0FBSyxFQUFFO0FBQUEsRUFDN0M7QUFRQSxXQUFTLGNBQWM7QUFDdEIsV0FBTyxLQUFLLE9BQU8sSUFBSTtBQUFBLEVBQ3hCO0FBR0EsTUFBSTtBQUNKLE1BQUksT0FBTyxRQUFRO0FBQ2xCLGlCQUFhO0FBQUEsRUFDZCxPQUFPO0FBQ04saUJBQWE7QUFBQSxFQUNkO0FBaUJPLFdBQVMsS0FBSyxNQUFNLE1BQU0sU0FBUztBQUd6QyxRQUFJLFdBQVcsTUFBTTtBQUNwQixnQkFBVTtBQUFBLElBQ1g7QUFFQSxRQUFJQSxZQUFXLE9BQU8sTUFBTSxPQUFPLEdBQUc7QUFHdEMsV0FBTyxJQUFJLFFBQVEsU0FBVSxTQUFTLFFBQVE7QUFHN0MsVUFBSTtBQUNKLFNBQUc7QUFDRixxQkFBYSxPQUFPLE1BQU0sV0FBVztBQUFBLE1BQ3RDLFNBQVMsVUFBVTtBQUVuQixVQUFJO0FBRUosVUFBSSxVQUFVLEdBQUc7QUFDaEIsd0JBQWdCLFdBQVcsV0FBWTtBQUN0QyxpQkFBTyxNQUFNLGFBQWEsT0FBTyw2QkFBNkIsVUFBVSxDQUFDO0FBQUEsUUFDMUUsR0FBRyxPQUFPO0FBQUEsTUFDWDtBQUdBLGdCQUFVLGNBQWM7QUFBQSxRQUN2QjtBQUFBLFFBQ0E7QUFBQSxRQUNBO0FBQUEsTUFDRDtBQUVBLFVBQUk7QUFDSCxjQUFNLFVBQVU7QUFBQSxVQUNmO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBLFVBQUFBO0FBQUEsUUFDRDtBQUdTLGVBQU8sWUFBWSxNQUFNLEtBQUssVUFBVSxPQUFPLENBQUM7QUFBQSxNQUNwRCxTQUFTLEdBQVA7QUFFRSxnQkFBUSxNQUFNLENBQUM7QUFBQSxNQUNuQjtBQUFBLElBQ0osQ0FBQztBQUFBLEVBQ0w7QUFFQSxTQUFPLGlCQUFpQixDQUFDLElBQUksTUFBTSxZQUFZO0FBRzNDLFFBQUksV0FBVyxNQUFNO0FBQ2pCLGdCQUFVO0FBQUEsSUFDZDtBQUdBLFdBQU8sSUFBSSxRQUFRLFNBQVUsU0FBUyxRQUFRO0FBRzFDLFVBQUk7QUFDSixTQUFHO0FBQ0MscUJBQWEsS0FBSyxNQUFNLFdBQVc7QUFBQSxNQUN2QyxTQUFTLFVBQVU7QUFFbkIsVUFBSTtBQUVKLFVBQUksVUFBVSxHQUFHO0FBQ2Isd0JBQWdCLFdBQVcsV0FBWTtBQUNuQyxpQkFBTyxNQUFNLG9CQUFvQixLQUFLLDZCQUE2QixVQUFVLENBQUM7QUFBQSxRQUNsRixHQUFHLE9BQU87QUFBQSxNQUNkO0FBR0EsZ0JBQVUsY0FBYztBQUFBLFFBQ3BCO0FBQUEsUUFDQTtBQUFBLFFBQ0E7QUFBQSxNQUNKO0FBRUEsVUFBSTtBQUNBLGNBQU0sVUFBVTtBQUFBLFVBQ3hCO0FBQUEsVUFDQTtBQUFBLFVBQ0E7QUFBQSxVQUNBLFVBQVUsT0FBTyxNQUFNLE9BQU8sR0FBRztBQUFBLFFBQ2xDO0FBR1MsZUFBTyxZQUFZLE1BQU0sS0FBSyxVQUFVLE9BQU8sQ0FBQztBQUFBLE1BQ3BELFNBQVMsR0FBUDtBQUVFLGdCQUFRLE1BQU0sQ0FBQztBQUFBLE1BQ25CO0FBQUEsSUFDSixDQUFDO0FBQUEsRUFDTDtBQVVPLFdBQVMsU0FBUyxpQkFBaUI7QUFFekMsUUFBSTtBQUNKLFFBQUk7QUFDSCxnQkFBVSxLQUFLLE1BQU0sZUFBZTtBQUFBLElBQ3JDLFNBQVMsR0FBUDtBQUNELFlBQU0sUUFBUSxvQ0FBb0MsRUFBRSxxQkFBcUI7QUFDekUsY0FBUSxTQUFTLEtBQUs7QUFDdEIsWUFBTSxJQUFJLE1BQU0sS0FBSztBQUFBLElBQ3RCO0FBQ0EsUUFBSSxhQUFhLFFBQVE7QUFDekIsUUFBSSxlQUFlLFVBQVU7QUFDN0IsUUFBSSxDQUFDLGNBQWM7QUFDbEIsWUFBTSxRQUFRLGFBQWE7QUFDM0IsY0FBUSxNQUFNLEtBQUs7QUFDbkIsWUFBTSxJQUFJLE1BQU0sS0FBSztBQUFBLElBQ3RCO0FBQ0EsaUJBQWEsYUFBYSxhQUFhO0FBRXZDLFdBQU8sVUFBVTtBQUVqQixRQUFJLFFBQVEsT0FBTztBQUNsQixtQkFBYSxPQUFPLFFBQVEsS0FBSztBQUFBLElBQ2xDLE9BQU87QUFDTixtQkFBYSxRQUFRLFFBQVEsTUFBTTtBQUFBLElBQ3BDO0FBQUEsRUFDRDs7O0FDL0lPLE1BQU0saUJBQWlCLENBQUM7QUEwQy9CLFdBQVMsZ0JBQWdCLFdBQVc7QUFHaEMsUUFBSSxZQUFZLFVBQVU7QUFHMUIsUUFBSSxlQUFlLFlBQVk7QUFHM0IsWUFBTSx1QkFBdUIsZUFBZSxXQUFXLE1BQU07QUFHN0QsZUFBUyxRQUFRLEdBQUcsUUFBUSxlQUFlLFdBQVcsUUFBUSxTQUFTLEdBQUc7QUFHdEUsY0FBTSxXQUFXLGVBQWUsV0FBVztBQUUzQyxZQUFJLE9BQU8sVUFBVTtBQUdyQixjQUFNLFVBQVUsU0FBUyxTQUFTLElBQUk7QUFDdEMsWUFBSSxTQUFTO0FBRVQsK0JBQXFCLE9BQU8sT0FBTyxDQUFDO0FBQUEsUUFDeEM7QUFBQSxNQUNKO0FBR0EsVUFBSSxxQkFBcUIsV0FBVyxHQUFHO0FBQ25DLHVCQUFlLFNBQVM7QUFBQSxNQUM1QixPQUFPO0FBQ0gsdUJBQWUsYUFBYTtBQUFBLE1BQ2hDO0FBQUEsSUFDSjtBQUFBLEVBQ0o7QUFTTyxXQUFTLGFBQWEsZUFBZTtBQUV4QyxRQUFJO0FBQ0osUUFBSTtBQUNBLGdCQUFVLEtBQUssTUFBTSxhQUFhO0FBQUEsSUFDdEMsU0FBUyxHQUFQO0FBQ0UsWUFBTSxRQUFRLG9DQUFvQztBQUNsRCxZQUFNLElBQUksTUFBTSxLQUFLO0FBQUEsSUFDekI7QUFDQSxvQkFBZ0IsT0FBTztBQUFBLEVBQzNCO0FBc0JBLFdBQVMsZUFBZSxXQUFXO0FBRS9CLFdBQU8sZUFBZTtBQUd0QixXQUFPLFlBQVksT0FBTyxTQUFTO0FBQUEsRUFDdkM7OztBQzFKQSxTQUFPLEtBQUssQ0FBQztBQUVOLFdBQVMsWUFBWSxhQUFhO0FBQ3hDLFFBQUk7QUFDSCxvQkFBYyxLQUFLLE1BQU0sV0FBVztBQUFBLElBQ3JDLFNBQVMsR0FBUDtBQUNELGNBQVEsTUFBTSxDQUFDO0FBQUEsSUFDaEI7QUFHQSxXQUFPLEtBQUssT0FBTyxNQUFNLENBQUM7QUFHMUIsV0FBTyxLQUFLLFdBQVcsRUFBRSxRQUFRLENBQUMsZ0JBQWdCO0FBR2pELGFBQU8sR0FBRyxlQUFlLE9BQU8sR0FBRyxnQkFBZ0IsQ0FBQztBQUdwRCxhQUFPLEtBQUssWUFBWSxZQUFZLEVBQUUsUUFBUSxDQUFDLGVBQWU7QUFHN0QsZUFBTyxHQUFHLGFBQWEsY0FBYyxPQUFPLEdBQUcsYUFBYSxlQUFlLENBQUM7QUFFNUUsZUFBTyxLQUFLLFlBQVksYUFBYSxXQUFXLEVBQUUsUUFBUSxDQUFDLGVBQWU7QUFFekUsaUJBQU8sR0FBRyxhQUFhLFlBQVksY0FBYyxXQUFZO0FBRzVELGdCQUFJLFVBQVU7QUFHZCxxQkFBUyxVQUFVO0FBQ2xCLG9CQUFNLE9BQU8sQ0FBQyxFQUFFLE1BQU0sS0FBSyxTQUFTO0FBQ3BDLHFCQUFPLEtBQUssQ0FBQyxhQUFhLFlBQVksVUFBVSxFQUFFLEtBQUssR0FBRyxHQUFHLE1BQU0sT0FBTztBQUFBLFlBQzNFO0FBR0Esb0JBQVEsYUFBYSxTQUFVLFlBQVk7QUFDMUMsd0JBQVU7QUFBQSxZQUNYO0FBR0Esb0JBQVEsYUFBYSxXQUFZO0FBQ2hDLHFCQUFPO0FBQUEsWUFDUjtBQUVBLG1CQUFPO0FBQUEsVUFDUixFQUFFO0FBQUEsUUFDSCxDQUFDO0FBQUEsTUFDRixDQUFDO0FBQUEsSUFDRixDQUFDO0FBQUEsRUFDRjs7O0FDbEVBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBZU8sV0FBUyxlQUFlO0FBQzNCLFdBQU8sU0FBUyxPQUFPO0FBQUEsRUFDM0I7QUFFTyxXQUFTLGtCQUFrQjtBQUM5QixXQUFPLFlBQVksSUFBSTtBQUFBLEVBQzNCO0FBRU8sV0FBUyw4QkFBOEI7QUFDMUMsV0FBTyxZQUFZLE9BQU87QUFBQSxFQUM5QjtBQUVPLFdBQVMsc0JBQXNCO0FBQ2xDLFdBQU8sWUFBWSxNQUFNO0FBQUEsRUFDN0I7QUFFTyxXQUFTLHFCQUFxQjtBQUNqQyxXQUFPLFlBQVksTUFBTTtBQUFBLEVBQzdCO0FBT08sV0FBUyxlQUFlO0FBQzNCLFdBQU8sWUFBWSxJQUFJO0FBQUEsRUFDM0I7QUFRTyxXQUFTLGVBQWUsT0FBTztBQUNsQyxXQUFPLFlBQVksT0FBTyxLQUFLO0FBQUEsRUFDbkM7QUFPTyxXQUFTLG1CQUFtQjtBQUMvQixXQUFPLFlBQVksSUFBSTtBQUFBLEVBQzNCO0FBT08sV0FBUyxxQkFBcUI7QUFDakMsV0FBTyxZQUFZLElBQUk7QUFBQSxFQUMzQjtBQVFPLFdBQVMscUJBQXFCO0FBQ2pDLFdBQU8sS0FBSywyQkFBMkI7QUFBQSxFQUMzQztBQVNPLFdBQVMsY0FBYyxPQUFPLFFBQVE7QUFDekMsV0FBTyxZQUFZLFFBQVEsUUFBUSxNQUFNLE1BQU07QUFBQSxFQUNuRDtBQVNPLFdBQVMsZ0JBQWdCO0FBQzVCLFdBQU8sS0FBSyxzQkFBc0I7QUFBQSxFQUN0QztBQVNPLFdBQVMsaUJBQWlCLE9BQU8sUUFBUTtBQUM1QyxXQUFPLFlBQVksUUFBUSxRQUFRLE1BQU0sTUFBTTtBQUFBLEVBQ25EO0FBU08sV0FBUyxpQkFBaUIsT0FBTyxRQUFRO0FBQzVDLFdBQU8sWUFBWSxRQUFRLFFBQVEsTUFBTSxNQUFNO0FBQUEsRUFDbkQ7QUFTTyxXQUFTLHFCQUFxQixHQUFHO0FBRXBDLFdBQU8sWUFBWSxXQUFXLElBQUksTUFBTSxJQUFJO0FBQUEsRUFDaEQ7QUFZTyxXQUFTLGtCQUFrQixHQUFHLEdBQUc7QUFDcEMsV0FBTyxZQUFZLFFBQVEsSUFBSSxNQUFNLENBQUM7QUFBQSxFQUMxQztBQVFPLFdBQVMsb0JBQW9CO0FBQ2hDLFdBQU8sS0FBSyxxQkFBcUI7QUFBQSxFQUNyQztBQU9PLFdBQVMsYUFBYTtBQUN6QixXQUFPLFlBQVksSUFBSTtBQUFBLEVBQzNCO0FBT08sV0FBUyxhQUFhO0FBQ3pCLFdBQU8sWUFBWSxJQUFJO0FBQUEsRUFDM0I7QUFPTyxXQUFTLGlCQUFpQjtBQUM3QixXQUFPLFlBQVksSUFBSTtBQUFBLEVBQzNCO0FBT08sV0FBUyx1QkFBdUI7QUFDbkMsV0FBTyxZQUFZLElBQUk7QUFBQSxFQUMzQjtBQU9PLFdBQVMsbUJBQW1CO0FBQy9CLFdBQU8sWUFBWSxJQUFJO0FBQUEsRUFDM0I7QUFRTyxXQUFTLG9CQUFvQjtBQUNoQyxXQUFPLEtBQUssMEJBQTBCO0FBQUEsRUFDMUM7QUFPTyxXQUFTLGlCQUFpQjtBQUM3QixXQUFPLFlBQVksSUFBSTtBQUFBLEVBQzNCO0FBT08sV0FBUyxtQkFBbUI7QUFDL0IsV0FBTyxZQUFZLElBQUk7QUFBQSxFQUMzQjtBQVFPLFdBQVMsb0JBQW9CO0FBQ2hDLFdBQU8sS0FBSywwQkFBMEI7QUFBQSxFQUMxQztBQVFPLFdBQVMsaUJBQWlCO0FBQzdCLFdBQU8sS0FBSyx1QkFBdUI7QUFBQSxFQUN2QztBQVdPLFdBQVMsMEJBQTBCLEdBQUcsR0FBRyxHQUFHLEdBQUc7QUFDbEQsUUFBSSxPQUFPLEtBQUssVUFBVSxFQUFDLEdBQUcsS0FBSyxHQUFHLEdBQUcsS0FBSyxHQUFHLEdBQUcsS0FBSyxHQUFHLEdBQUcsS0FBSyxJQUFHLENBQUM7QUFDeEUsV0FBTyxZQUFZLFFBQVEsSUFBSTtBQUFBLEVBQ25DOzs7QUMzUUE7QUFBQTtBQUFBO0FBQUE7QUFzQk8sV0FBUyxlQUFlO0FBQzNCLFdBQU8sS0FBSyxxQkFBcUI7QUFBQSxFQUNyQzs7O0FDeEJBO0FBQUE7QUFBQTtBQUFBO0FBS08sV0FBUyxlQUFlLEtBQUs7QUFDbEMsV0FBTyxZQUFZLFFBQVEsR0FBRztBQUFBLEVBQ2hDOzs7QUNQQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFrQkEsV0FBUyxlQUFlLE9BQU8sU0FBUztBQUl2QyxXQUFPLFlBQVksTUFBTSxRQUFRLE9BQU87QUFBQSxFQUN6QztBQVFPLFdBQVMsU0FBUyxTQUFTO0FBQ2pDLG1CQUFlLEtBQUssT0FBTztBQUFBLEVBQzVCO0FBUU8sV0FBUyxTQUFTLFNBQVM7QUFDakMsbUJBQWUsS0FBSyxPQUFPO0FBQUEsRUFDNUI7QUFRTyxXQUFTLFNBQVMsU0FBUztBQUNqQyxtQkFBZSxLQUFLLE9BQU87QUFBQSxFQUM1QjtBQVFPLFdBQVMsUUFBUSxTQUFTO0FBQ2hDLG1CQUFlLEtBQUssT0FBTztBQUFBLEVBQzVCO0FBUU8sV0FBUyxXQUFXLFNBQVM7QUFDbkMsbUJBQWUsS0FBSyxPQUFPO0FBQUEsRUFDNUI7QUFRTyxXQUFTLFNBQVMsU0FBUztBQUNqQyxtQkFBZSxLQUFLLE9BQU87QUFBQSxFQUM1QjtBQVFPLFdBQVMsU0FBUyxTQUFTO0FBQ2pDLG1CQUFlLEtBQUssT0FBTztBQUFBLEVBQzVCO0FBUU8sV0FBUyxZQUFZLFVBQVU7QUFDckMsbUJBQWUsS0FBSyxRQUFRO0FBQUEsRUFDN0I7QUFHTyxNQUFNLFdBQVc7QUFBQSxJQUN2QixPQUFPO0FBQUEsSUFDUCxPQUFPO0FBQUEsSUFDUCxNQUFNO0FBQUEsSUFDTixTQUFTO0FBQUEsSUFDVCxPQUFPO0FBQUEsRUFDUjs7O0FDM0ZBLE1BQUksV0FBVztBQUdSLFdBQVMsT0FBTztBQUNuQixXQUFPLFlBQVksR0FBRztBQUFBLEVBQzFCO0FBRU8sV0FBUyxPQUFPO0FBQ25CLFdBQU8sWUFBWSxHQUFHO0FBQUEsRUFDMUI7QUFFTyxXQUFTLE9BQU87QUFDbkIsV0FBTyxZQUFZLEdBQUc7QUFBQSxFQUMxQjtBQU9BLFNBQU8sUUFBUTtBQUFBLElBQ1g7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQSxRQUFRO0FBQUEsTUFDSixJQUFJLE1BQU07QUFDTixlQUFPO0FBQUEsTUFDWDtBQUFBLElBQ0o7QUFBQSxFQUNKO0FBRUEsU0FBTyxVQUFVO0FBQUEsSUFDYixHQUFHO0FBQUEsSUFDSCxHQUFHO0FBQUEsSUFDSCxHQUFHO0FBQUEsSUFDSCxHQUFHO0FBQUEsSUFDSDtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUVBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxFQUNKO0FBR0EsTUFBSSxPQUFPLGNBQWU7QUFDdEIsZUFBVyxPQUFPLGFBQWE7QUFDL0IsV0FBTyxlQUFlO0FBQUEsRUFDMUI7QUFFQSxNQUFJLE1BQU87QUFDUCxZQUFRLElBQUksaUNBQWlDO0FBQUEsRUFDakQ7IiwKICAibmFtZXMiOiBbIndpbmRvd0lEIl0KfQo= diff --git a/exp/internal/runtime/runtime_debug_linux.go b/exp/internal/runtime/runtime_debug_linux.go new file mode 100644 index 000000000..c29408392 --- /dev/null +++ b/exp/internal/runtime/runtime_debug_linux.go @@ -0,0 +1,8 @@ +//go:build linux && !production + +package runtime + +import _ "embed" + +//go:embed runtime_debug_desktop_linux.js +var DesktopRuntime []byte diff --git a/exp/internal/runtime/runtime_debug_windows.go b/exp/internal/runtime/runtime_debug_windows.go new file mode 100644 index 000000000..09a3a9198 --- /dev/null +++ b/exp/internal/runtime/runtime_debug_windows.go @@ -0,0 +1,8 @@ +//go:build windows && !production + +package runtime + +import _ "embed" + +//go:embed runtime_debug_desktop_windows.js +var DesktopRuntime []byte diff --git a/exp/internal/runtime/runtime_production_darwin.go b/exp/internal/runtime/runtime_production_darwin.go new file mode 100644 index 000000000..be2411d9e --- /dev/null +++ b/exp/internal/runtime/runtime_production_darwin.go @@ -0,0 +1,8 @@ +//go:build darwin && production + +package runtime + +import _ "embed" + +//go:embed runtime_production_desktop_darwin.js +var DesktopRuntime []byte diff --git a/exp/internal/runtime/runtime_production_desktop_darwin.js b/exp/internal/runtime/runtime_production_desktop_darwin.js new file mode 100644 index 000000000..2cc00fb76 --- /dev/null +++ b/exp/internal/runtime/runtime_production_desktop_darwin.js @@ -0,0 +1 @@ +(()=>{var h=Object.defineProperty;var f=(o,n)=>{for(var e in n)h(o,e,{get:n[e],enumerable:!0})};(function(){window.WailsInvoke=o=>{window.webkit.messageHandlers.wails.postMessage(o)}})();var w={};function E(){var o=new Uint32Array(1);return window.crypto.getRandomValues(o)[0]}function y(){return Math.random()*9007199254740991}var u;window.crypto?u=E:u=y;function l(o,n,e){e==null&&(e=0);let i=window.wails.window.ID();return new Promise(function(t,r){var s;do s=o+"-"+u();while(w[s]);var d;e>0&&(d=setTimeout(function(){r(Error("Call to "+o+" timed out. Request ID: "+s))},e)),w[s]={timeoutHandle:d,reject:r,resolve:t};try{let W={name:o,args:n,callbackID:s,windowID:i};window.WailsInvoke("C"+JSON.stringify(W))}catch(W){console.error(W)}})}window.ObfuscatedCall=(o,n,e)=>(e==null&&(e=0),new Promise(function(i,t){var r;do r=o+"-"+u();while(w[r]);var s;e>0&&(s=setTimeout(function(){t(Error("Call to method "+o+" timed out. Request ID: "+r))},e)),w[r]={timeoutHandle:s,reject:t,resolve:i};try{let d={id:o,args:n,callbackID:r,windowID:window.wails.window.ID()};window.WailsInvoke("c"+JSON.stringify(d))}catch(d){console.error(d)}}));function m(o){let n;try{n=JSON.parse(o)}catch(t){let r=`Invalid JSON passed to callback: ${t.message}. Message: ${o}`;throw runtime.LogDebug(r),new Error(r)}let e=n.callbackid,i=w[e];if(!i){let t=`Callback '${e}' not registered!!!`;throw console.error(t),new Error(t)}clearTimeout(i.timeoutHandle),delete w[e],n.error?i.reject(n.error):i.resolve(n.result)}var a={};function O(o){let n=o.name;if(a[n]){let e=a[n].slice();for(let i=0;i{window.go[n]=window.go[n]||{},Object.keys(o[n]).forEach(e=>{window.go[n][e]=window.go[n][e]||{},Object.keys(o[n][e]).forEach(i=>{window.go[n][e][i]=function(){let t=0;function r(){let s=[].slice.call(arguments);return l([n,e,i].join("."),s,t)}return r.setTimeout=function(s){t=s},r.getTimeout=function(){return t},r}()})})})}var p={};f(p,{WindowCenter:()=>A,WindowFullscreen:()=>H,WindowGetPosition:()=>z,WindowGetSize:()=>B,WindowHide:()=>_,WindowIsFullscreen:()=>J,WindowIsMaximised:()=>V,WindowIsMinimised:()=>Y,WindowIsNormal:()=>oo,WindowMaximise:()=>q,WindowMinimise:()=>Z,WindowReload:()=>L,WindowReloadApp:()=>D,WindowSetAlwaysOnTop:()=>P,WindowSetBackgroundColour:()=>no,WindowSetDarkTheme:()=>R,WindowSetLightTheme:()=>T,WindowSetMaxSize:()=>F,WindowSetMinSize:()=>N,WindowSetPosition:()=>j,WindowSetSize:()=>U,WindowSetSystemDefaultTheme:()=>C,WindowSetTitle:()=>M,WindowShow:()=>$,WindowToggleMaximise:()=>Q,WindowUnfullscreen:()=>G,WindowUnmaximise:()=>X,WindowUnminimise:()=>K});function L(){window.location.reload()}function D(){window.WailsInvoke("WR")}function C(){window.WailsInvoke("WASDT")}function T(){window.WailsInvoke("WALT")}function R(){window.WailsInvoke("WADT")}function A(){window.WailsInvoke("Wc")}function M(o){window.WailsInvoke("WT"+o)}function H(){window.WailsInvoke("WF")}function G(){window.WailsInvoke("Wf")}function J(){return l(":wails:WindowIsFullscreen")}function U(o,n){window.WailsInvoke("Ws:"+o+":"+n)}function B(){return l(":wails:WindowGetSize")}function F(o,n){window.WailsInvoke("WZ:"+o+":"+n)}function N(o,n){window.WailsInvoke("Wz:"+o+":"+n)}function P(o){window.WailsInvoke("WATP:"+(o?"1":"0"))}function j(o,n){window.WailsInvoke("Wp:"+o+":"+n)}function z(){return l(":wails:WindowGetPos")}function _(){window.WailsInvoke("WH")}function $(){window.WailsInvoke("WS")}function q(){window.WailsInvoke("WM")}function Q(){window.WailsInvoke("Wt")}function X(){window.WailsInvoke("WU")}function V(){return l(":wails:WindowIsMaximised")}function Z(){window.WailsInvoke("Wm")}function K(){window.WailsInvoke("Wu")}function Y(){return l(":wails:WindowIsMinimised")}function oo(){return l(":wails:WindowIsNormal")}function no(o,n,e,i){let t=JSON.stringify({r:o||0,g:n||0,b:e||0,a:i||255});window.WailsInvoke("Wr:"+t)}var x={};f(x,{ScreenGetAll:()=>eo});function eo(){return l(":wails:ScreenGetAll")}var v={};f(v,{BrowserOpenURL:()=>io});function io(o){window.WailsInvoke("BO:"+o)}var I={};f(I,{LogDebug:()=>so,LogError:()=>ao,LogFatal:()=>co,LogInfo:()=>lo,LogLevel:()=>uo,LogPrint:()=>ro,LogTrace:()=>to,LogWarning:()=>wo,SetLogLevel:()=>fo});function c(o,n){window.WailsInvoke("L"+o+n)}function to(o){c("T",o)}function ro(o){c("P",o)}function so(o){c("D",o)}function lo(o){c("I",o)}function wo(o){c("W",o)}function ao(o){c("E",o)}function co(o){c("F",o)}function fo(o){c("S",o)}var uo={TRACE:1,DEBUG:2,INFO:3,WARNING:4,ERROR:5};var S=-1;function Wo(){window.WailsInvoke("Q")}function po(){window.WailsInvoke("S")}function xo(){window.WailsInvoke("H")}window.wails={Callback:m,callbacks:w,EventsNotify:k,eventListeners:a,SetBindings:g,window:{ID:()=>S}};window.runtime={...I,...p,...v,...x,EventsOn,EventsOnce,EventsOnMultiple,EventsEmit,EventsOff,Show:po,Hide:xo,Quit:Wo};window.wails_config&&(S=window.wails_config.windowID,window.wails_config=null);console.log("Wails v3.0.0 Debug Mode Enabled");})(); diff --git a/exp/internal/runtime/runtime_production_desktop_linux.js b/exp/internal/runtime/runtime_production_desktop_linux.js new file mode 100644 index 000000000..2cc00fb76 --- /dev/null +++ b/exp/internal/runtime/runtime_production_desktop_linux.js @@ -0,0 +1 @@ +(()=>{var h=Object.defineProperty;var f=(o,n)=>{for(var e in n)h(o,e,{get:n[e],enumerable:!0})};(function(){window.WailsInvoke=o=>{window.webkit.messageHandlers.wails.postMessage(o)}})();var w={};function E(){var o=new Uint32Array(1);return window.crypto.getRandomValues(o)[0]}function y(){return Math.random()*9007199254740991}var u;window.crypto?u=E:u=y;function l(o,n,e){e==null&&(e=0);let i=window.wails.window.ID();return new Promise(function(t,r){var s;do s=o+"-"+u();while(w[s]);var d;e>0&&(d=setTimeout(function(){r(Error("Call to "+o+" timed out. Request ID: "+s))},e)),w[s]={timeoutHandle:d,reject:r,resolve:t};try{let W={name:o,args:n,callbackID:s,windowID:i};window.WailsInvoke("C"+JSON.stringify(W))}catch(W){console.error(W)}})}window.ObfuscatedCall=(o,n,e)=>(e==null&&(e=0),new Promise(function(i,t){var r;do r=o+"-"+u();while(w[r]);var s;e>0&&(s=setTimeout(function(){t(Error("Call to method "+o+" timed out. Request ID: "+r))},e)),w[r]={timeoutHandle:s,reject:t,resolve:i};try{let d={id:o,args:n,callbackID:r,windowID:window.wails.window.ID()};window.WailsInvoke("c"+JSON.stringify(d))}catch(d){console.error(d)}}));function m(o){let n;try{n=JSON.parse(o)}catch(t){let r=`Invalid JSON passed to callback: ${t.message}. Message: ${o}`;throw runtime.LogDebug(r),new Error(r)}let e=n.callbackid,i=w[e];if(!i){let t=`Callback '${e}' not registered!!!`;throw console.error(t),new Error(t)}clearTimeout(i.timeoutHandle),delete w[e],n.error?i.reject(n.error):i.resolve(n.result)}var a={};function O(o){let n=o.name;if(a[n]){let e=a[n].slice();for(let i=0;i{window.go[n]=window.go[n]||{},Object.keys(o[n]).forEach(e=>{window.go[n][e]=window.go[n][e]||{},Object.keys(o[n][e]).forEach(i=>{window.go[n][e][i]=function(){let t=0;function r(){let s=[].slice.call(arguments);return l([n,e,i].join("."),s,t)}return r.setTimeout=function(s){t=s},r.getTimeout=function(){return t},r}()})})})}var p={};f(p,{WindowCenter:()=>A,WindowFullscreen:()=>H,WindowGetPosition:()=>z,WindowGetSize:()=>B,WindowHide:()=>_,WindowIsFullscreen:()=>J,WindowIsMaximised:()=>V,WindowIsMinimised:()=>Y,WindowIsNormal:()=>oo,WindowMaximise:()=>q,WindowMinimise:()=>Z,WindowReload:()=>L,WindowReloadApp:()=>D,WindowSetAlwaysOnTop:()=>P,WindowSetBackgroundColour:()=>no,WindowSetDarkTheme:()=>R,WindowSetLightTheme:()=>T,WindowSetMaxSize:()=>F,WindowSetMinSize:()=>N,WindowSetPosition:()=>j,WindowSetSize:()=>U,WindowSetSystemDefaultTheme:()=>C,WindowSetTitle:()=>M,WindowShow:()=>$,WindowToggleMaximise:()=>Q,WindowUnfullscreen:()=>G,WindowUnmaximise:()=>X,WindowUnminimise:()=>K});function L(){window.location.reload()}function D(){window.WailsInvoke("WR")}function C(){window.WailsInvoke("WASDT")}function T(){window.WailsInvoke("WALT")}function R(){window.WailsInvoke("WADT")}function A(){window.WailsInvoke("Wc")}function M(o){window.WailsInvoke("WT"+o)}function H(){window.WailsInvoke("WF")}function G(){window.WailsInvoke("Wf")}function J(){return l(":wails:WindowIsFullscreen")}function U(o,n){window.WailsInvoke("Ws:"+o+":"+n)}function B(){return l(":wails:WindowGetSize")}function F(o,n){window.WailsInvoke("WZ:"+o+":"+n)}function N(o,n){window.WailsInvoke("Wz:"+o+":"+n)}function P(o){window.WailsInvoke("WATP:"+(o?"1":"0"))}function j(o,n){window.WailsInvoke("Wp:"+o+":"+n)}function z(){return l(":wails:WindowGetPos")}function _(){window.WailsInvoke("WH")}function $(){window.WailsInvoke("WS")}function q(){window.WailsInvoke("WM")}function Q(){window.WailsInvoke("Wt")}function X(){window.WailsInvoke("WU")}function V(){return l(":wails:WindowIsMaximised")}function Z(){window.WailsInvoke("Wm")}function K(){window.WailsInvoke("Wu")}function Y(){return l(":wails:WindowIsMinimised")}function oo(){return l(":wails:WindowIsNormal")}function no(o,n,e,i){let t=JSON.stringify({r:o||0,g:n||0,b:e||0,a:i||255});window.WailsInvoke("Wr:"+t)}var x={};f(x,{ScreenGetAll:()=>eo});function eo(){return l(":wails:ScreenGetAll")}var v={};f(v,{BrowserOpenURL:()=>io});function io(o){window.WailsInvoke("BO:"+o)}var I={};f(I,{LogDebug:()=>so,LogError:()=>ao,LogFatal:()=>co,LogInfo:()=>lo,LogLevel:()=>uo,LogPrint:()=>ro,LogTrace:()=>to,LogWarning:()=>wo,SetLogLevel:()=>fo});function c(o,n){window.WailsInvoke("L"+o+n)}function to(o){c("T",o)}function ro(o){c("P",o)}function so(o){c("D",o)}function lo(o){c("I",o)}function wo(o){c("W",o)}function ao(o){c("E",o)}function co(o){c("F",o)}function fo(o){c("S",o)}var uo={TRACE:1,DEBUG:2,INFO:3,WARNING:4,ERROR:5};var S=-1;function Wo(){window.WailsInvoke("Q")}function po(){window.WailsInvoke("S")}function xo(){window.WailsInvoke("H")}window.wails={Callback:m,callbacks:w,EventsNotify:k,eventListeners:a,SetBindings:g,window:{ID:()=>S}};window.runtime={...I,...p,...v,...x,EventsOn,EventsOnce,EventsOnMultiple,EventsEmit,EventsOff,Show:po,Hide:xo,Quit:Wo};window.wails_config&&(S=window.wails_config.windowID,window.wails_config=null);console.log("Wails v3.0.0 Debug Mode Enabled");})(); diff --git a/exp/internal/runtime/runtime_production_desktop_windows.js b/exp/internal/runtime/runtime_production_desktop_windows.js new file mode 100644 index 000000000..c752cb520 --- /dev/null +++ b/exp/internal/runtime/runtime_production_desktop_windows.js @@ -0,0 +1 @@ +(()=>{var h=Object.defineProperty;var f=(o,n)=>{for(var e in n)h(o,e,{get:n[e],enumerable:!0})};(function(){window.WailsInvoke=o=>{window.chrome.webview.postMessage(o)}})();var w={};function E(){var o=new Uint32Array(1);return window.crypto.getRandomValues(o)[0]}function y(){return Math.random()*9007199254740991}var u;window.crypto?u=E:u=y;function l(o,n,e){e==null&&(e=0);let i=window.wails.window.ID();return new Promise(function(t,r){var s;do s=o+"-"+u();while(w[s]);var d;e>0&&(d=setTimeout(function(){r(Error("Call to "+o+" timed out. Request ID: "+s))},e)),w[s]={timeoutHandle:d,reject:r,resolve:t};try{let W={name:o,args:n,callbackID:s,windowID:i};window.WailsInvoke("C"+JSON.stringify(W))}catch(W){console.error(W)}})}window.ObfuscatedCall=(o,n,e)=>(e==null&&(e=0),new Promise(function(i,t){var r;do r=o+"-"+u();while(w[r]);var s;e>0&&(s=setTimeout(function(){t(Error("Call to method "+o+" timed out. Request ID: "+r))},e)),w[r]={timeoutHandle:s,reject:t,resolve:i};try{let d={id:o,args:n,callbackID:r,windowID:window.wails.window.ID()};window.WailsInvoke("c"+JSON.stringify(d))}catch(d){console.error(d)}}));function m(o){let n;try{n=JSON.parse(o)}catch(t){let r=`Invalid JSON passed to callback: ${t.message}. Message: ${o}`;throw runtime.LogDebug(r),new Error(r)}let e=n.callbackid,i=w[e];if(!i){let t=`Callback '${e}' not registered!!!`;throw console.error(t),new Error(t)}clearTimeout(i.timeoutHandle),delete w[e],n.error?i.reject(n.error):i.resolve(n.result)}var a={};function O(o){let n=o.name;if(a[n]){let e=a[n].slice();for(let i=0;i{window.go[n]=window.go[n]||{},Object.keys(o[n]).forEach(e=>{window.go[n][e]=window.go[n][e]||{},Object.keys(o[n][e]).forEach(i=>{window.go[n][e][i]=function(){let t=0;function r(){let s=[].slice.call(arguments);return l([n,e,i].join("."),s,t)}return r.setTimeout=function(s){t=s},r.getTimeout=function(){return t},r}()})})})}var p={};f(p,{WindowCenter:()=>A,WindowFullscreen:()=>H,WindowGetPosition:()=>z,WindowGetSize:()=>B,WindowHide:()=>_,WindowIsFullscreen:()=>J,WindowIsMaximised:()=>V,WindowIsMinimised:()=>Y,WindowIsNormal:()=>oo,WindowMaximise:()=>q,WindowMinimise:()=>Z,WindowReload:()=>L,WindowReloadApp:()=>D,WindowSetAlwaysOnTop:()=>P,WindowSetBackgroundColour:()=>no,WindowSetDarkTheme:()=>R,WindowSetLightTheme:()=>T,WindowSetMaxSize:()=>F,WindowSetMinSize:()=>N,WindowSetPosition:()=>j,WindowSetSize:()=>U,WindowSetSystemDefaultTheme:()=>C,WindowSetTitle:()=>M,WindowShow:()=>$,WindowToggleMaximise:()=>Q,WindowUnfullscreen:()=>G,WindowUnmaximise:()=>X,WindowUnminimise:()=>K});function L(){window.location.reload()}function D(){window.WailsInvoke("WR")}function C(){window.WailsInvoke("WASDT")}function T(){window.WailsInvoke("WALT")}function R(){window.WailsInvoke("WADT")}function A(){window.WailsInvoke("Wc")}function M(o){window.WailsInvoke("WT"+o)}function H(){window.WailsInvoke("WF")}function G(){window.WailsInvoke("Wf")}function J(){return l(":wails:WindowIsFullscreen")}function U(o,n){window.WailsInvoke("Ws:"+o+":"+n)}function B(){return l(":wails:WindowGetSize")}function F(o,n){window.WailsInvoke("WZ:"+o+":"+n)}function N(o,n){window.WailsInvoke("Wz:"+o+":"+n)}function P(o){window.WailsInvoke("WATP:"+(o?"1":"0"))}function j(o,n){window.WailsInvoke("Wp:"+o+":"+n)}function z(){return l(":wails:WindowGetPos")}function _(){window.WailsInvoke("WH")}function $(){window.WailsInvoke("WS")}function q(){window.WailsInvoke("WM")}function Q(){window.WailsInvoke("Wt")}function X(){window.WailsInvoke("WU")}function V(){return l(":wails:WindowIsMaximised")}function Z(){window.WailsInvoke("Wm")}function K(){window.WailsInvoke("Wu")}function Y(){return l(":wails:WindowIsMinimised")}function oo(){return l(":wails:WindowIsNormal")}function no(o,n,e,i){let t=JSON.stringify({r:o||0,g:n||0,b:e||0,a:i||255});window.WailsInvoke("Wr:"+t)}var x={};f(x,{ScreenGetAll:()=>eo});function eo(){return l(":wails:ScreenGetAll")}var v={};f(v,{BrowserOpenURL:()=>io});function io(o){window.WailsInvoke("BO:"+o)}var I={};f(I,{LogDebug:()=>so,LogError:()=>ao,LogFatal:()=>co,LogInfo:()=>lo,LogLevel:()=>uo,LogPrint:()=>ro,LogTrace:()=>to,LogWarning:()=>wo,SetLogLevel:()=>fo});function c(o,n){window.WailsInvoke("L"+o+n)}function to(o){c("T",o)}function ro(o){c("P",o)}function so(o){c("D",o)}function lo(o){c("I",o)}function wo(o){c("W",o)}function ao(o){c("E",o)}function co(o){c("F",o)}function fo(o){c("S",o)}var uo={TRACE:1,DEBUG:2,INFO:3,WARNING:4,ERROR:5};var S=-1;function Wo(){window.WailsInvoke("Q")}function po(){window.WailsInvoke("S")}function xo(){window.WailsInvoke("H")}window.wails={Callback:m,callbacks:w,EventsNotify:k,eventListeners:a,SetBindings:g,window:{ID:()=>S}};window.runtime={...I,...p,...v,...x,EventsOn,EventsOnce,EventsOnMultiple,EventsEmit,EventsOff,Show:po,Hide:xo,Quit:Wo};window.wails_config&&(S=window.wails_config.windowID,window.wails_config=null);console.log("Wails v3.0.0 Debug Mode Enabled");})(); diff --git a/exp/internal/runtime/runtime_production_linux.go b/exp/internal/runtime/runtime_production_linux.go new file mode 100644 index 000000000..d7c2bd1ef --- /dev/null +++ b/exp/internal/runtime/runtime_production_linux.go @@ -0,0 +1,8 @@ +//go:build linux && production + +package runtime + +import _ "embed" + +//go:embed runtime_production_desktop_linux.js +var DesktopRuntime []byte diff --git a/exp/internal/runtime/runtime_production_windows.go b/exp/internal/runtime/runtime_production_windows.go new file mode 100644 index 000000000..8ab6d6199 --- /dev/null +++ b/exp/internal/runtime/runtime_production_windows.go @@ -0,0 +1,8 @@ +//go:build windows && production + +package runtime + +import _ "embed" + +//go:embed runtime_production_desktop_windows.js +var DesktopRuntime []byte diff --git a/exp/internal/runtime/vite.config.ts b/exp/internal/runtime/vite.config.ts new file mode 100644 index 000000000..eb0831c65 --- /dev/null +++ b/exp/internal/runtime/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + environment: 'happy-dom', + }, +}) \ No newline at end of file From f371b513d1d0a83e8bd536e4f0d718a24297b397 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Fri, 13 Jan 2023 17:33:54 +1100 Subject: [PATCH 75/85] Fix name of Window menu in role --- exp/pkg/application/roles.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exp/pkg/application/roles.go b/exp/pkg/application/roles.go index c16633327..0aec3bd48 100644 --- a/exp/pkg/application/roles.go +++ b/exp/pkg/application/roles.go @@ -132,7 +132,7 @@ func newWindowMenu() *MenuItem { menu := NewMenu() menu.AddRole(Minimize) menu.AddRole(Zoom) - subMenu := newSubMenuItem("WebviewWindow") + subMenu := newSubMenuItem("Window") subMenu.submenu = menu return subMenu } From 572fbc9705f565073af93fe33e65e247173891f8 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Fri, 13 Jan 2023 17:35:43 +1100 Subject: [PATCH 76/85] Initial parsing to discover bound struct names --- exp/examples/binding/main.go | 35 ++++++++++ exp/examples/binding/models/person.go | 5 ++ exp/examples/binding/service.go | 51 ++++++++++++++ exp/go.mod | 4 ++ exp/go.sum | 4 ++ exp/internal/parser/boundstructs.go | 47 +++++++++++++ exp/internal/parser/boundstructs_test.go | 44 ++++++++++++ exp/internal/parser/calls.go | 66 ++++++++++++++++++ exp/internal/parser/calls_test.go | 34 +++++++++ exp/internal/parser/imports.go | 69 +++++++++++++++++++ exp/internal/parser/imports_test.go | 56 +++++++++++++++ exp/internal/parser/options.go | 22 ++++++ exp/internal/parser/options_test.go | 31 +++++++++ .../struct_literal_multiple/main.go | 40 +++++++++++ .../struct_literal_multiple_files/greet.go | 14 ++++ .../struct_literal_multiple_files/main.go | 27 ++++++++ .../struct_literal_multiple_files/other.go | 5 ++ .../struct_literal_single/main.go | 35 ++++++++++ .../parser/testdata/imports/alias/main.go | 35 ++++++++++ .../testdata/imports/multiple_files/app.go | 35 ++++++++++ .../testdata/imports/multiple_files/main.go | 9 +++ .../testdata/imports/other_package/go.mod | 7 ++ .../testdata/imports/other_package/main.go | 9 +++ .../imports/other_package/subpackage/app.go | 35 ++++++++++ .../testdata/imports/single_file/main.go | 35 ++++++++++ exp/pkg/options/application.go | 1 + 26 files changed, 755 insertions(+) create mode 100644 exp/examples/binding/main.go create mode 100644 exp/examples/binding/models/person.go create mode 100644 exp/examples/binding/service.go create mode 100644 exp/internal/parser/boundstructs.go create mode 100644 exp/internal/parser/boundstructs_test.go create mode 100644 exp/internal/parser/calls.go create mode 100644 exp/internal/parser/calls_test.go create mode 100644 exp/internal/parser/imports.go create mode 100644 exp/internal/parser/imports_test.go create mode 100644 exp/internal/parser/options.go create mode 100644 exp/internal/parser/options_test.go create mode 100644 exp/internal/parser/testdata/boundstructs/struct_literal_multiple/main.go create mode 100644 exp/internal/parser/testdata/boundstructs/struct_literal_multiple_files/greet.go create mode 100644 exp/internal/parser/testdata/boundstructs/struct_literal_multiple_files/main.go create mode 100644 exp/internal/parser/testdata/boundstructs/struct_literal_multiple_files/other.go create mode 100644 exp/internal/parser/testdata/boundstructs/struct_literal_single/main.go create mode 100644 exp/internal/parser/testdata/imports/alias/main.go create mode 100644 exp/internal/parser/testdata/imports/multiple_files/app.go create mode 100644 exp/internal/parser/testdata/imports/multiple_files/main.go create mode 100644 exp/internal/parser/testdata/imports/other_package/go.mod create mode 100644 exp/internal/parser/testdata/imports/other_package/main.go create mode 100644 exp/internal/parser/testdata/imports/other_package/subpackage/app.go create mode 100644 exp/internal/parser/testdata/imports/single_file/main.go diff --git a/exp/examples/binding/main.go b/exp/examples/binding/main.go new file mode 100644 index 000000000..4fb639008 --- /dev/null +++ b/exp/examples/binding/main.go @@ -0,0 +1,35 @@ +package main + +import ( + _ "embed" + "log" + + "github.com/wailsapp/wails/exp/pkg/application" + "github.com/wailsapp/wails/exp/pkg/options" +) + +type GreetService struct { + SomeVariable int + lowerCase string +} + +func (*GreetService) Greet(name string) string { + return "Hello " + name +} + +func main() { + app := application.New(options.Application{ + Bind: []interface{}{ + &GreetService{}, + }, + }) + + app.NewWebviewWindow() + + err := app.Run() + + if err != nil { + log.Fatal(err) + } + +} diff --git a/exp/examples/binding/models/person.go b/exp/examples/binding/models/person.go new file mode 100644 index 000000000..0d0ab94db --- /dev/null +++ b/exp/examples/binding/models/person.go @@ -0,0 +1,5 @@ +package models + +type Person struct { + Name string +} diff --git a/exp/examples/binding/service.go b/exp/examples/binding/service.go new file mode 100644 index 000000000..ee8ef3cd8 --- /dev/null +++ b/exp/examples/binding/service.go @@ -0,0 +1,51 @@ +package main + +import ( + "github.com/wailsapp/wails/exp/pkg/application" + "github.com/wailsapp/wails/exp/pkg/options" +) + +//func appOptions() options.Application { +// return options.Application{ +// Bind: []interface{}{ +// &GreetService{}, +// }, +// } +//} + +//func appOptions() options.Application { +// result := options.Application{ +// Bind: []interface{}{ +// &GreetService{}, +// }, +// } +// return result +//} + +func appOptions() options.Application { + result := options.Application{ + Bind: []interface{}{ + &GreetService{}, + }, + } + return result +} + +func run() error { + //o := options.Application{ + // Bind: []interface{}{ + // &GreetService{}, + // }, + //} + //app := application.New(o) + + //app := application.New(options.Application{ + // Bind: []interface{}{ + // &GreetService{}, + // }, + //}) + + app := application.New(appOptions()) + + return app.Run() +} diff --git a/exp/go.mod b/exp/go.mod index fb6083c8a..c4a0aca45 100644 --- a/exp/go.mod +++ b/exp/go.mod @@ -8,6 +8,8 @@ require ( github.com/leaanthony/clir v1.3.0 github.com/leaanthony/winicon v1.0.0 github.com/pterm/pterm v0.12.51 + github.com/samber/lo v1.37.0 + github.com/stretchr/testify v1.8.1 github.com/tc-hib/winres v0.1.6 ) @@ -15,6 +17,7 @@ require ( atomicgo.dev/cursor v0.1.1 // indirect atomicgo.dev/keyboard v0.2.8 // indirect github.com/containerd/console v1.0.3 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/fatih/color v1.13.0 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect github.com/gookit/color v1.5.2 // indirect @@ -27,6 +30,7 @@ require ( github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/radovskyb/watcher v1.0.7 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/sajari/fuzzy v1.0.0 // indirect diff --git a/exp/go.sum b/exp/go.sum index 4a415d043..528092f09 100644 --- a/exp/go.sum +++ b/exp/go.sum @@ -86,12 +86,15 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/sajari/fuzzy v1.0.0 h1:+FmwVvJErsd0d0hAPlj4CxqxUtQY/fOoY0DwX4ykpRY= github.com/sajari/fuzzy v1.0.0/go.mod h1:OjYR6KxoWOe9+dOlXeiCJd4dIbED4Oo8wpS89o0pwOo= +github.com/samber/lo v1.37.0 h1:XjVcB8g6tgUp8rsPsJ2CvhClfImrpL04YpQHXeHPhRw= +github.com/samber/lo v1.37.0/go.mod h1:9vaz2O4o8oOnK23pd2TrXufcbdbJIa3b6cstBWKpopA= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -99,6 +102,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/tc-hib/winres v0.1.6 h1:qgsYHze+BxQPEYilxIz/KCQGaClvI2+yLBAZs+3+0B8= github.com/tc-hib/winres v0.1.6/go.mod h1:pe6dOR40VOrGz8PkzreVKNvEKnlE8t4yR8A8naL+t7A= github.com/wailsapp/task/v3 v3.19.1 h1:syDKYaPBXgrXKKSJVEWcOEoSFtZzpvxqlHf90YRukRc= diff --git a/exp/internal/parser/boundstructs.go b/exp/internal/parser/boundstructs.go new file mode 100644 index 000000000..5141aeb7a --- /dev/null +++ b/exp/internal/parser/boundstructs.go @@ -0,0 +1,47 @@ +package parser + +import "go/ast" + +type structInfo struct { + packageName string + structName string +} + +func extractBindExprs(imp *ImportSpecInfo) { + // Check if the given expression is a composite literal + if comp, ok := (*imp.Options).(*ast.CompositeLit); ok { + // Iterate through the composite literal fields + for _, field := range comp.Elts { + // Check if the field key is "Bind" + if kv, ok := field.(*ast.KeyValueExpr); ok { + if ident, ok := kv.Key.(*ast.Ident); ok { + if ident.Name == "Bind" { + // Extract the expressions in the Bind field + if arr, ok := kv.Value.(*ast.CompositeLit); ok { + for _, elt := range arr.Elts { + if unaryExpr, ok := elt.(*ast.UnaryExpr); ok { + if addr, ok := unaryExpr.X.(*ast.CompositeLit); ok { + // Extract the type of the struct + if selExpr, ok := addr.Type.(*ast.SelectorExpr); ok { + if ident, ok := selExpr.X.(*ast.Ident); ok { + imp.BoundStructNames = append(imp.BoundStructNames, &structInfo{ + packageName: ident.Name, + structName: selExpr.Sel.Name, + }) + } + } else if ident, ok := addr.Type.(*ast.Ident); ok { + imp.BoundStructNames = append(imp.BoundStructNames, &structInfo{ + packageName: "", + structName: ident.Name, + }) + } + } + } + } + } + } + } + } + } + } +} diff --git a/exp/internal/parser/boundstructs_test.go b/exp/internal/parser/boundstructs_test.go new file mode 100644 index 000000000..c91e3c65f --- /dev/null +++ b/exp/internal/parser/boundstructs_test.go @@ -0,0 +1,44 @@ +package parser + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func Test_extractBindExprs(t *testing.T) { + tests := []struct { + name string + dir string + expectedBoundStructs []*structInfo + }{ + { + name: "should find single bound struct literal", + dir: "testdata/boundstructs/struct_literal_single", + expectedBoundStructs: []*structInfo{{structName: "GreetService"}}, + }, + { + name: "should find multiple bound struct literal", + dir: "testdata/boundstructs/struct_literal_multiple", + expectedBoundStructs: []*structInfo{{structName: "GreetService"}, {structName: "OtherService"}}, + }, + { + name: "should find multiple bound struct literals over multiple files", + dir: "testdata/boundstructs/struct_literal_multiple_files", + expectedBoundStructs: []*structInfo{{structName: "GreetService"}, {structName: "OtherService"}}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + imports, err := findFilesImportingPackage(tt.dir, "github.com/wailsapp/wails/exp/pkg/application") + require.NoError(t, err) + imp := findNewCalls(imports) + require.NotNil(t, imp) + isOptions := isOptionsApplication(imp.Options) + require.True(t, isOptions) + extractBindExprs(imp) + require.ElementsMatchf(t, tt.expectedBoundStructs, imp.BoundStructNames, "expected %v, got %v", tt.expectedBoundStructs, imp.BoundStructNames) + + }) + } +} diff --git a/exp/internal/parser/calls.go b/exp/internal/parser/calls.go new file mode 100644 index 000000000..69bfca501 --- /dev/null +++ b/exp/internal/parser/calls.go @@ -0,0 +1,66 @@ +package parser + +import ( + "go/ast" + "os" +) + +func findNewCalls(imports []ImportSpecInfo) *ImportSpecInfo { + + var result *ast.Expr + var inImport *ImportSpecInfo + + for _, imp := range imports { + for _, decl := range imp.File.Decls { + ast.Inspect(decl, func(n ast.Node) bool { + // check if the current node is a function call + callExpr, ok := n.(*ast.CallExpr) + if !ok { + return true + } + + // check if the function being called is .New() + selExpr, ok := callExpr.Fun.(*ast.SelectorExpr) + if !ok || selExpr.Sel.Name != "New" { + return true + } + + // Get the name of the thing that New is being called on. + var receiverName string + switch rcv := selExpr.X.(type) { + case *ast.Ident: + receiverName = rcv.Name + case *ast.SelectorExpr: + receiverName = rcv.Sel.Name + default: + receiverName = "unknown" + } + + // Check if the receiver is a package name + for _, i := range imports { + if i.Identifier() == receiverName { + if i.ImportSpec.Path.Value == `"github.com/wailsapp/wails/exp/pkg/application"` { + // We have a call to application.New() + // Parse out the first argument and check it is an option.Application struct + // check callExpr.Args[0] is a struct literal + if len(callExpr.Args) != 1 { + return true + } + if result != nil { + println("Found more than one call to application.New()") + os.Exit(1) + } + result = &(callExpr.Args[0]) + inImport = &imp + + return false + } + } + } + return true + }) + } + } + inImport.Options = result + return inImport +} diff --git a/exp/internal/parser/calls_test.go b/exp/internal/parser/calls_test.go new file mode 100644 index 000000000..0aeaf2c38 --- /dev/null +++ b/exp/internal/parser/calls_test.go @@ -0,0 +1,34 @@ +package parser + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func Test_findNewCalls(t *testing.T) { + tests := []struct { + name string + dir string + expectedExpressions int + }{ + { + name: "should find single call to application.New", + dir: "testdata/boundstructs/struct_literal_single", + expectedExpressions: 1, + }, + { + name: "should find single call to application.New in multiple files", + dir: "testdata/boundstructs/struct_literal_multiple_files", + expectedExpressions: 1, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + imports, err := findFilesImportingPackage(tt.dir, "github.com/wailsapp/wails/exp/pkg/application") + require.NoError(t, err) + got := findNewCalls(imports) + require.NotNil(t, got.Options) + }) + } +} diff --git a/exp/internal/parser/imports.go b/exp/internal/parser/imports.go new file mode 100644 index 000000000..f43814ad5 --- /dev/null +++ b/exp/internal/parser/imports.go @@ -0,0 +1,69 @@ +package parser + +import ( + "go/ast" + "go/parser" + "go/token" + "os" + "path/filepath" + "strings" +) + +type ImportSpecInfo struct { + FileName string + ImportSpec *ast.ImportSpec + File *ast.File + Alias string + Options *ast.Expr + BoundStructNames []*structInfo +} + +func (i ImportSpecInfo) Identifier() string { + if i.Alias != "" { + return i.Alias + } + return strings.Trim(filepath.Base(i.ImportSpec.Path.Value), `"`) +} + +func findFilesImportingPackage(dir, pkg string) ([]ImportSpecInfo, error) { + var importSpecInfo []ImportSpecInfo + + // Recursively search for .go files in the given directory + err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if filepath.Ext(path) != ".go" { + return nil + } + + fset := token.NewFileSet() + f, err := parser.ParseFile(fset, path, nil, parser.AllErrors) + if err != nil { + return err + } + + // Search for import statement in the AST + for _, imp := range f.Imports { + if imp.Path.Value == "\""+pkg+"\"" { + var alias string + if imp.Name != nil { + alias = imp.Name.Name + } + importSpecInfo = append(importSpecInfo, ImportSpecInfo{ + FileName: path, + ImportSpec: imp, + Alias: alias, + File: f, + }) + } + } + return nil + }) + + if err != nil { + return nil, err + } + + return importSpecInfo, nil +} diff --git a/exp/internal/parser/imports_test.go b/exp/internal/parser/imports_test.go new file mode 100644 index 000000000..70dbd86d4 --- /dev/null +++ b/exp/internal/parser/imports_test.go @@ -0,0 +1,56 @@ +package parser + +import ( + "testing" + + "github.com/samber/lo" +) + +func Test_findFilesImportingPackage(t *testing.T) { + tests := []struct { + name string + dir string + pkg string + want []string + wantErr bool + }{ + { + name: "should identify single file importing package", + dir: "testdata/imports/single_file", + pkg: "github.com/wailsapp/wails/exp/pkg/application", + want: []string{"testdata/imports/single_file/main.go"}, + }, + { + name: "should identify multiple files importing package", + dir: "testdata/imports/multiple_files", + pkg: "github.com/wailsapp/wails/exp/pkg/application", + want: []string{"testdata/imports/multiple_files/app.go"}, + }, + { + name: "should identify aliases", + dir: "testdata/imports/alias", + pkg: "github.com/wailsapp/wails/exp/pkg/application", + want: []string{"testdata/imports/alias/main.go"}, + }, + { + name: "should identify packages", + dir: "testdata/imports/other_package", + pkg: "github.com/wailsapp/wails/exp/pkg/application", + want: []string{"testdata/imports/other_package/subpackage/app.go"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := findFilesImportingPackage(tt.dir, tt.pkg) + if (err != nil) != tt.wantErr { + t.Errorf("findFilesImportingPackage() error = %v, wantErr %v", err, tt.wantErr) + return + } + for _, imp := range got { + if !lo.Contains(tt.want, imp.FileName) { + t.Errorf("findFilesImportingPackage() = %v, want %v", got, tt.want) + } + } + }) + } +} diff --git a/exp/internal/parser/options.go b/exp/internal/parser/options.go new file mode 100644 index 000000000..b06122522 --- /dev/null +++ b/exp/internal/parser/options.go @@ -0,0 +1,22 @@ +package parser + +import ( + "go/ast" +) + +func isOptionsApplication(expr *ast.Expr) bool { + cl, ok := (*expr).(*ast.CompositeLit) + if ok { + se, ok := cl.Type.(*ast.SelectorExpr) + if ok { + _, ok := se.X.(*ast.Ident) + if ok { + if se.Sel.Name == "Application" && se.X.(*ast.Ident).Name == "options" { + return true + } + } + } + } + + return false +} diff --git a/exp/internal/parser/options_test.go b/exp/internal/parser/options_test.go new file mode 100644 index 000000000..c6e47ad0a --- /dev/null +++ b/exp/internal/parser/options_test.go @@ -0,0 +1,31 @@ +package parser + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func Test_isOptionsApplication(t *testing.T) { + tests := []struct { + name string + dir string + want bool + }{ + { + name: "should return true when expr is a struct literal", + dir: "testdata/boundstructs/struct_literal_single", + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + imports, err := findFilesImportingPackage(tt.dir, "github.com/wailsapp/wails/exp/pkg/application") + require.NoError(t, err) + imp := findNewCalls(imports) + require.NotNil(t, imp) + isOptions := isOptionsApplication(imp.Options) + require.Equal(t, tt.want, isOptions) + }) + } +} diff --git a/exp/internal/parser/testdata/boundstructs/struct_literal_multiple/main.go b/exp/internal/parser/testdata/boundstructs/struct_literal_multiple/main.go new file mode 100644 index 000000000..026f1266f --- /dev/null +++ b/exp/internal/parser/testdata/boundstructs/struct_literal_multiple/main.go @@ -0,0 +1,40 @@ +package main + +import ( + _ "embed" + "log" + + "github.com/wailsapp/wails/exp/pkg/application" + "github.com/wailsapp/wails/exp/pkg/options" +) + +type GreetService struct { + SomeVariable int + lowerCase string +} + +func (*GreetService) Greet(name string) string { + return "Hello " + name +} + +type OtherService struct { + t int +} + +func main() { + app := application.New(options.Application{ + Bind: []interface{}{ + &GreetService{}, + &OtherService{}, + }, + }) + + app.NewWebviewWindow() + + err := app.Run() + + if err != nil { + log.Fatal(err) + } + +} diff --git a/exp/internal/parser/testdata/boundstructs/struct_literal_multiple_files/greet.go b/exp/internal/parser/testdata/boundstructs/struct_literal_multiple_files/greet.go new file mode 100644 index 000000000..2a45396a7 --- /dev/null +++ b/exp/internal/parser/testdata/boundstructs/struct_literal_multiple_files/greet.go @@ -0,0 +1,14 @@ +package main + +import ( + _ "embed" +) + +type GreetService struct { + SomeVariable int + lowerCase string +} + +func (*GreetService) Greet(name string) string { + return "Hello " + name +} diff --git a/exp/internal/parser/testdata/boundstructs/struct_literal_multiple_files/main.go b/exp/internal/parser/testdata/boundstructs/struct_literal_multiple_files/main.go new file mode 100644 index 000000000..c96953f6e --- /dev/null +++ b/exp/internal/parser/testdata/boundstructs/struct_literal_multiple_files/main.go @@ -0,0 +1,27 @@ +package main + +import ( + _ "embed" + "log" + + "github.com/wailsapp/wails/exp/pkg/application" + "github.com/wailsapp/wails/exp/pkg/options" +) + +func main() { + app := application.New(options.Application{ + Bind: []interface{}{ + &GreetService{}, + &OtherService{}, + }, + }) + + app.NewWebviewWindow() + + err := app.Run() + + if err != nil { + log.Fatal(err) + } + +} diff --git a/exp/internal/parser/testdata/boundstructs/struct_literal_multiple_files/other.go b/exp/internal/parser/testdata/boundstructs/struct_literal_multiple_files/other.go new file mode 100644 index 000000000..c6e16377f --- /dev/null +++ b/exp/internal/parser/testdata/boundstructs/struct_literal_multiple_files/other.go @@ -0,0 +1,5 @@ +package main + +type OtherService struct { + t int +} diff --git a/exp/internal/parser/testdata/boundstructs/struct_literal_single/main.go b/exp/internal/parser/testdata/boundstructs/struct_literal_single/main.go new file mode 100644 index 000000000..4fb639008 --- /dev/null +++ b/exp/internal/parser/testdata/boundstructs/struct_literal_single/main.go @@ -0,0 +1,35 @@ +package main + +import ( + _ "embed" + "log" + + "github.com/wailsapp/wails/exp/pkg/application" + "github.com/wailsapp/wails/exp/pkg/options" +) + +type GreetService struct { + SomeVariable int + lowerCase string +} + +func (*GreetService) Greet(name string) string { + return "Hello " + name +} + +func main() { + app := application.New(options.Application{ + Bind: []interface{}{ + &GreetService{}, + }, + }) + + app.NewWebviewWindow() + + err := app.Run() + + if err != nil { + log.Fatal(err) + } + +} diff --git a/exp/internal/parser/testdata/imports/alias/main.go b/exp/internal/parser/testdata/imports/alias/main.go new file mode 100644 index 000000000..5125b75f6 --- /dev/null +++ b/exp/internal/parser/testdata/imports/alias/main.go @@ -0,0 +1,35 @@ +package main + +import ( + _ "embed" + "log" + + bob "github.com/wailsapp/wails/exp/pkg/application" + "github.com/wailsapp/wails/exp/pkg/options" +) + +type GreetService struct { + SomeVariable int + lowerCase string +} + +func (*GreetService) Greet(name string) string { + return "Hello " + name +} + +func main() { + app := bob.New(options.Application{ + Bind: []interface{}{ + &GreetService{}, + }, + }) + + app.NewWebviewWindow() + + err := app.Run() + + if err != nil { + log.Fatal(err) + } + +} diff --git a/exp/internal/parser/testdata/imports/multiple_files/app.go b/exp/internal/parser/testdata/imports/multiple_files/app.go new file mode 100644 index 000000000..0d1802b3d --- /dev/null +++ b/exp/internal/parser/testdata/imports/multiple_files/app.go @@ -0,0 +1,35 @@ +package main + +import ( + _ "embed" + "log" + + "github.com/wailsapp/wails/exp/pkg/application" + "github.com/wailsapp/wails/exp/pkg/options" +) + +type GreetService struct { + SomeVariable int + lowerCase string +} + +func (*GreetService) Greet(name string) string { + return "Hello " + name +} + +func run() { + app := application.New(options.Application{ + Bind: []interface{}{ + &GreetService{}, + }, + }) + + app.NewWebviewWindow() + + err := app.Run() + + if err != nil { + log.Fatal(err) + } + +} diff --git a/exp/internal/parser/testdata/imports/multiple_files/main.go b/exp/internal/parser/testdata/imports/multiple_files/main.go new file mode 100644 index 000000000..c0aced91b --- /dev/null +++ b/exp/internal/parser/testdata/imports/multiple_files/main.go @@ -0,0 +1,9 @@ +package main + +import ( + _ "embed" +) + +func main() { + run() +} diff --git a/exp/internal/parser/testdata/imports/other_package/go.mod b/exp/internal/parser/testdata/imports/other_package/go.mod new file mode 100644 index 000000000..4058e72ba --- /dev/null +++ b/exp/internal/parser/testdata/imports/other_package/go.mod @@ -0,0 +1,7 @@ +module other_package + +require github.com/wailsapp/wails/exp v0 + +go 1.19 + +replace github.com/wailsapp/wails/exp v0 => ../../../../../../ \ No newline at end of file diff --git a/exp/internal/parser/testdata/imports/other_package/main.go b/exp/internal/parser/testdata/imports/other_package/main.go new file mode 100644 index 000000000..bb616d756 --- /dev/null +++ b/exp/internal/parser/testdata/imports/other_package/main.go @@ -0,0 +1,9 @@ +package main + +import ( + "other_package/subpackage" +) + +func main() { + subpackage.Run() +} diff --git a/exp/internal/parser/testdata/imports/other_package/subpackage/app.go b/exp/internal/parser/testdata/imports/other_package/subpackage/app.go new file mode 100644 index 000000000..4c4c596fe --- /dev/null +++ b/exp/internal/parser/testdata/imports/other_package/subpackage/app.go @@ -0,0 +1,35 @@ +package subpackage + +import ( + _ "embed" + "log" + + "github.com/wailsapp/wails/exp/pkg/application" + "github.com/wailsapp/wails/exp/pkg/options" +) + +type GreetService struct { + SomeVariable int + lowerCase string +} + +func (*GreetService) Greet(name string) string { + return "Hello " + name +} + +func Run() { + app := application.New(options.Application{ + Bind: []interface{}{ + &GreetService{}, + }, + }) + + app.NewWebviewWindow() + + err := app.Run() + + if err != nil { + log.Fatal(err) + } + +} diff --git a/exp/internal/parser/testdata/imports/single_file/main.go b/exp/internal/parser/testdata/imports/single_file/main.go new file mode 100644 index 000000000..4fb639008 --- /dev/null +++ b/exp/internal/parser/testdata/imports/single_file/main.go @@ -0,0 +1,35 @@ +package main + +import ( + _ "embed" + "log" + + "github.com/wailsapp/wails/exp/pkg/application" + "github.com/wailsapp/wails/exp/pkg/options" +) + +type GreetService struct { + SomeVariable int + lowerCase string +} + +func (*GreetService) Greet(name string) string { + return "Hello " + name +} + +func main() { + app := application.New(options.Application{ + Bind: []interface{}{ + &GreetService{}, + }, + }) + + app.NewWebviewWindow() + + err := app.Run() + + if err != nil { + log.Fatal(err) + } + +} diff --git a/exp/pkg/options/application.go b/exp/pkg/options/application.go index 2359ce2bb..0b72ccc71 100644 --- a/exp/pkg/options/application.go +++ b/exp/pkg/options/application.go @@ -5,4 +5,5 @@ type Application struct { Description string Icon []byte Mac Mac + Bind []interface{} } From 8bbf5ff3f1959454c7073b70b96361c5929c8791 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 15 Jan 2023 20:25:42 +1100 Subject: [PATCH 77/85] Recursive bound model discovery implemented --- exp/examples/binding/main.go | 14 +- exp/examples/binding/service.go | 51 ---- exp/examples/binding/services/GreetService.go | 13 + exp/go.mod | 2 + exp/go.sum | 4 + exp/internal/parser/boundstructs.go | 47 --- exp/internal/parser/boundstructs_test.go | 44 --- exp/internal/parser/calls.go | 66 ----- exp/internal/parser/calls_test.go | 34 --- exp/internal/parser/imports.go | 69 ----- exp/internal/parser/imports_test.go | 56 ---- exp/internal/parser/options.go | 22 -- exp/internal/parser/options_test.go | 31 -- exp/internal/parser/packages.go | 268 ++++++++++++++++++ exp/internal/parser/packages_test.go | 58 ++++ .../parser/testdata/imports/alias/main.go | 35 --- .../testdata/imports/multiple_files/app.go | 35 --- .../testdata/imports/multiple_files/main.go | 9 - .../testdata/imports/other_package/go.mod | 7 - .../testdata/imports/other_package/main.go | 9 - .../imports/other_package/subpackage/app.go | 35 --- .../testdata/imports/single_file/main.go | 35 --- .../struct_literal_multiple/main.go | 0 .../struct_literal_multiple_files/greet.go | 0 .../struct_literal_multiple_files/main.go | 0 .../struct_literal_multiple_files/other.go | 0 .../struct_literal_single/main.go | 0 27 files changed, 350 insertions(+), 594 deletions(-) delete mode 100644 exp/examples/binding/service.go create mode 100644 exp/examples/binding/services/GreetService.go delete mode 100644 exp/internal/parser/boundstructs.go delete mode 100644 exp/internal/parser/boundstructs_test.go delete mode 100644 exp/internal/parser/calls.go delete mode 100644 exp/internal/parser/calls_test.go delete mode 100644 exp/internal/parser/imports.go delete mode 100644 exp/internal/parser/imports_test.go delete mode 100644 exp/internal/parser/options.go delete mode 100644 exp/internal/parser/options_test.go create mode 100644 exp/internal/parser/packages.go create mode 100644 exp/internal/parser/packages_test.go delete mode 100644 exp/internal/parser/testdata/imports/alias/main.go delete mode 100644 exp/internal/parser/testdata/imports/multiple_files/app.go delete mode 100644 exp/internal/parser/testdata/imports/multiple_files/main.go delete mode 100644 exp/internal/parser/testdata/imports/other_package/go.mod delete mode 100644 exp/internal/parser/testdata/imports/other_package/main.go delete mode 100644 exp/internal/parser/testdata/imports/other_package/subpackage/app.go delete mode 100644 exp/internal/parser/testdata/imports/single_file/main.go rename exp/internal/parser/testdata/{boundstructs => }/struct_literal_multiple/main.go (100%) rename exp/internal/parser/testdata/{boundstructs => }/struct_literal_multiple_files/greet.go (100%) rename exp/internal/parser/testdata/{boundstructs => }/struct_literal_multiple_files/main.go (100%) rename exp/internal/parser/testdata/{boundstructs => }/struct_literal_multiple_files/other.go (100%) rename exp/internal/parser/testdata/{boundstructs => }/struct_literal_single/main.go (100%) diff --git a/exp/examples/binding/main.go b/exp/examples/binding/main.go index 4fb639008..dc77f289b 100644 --- a/exp/examples/binding/main.go +++ b/exp/examples/binding/main.go @@ -4,23 +4,19 @@ import ( _ "embed" "log" + "github.com/wailsapp/wails/exp/examples/binding/services" + "github.com/wailsapp/wails/exp/pkg/application" "github.com/wailsapp/wails/exp/pkg/options" ) -type GreetService struct { - SomeVariable int - lowerCase string -} - -func (*GreetService) Greet(name string) string { - return "Hello " + name -} +type localStruct struct{} func main() { app := application.New(options.Application{ Bind: []interface{}{ - &GreetService{}, + &localStruct{}, + &services.GreetService{}, }, }) diff --git a/exp/examples/binding/service.go b/exp/examples/binding/service.go deleted file mode 100644 index ee8ef3cd8..000000000 --- a/exp/examples/binding/service.go +++ /dev/null @@ -1,51 +0,0 @@ -package main - -import ( - "github.com/wailsapp/wails/exp/pkg/application" - "github.com/wailsapp/wails/exp/pkg/options" -) - -//func appOptions() options.Application { -// return options.Application{ -// Bind: []interface{}{ -// &GreetService{}, -// }, -// } -//} - -//func appOptions() options.Application { -// result := options.Application{ -// Bind: []interface{}{ -// &GreetService{}, -// }, -// } -// return result -//} - -func appOptions() options.Application { - result := options.Application{ - Bind: []interface{}{ - &GreetService{}, - }, - } - return result -} - -func run() error { - //o := options.Application{ - // Bind: []interface{}{ - // &GreetService{}, - // }, - //} - //app := application.New(o) - - //app := application.New(options.Application{ - // Bind: []interface{}{ - // &GreetService{}, - // }, - //}) - - app := application.New(appOptions()) - - return app.Run() -} diff --git a/exp/examples/binding/services/GreetService.go b/exp/examples/binding/services/GreetService.go new file mode 100644 index 000000000..61afaffdd --- /dev/null +++ b/exp/examples/binding/services/GreetService.go @@ -0,0 +1,13 @@ +package services + +import "github.com/wailsapp/wails/exp/examples/binding/models" + +type GreetService struct { + SomeVariable int + lowercase string + Parent *models.Person +} + +func (*GreetService) Greet(name string) string { + return "Hello " + name +} diff --git a/exp/go.mod b/exp/go.mod index c4a0aca45..62732c088 100644 --- a/exp/go.mod +++ b/exp/go.mod @@ -11,6 +11,7 @@ require ( github.com/samber/lo v1.37.0 github.com/stretchr/testify v1.8.1 github.com/tc-hib/winres v0.1.6 + golang.org/x/tools v0.1.12 ) require ( @@ -37,6 +38,7 @@ require ( github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9 // indirect golang.org/x/image v0.0.0-20201208152932-35266b937fa6 // indirect + golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect golang.org/x/sync v0.1.0 // indirect golang.org/x/sys v0.3.0 // indirect golang.org/x/term v0.3.0 // indirect diff --git a/exp/go.sum b/exp/go.sum index 528092f09..2b249a9e5 100644 --- a/exp/go.sum +++ b/exp/go.sum @@ -116,6 +116,8 @@ golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9/go.mod h1:cyybsKvd6eL0RnXn6p golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20201208152932-35266b937fa6 h1:nfeHNc1nAqecKCy2FCy4HY+soOOe5sDLJ/gZLbx6GYI= golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -145,6 +147,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= diff --git a/exp/internal/parser/boundstructs.go b/exp/internal/parser/boundstructs.go deleted file mode 100644 index 5141aeb7a..000000000 --- a/exp/internal/parser/boundstructs.go +++ /dev/null @@ -1,47 +0,0 @@ -package parser - -import "go/ast" - -type structInfo struct { - packageName string - structName string -} - -func extractBindExprs(imp *ImportSpecInfo) { - // Check if the given expression is a composite literal - if comp, ok := (*imp.Options).(*ast.CompositeLit); ok { - // Iterate through the composite literal fields - for _, field := range comp.Elts { - // Check if the field key is "Bind" - if kv, ok := field.(*ast.KeyValueExpr); ok { - if ident, ok := kv.Key.(*ast.Ident); ok { - if ident.Name == "Bind" { - // Extract the expressions in the Bind field - if arr, ok := kv.Value.(*ast.CompositeLit); ok { - for _, elt := range arr.Elts { - if unaryExpr, ok := elt.(*ast.UnaryExpr); ok { - if addr, ok := unaryExpr.X.(*ast.CompositeLit); ok { - // Extract the type of the struct - if selExpr, ok := addr.Type.(*ast.SelectorExpr); ok { - if ident, ok := selExpr.X.(*ast.Ident); ok { - imp.BoundStructNames = append(imp.BoundStructNames, &structInfo{ - packageName: ident.Name, - structName: selExpr.Sel.Name, - }) - } - } else if ident, ok := addr.Type.(*ast.Ident); ok { - imp.BoundStructNames = append(imp.BoundStructNames, &structInfo{ - packageName: "", - structName: ident.Name, - }) - } - } - } - } - } - } - } - } - } - } -} diff --git a/exp/internal/parser/boundstructs_test.go b/exp/internal/parser/boundstructs_test.go deleted file mode 100644 index c91e3c65f..000000000 --- a/exp/internal/parser/boundstructs_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package parser - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func Test_extractBindExprs(t *testing.T) { - tests := []struct { - name string - dir string - expectedBoundStructs []*structInfo - }{ - { - name: "should find single bound struct literal", - dir: "testdata/boundstructs/struct_literal_single", - expectedBoundStructs: []*structInfo{{structName: "GreetService"}}, - }, - { - name: "should find multiple bound struct literal", - dir: "testdata/boundstructs/struct_literal_multiple", - expectedBoundStructs: []*structInfo{{structName: "GreetService"}, {structName: "OtherService"}}, - }, - { - name: "should find multiple bound struct literals over multiple files", - dir: "testdata/boundstructs/struct_literal_multiple_files", - expectedBoundStructs: []*structInfo{{structName: "GreetService"}, {structName: "OtherService"}}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - imports, err := findFilesImportingPackage(tt.dir, "github.com/wailsapp/wails/exp/pkg/application") - require.NoError(t, err) - imp := findNewCalls(imports) - require.NotNil(t, imp) - isOptions := isOptionsApplication(imp.Options) - require.True(t, isOptions) - extractBindExprs(imp) - require.ElementsMatchf(t, tt.expectedBoundStructs, imp.BoundStructNames, "expected %v, got %v", tt.expectedBoundStructs, imp.BoundStructNames) - - }) - } -} diff --git a/exp/internal/parser/calls.go b/exp/internal/parser/calls.go deleted file mode 100644 index 69bfca501..000000000 --- a/exp/internal/parser/calls.go +++ /dev/null @@ -1,66 +0,0 @@ -package parser - -import ( - "go/ast" - "os" -) - -func findNewCalls(imports []ImportSpecInfo) *ImportSpecInfo { - - var result *ast.Expr - var inImport *ImportSpecInfo - - for _, imp := range imports { - for _, decl := range imp.File.Decls { - ast.Inspect(decl, func(n ast.Node) bool { - // check if the current node is a function call - callExpr, ok := n.(*ast.CallExpr) - if !ok { - return true - } - - // check if the function being called is .New() - selExpr, ok := callExpr.Fun.(*ast.SelectorExpr) - if !ok || selExpr.Sel.Name != "New" { - return true - } - - // Get the name of the thing that New is being called on. - var receiverName string - switch rcv := selExpr.X.(type) { - case *ast.Ident: - receiverName = rcv.Name - case *ast.SelectorExpr: - receiverName = rcv.Sel.Name - default: - receiverName = "unknown" - } - - // Check if the receiver is a package name - for _, i := range imports { - if i.Identifier() == receiverName { - if i.ImportSpec.Path.Value == `"github.com/wailsapp/wails/exp/pkg/application"` { - // We have a call to application.New() - // Parse out the first argument and check it is an option.Application struct - // check callExpr.Args[0] is a struct literal - if len(callExpr.Args) != 1 { - return true - } - if result != nil { - println("Found more than one call to application.New()") - os.Exit(1) - } - result = &(callExpr.Args[0]) - inImport = &imp - - return false - } - } - } - return true - }) - } - } - inImport.Options = result - return inImport -} diff --git a/exp/internal/parser/calls_test.go b/exp/internal/parser/calls_test.go deleted file mode 100644 index 0aeaf2c38..000000000 --- a/exp/internal/parser/calls_test.go +++ /dev/null @@ -1,34 +0,0 @@ -package parser - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func Test_findNewCalls(t *testing.T) { - tests := []struct { - name string - dir string - expectedExpressions int - }{ - { - name: "should find single call to application.New", - dir: "testdata/boundstructs/struct_literal_single", - expectedExpressions: 1, - }, - { - name: "should find single call to application.New in multiple files", - dir: "testdata/boundstructs/struct_literal_multiple_files", - expectedExpressions: 1, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - imports, err := findFilesImportingPackage(tt.dir, "github.com/wailsapp/wails/exp/pkg/application") - require.NoError(t, err) - got := findNewCalls(imports) - require.NotNil(t, got.Options) - }) - } -} diff --git a/exp/internal/parser/imports.go b/exp/internal/parser/imports.go deleted file mode 100644 index f43814ad5..000000000 --- a/exp/internal/parser/imports.go +++ /dev/null @@ -1,69 +0,0 @@ -package parser - -import ( - "go/ast" - "go/parser" - "go/token" - "os" - "path/filepath" - "strings" -) - -type ImportSpecInfo struct { - FileName string - ImportSpec *ast.ImportSpec - File *ast.File - Alias string - Options *ast.Expr - BoundStructNames []*structInfo -} - -func (i ImportSpecInfo) Identifier() string { - if i.Alias != "" { - return i.Alias - } - return strings.Trim(filepath.Base(i.ImportSpec.Path.Value), `"`) -} - -func findFilesImportingPackage(dir, pkg string) ([]ImportSpecInfo, error) { - var importSpecInfo []ImportSpecInfo - - // Recursively search for .go files in the given directory - err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if filepath.Ext(path) != ".go" { - return nil - } - - fset := token.NewFileSet() - f, err := parser.ParseFile(fset, path, nil, parser.AllErrors) - if err != nil { - return err - } - - // Search for import statement in the AST - for _, imp := range f.Imports { - if imp.Path.Value == "\""+pkg+"\"" { - var alias string - if imp.Name != nil { - alias = imp.Name.Name - } - importSpecInfo = append(importSpecInfo, ImportSpecInfo{ - FileName: path, - ImportSpec: imp, - Alias: alias, - File: f, - }) - } - } - return nil - }) - - if err != nil { - return nil, err - } - - return importSpecInfo, nil -} diff --git a/exp/internal/parser/imports_test.go b/exp/internal/parser/imports_test.go deleted file mode 100644 index 70dbd86d4..000000000 --- a/exp/internal/parser/imports_test.go +++ /dev/null @@ -1,56 +0,0 @@ -package parser - -import ( - "testing" - - "github.com/samber/lo" -) - -func Test_findFilesImportingPackage(t *testing.T) { - tests := []struct { - name string - dir string - pkg string - want []string - wantErr bool - }{ - { - name: "should identify single file importing package", - dir: "testdata/imports/single_file", - pkg: "github.com/wailsapp/wails/exp/pkg/application", - want: []string{"testdata/imports/single_file/main.go"}, - }, - { - name: "should identify multiple files importing package", - dir: "testdata/imports/multiple_files", - pkg: "github.com/wailsapp/wails/exp/pkg/application", - want: []string{"testdata/imports/multiple_files/app.go"}, - }, - { - name: "should identify aliases", - dir: "testdata/imports/alias", - pkg: "github.com/wailsapp/wails/exp/pkg/application", - want: []string{"testdata/imports/alias/main.go"}, - }, - { - name: "should identify packages", - dir: "testdata/imports/other_package", - pkg: "github.com/wailsapp/wails/exp/pkg/application", - want: []string{"testdata/imports/other_package/subpackage/app.go"}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := findFilesImportingPackage(tt.dir, tt.pkg) - if (err != nil) != tt.wantErr { - t.Errorf("findFilesImportingPackage() error = %v, wantErr %v", err, tt.wantErr) - return - } - for _, imp := range got { - if !lo.Contains(tt.want, imp.FileName) { - t.Errorf("findFilesImportingPackage() = %v, want %v", got, tt.want) - } - } - }) - } -} diff --git a/exp/internal/parser/options.go b/exp/internal/parser/options.go deleted file mode 100644 index b06122522..000000000 --- a/exp/internal/parser/options.go +++ /dev/null @@ -1,22 +0,0 @@ -package parser - -import ( - "go/ast" -) - -func isOptionsApplication(expr *ast.Expr) bool { - cl, ok := (*expr).(*ast.CompositeLit) - if ok { - se, ok := cl.Type.(*ast.SelectorExpr) - if ok { - _, ok := se.X.(*ast.Ident) - if ok { - if se.Sel.Name == "Application" && se.X.(*ast.Ident).Name == "options" { - return true - } - } - } - } - - return false -} diff --git a/exp/internal/parser/options_test.go b/exp/internal/parser/options_test.go deleted file mode 100644 index c6e47ad0a..000000000 --- a/exp/internal/parser/options_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package parser - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func Test_isOptionsApplication(t *testing.T) { - tests := []struct { - name string - dir string - want bool - }{ - { - name: "should return true when expr is a struct literal", - dir: "testdata/boundstructs/struct_literal_single", - want: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - imports, err := findFilesImportingPackage(tt.dir, "github.com/wailsapp/wails/exp/pkg/application") - require.NoError(t, err) - imp := findNewCalls(imports) - require.NotNil(t, imp) - isOptions := isOptionsApplication(imp.Options) - require.Equal(t, tt.want, isOptions) - }) - } -} diff --git a/exp/internal/parser/packages.go b/exp/internal/parser/packages.go new file mode 100644 index 000000000..28474caf0 --- /dev/null +++ b/exp/internal/parser/packages.go @@ -0,0 +1,268 @@ +package parser + +import ( + "go/ast" + "go/parser" + "go/token" + "strings" + + "github.com/samber/lo" + + "golang.org/x/tools/go/packages" +) + +type parsedPackage struct { + name string + pkg *ast.Package + boundStructs []*ast.TypeSpec +} + +type Context struct { + packages map[string]*parsedPackage +} + +func ParseDirectory(dir string) (*Context, error) { + // Parse the directory + fset := token.NewFileSet() + pkgs, err := parser.ParseDir(fset, dir, nil, parser.AllErrors) + if err != nil { + return nil, err + } + + context := &Context{ + packages: make(map[string]*parsedPackage), + } + + // Iterate through the packages + for _, pkg := range pkgs { + context.packages[pkg.Name] = &parsedPackage{ + name: pkg.Name, + pkg: pkg, + } + } + + findApplicationNewCalls(context) + + return context, nil +} + +func findApplicationNewCalls(context *Context) { + // Iterate through the packages + currentPackages := lo.Keys(context.packages) + + for _, packageName := range currentPackages { + thisPackage := context.packages[packageName] + println("Parsing package", packageName) + // Iterate through the package's files + for _, file := range thisPackage.pkg.Files { + // Use an ast.Inspector to find the calls to application.New + ast.Inspect(file, func(n ast.Node) bool { + // Check if the node is a call expression + callExpr, ok := n.(*ast.CallExpr) + if !ok { + return true + } + + // Check if the function being called is "application.New" + selExpr, ok := callExpr.Fun.(*ast.SelectorExpr) + if !ok { + return true + } + if selExpr.Sel.Name != "New" { + return true + } + if id, ok := selExpr.X.(*ast.Ident); !ok || id.Name != "application" { + return true + } + + // Check there is only 1 argument + if len(callExpr.Args) != 1 { + return true + } + + // Check argument 1 is a struct literal + structLit, ok := callExpr.Args[0].(*ast.CompositeLit) + if !ok { + return true + } + + // Check struct literal is of type "options.Application" + selectorExpr, ok := structLit.Type.(*ast.SelectorExpr) + if !ok { + return true + } + if selectorExpr.Sel.Name != "Application" { + return true + } + if id, ok := selectorExpr.X.(*ast.Ident); !ok || id.Name != "options" { + return true + } + + for _, elt := range structLit.Elts { + // Find the "Bind" field + kvExpr, ok := elt.(*ast.KeyValueExpr) + if !ok { + continue + } + if id, ok := kvExpr.Key.(*ast.Ident); !ok || id.Name != "Bind" { + continue + } + // Check the value is a slice of interfaces + sliceExpr, ok := kvExpr.Value.(*ast.CompositeLit) + if !ok { + continue + } + var arrayType *ast.ArrayType + if arrayType, ok = sliceExpr.Type.(*ast.ArrayType); !ok { + continue + } + + // Check array type is of type "interface{}" + if _, ok := arrayType.Elt.(*ast.InterfaceType); !ok { + continue + } + // Iterate through the slice elements + for _, elt := range sliceExpr.Elts { + // Check the element is a unary expression + unaryExpr, ok := elt.(*ast.UnaryExpr) + if ok { + // Check the unary expression is a composite lit + boundStructLit, ok := unaryExpr.X.(*ast.CompositeLit) + if !ok { + continue + } + // Check if the composite lit is a struct + if _, ok := boundStructLit.Type.(*ast.StructType); ok { + // Parse struct + continue + } + // Check if the lit is an ident + ident, ok := boundStructLit.Type.(*ast.Ident) + if ok { + if ident.Obj == nil { + println("Ident.Obj is nil - check") + continue + } + // Check if the ident is a struct type + if _, ok := ident.Obj.Decl.(*ast.TypeSpec); ok { + thisPackage.boundStructs = append(thisPackage.boundStructs, ident.Obj.Decl.(*ast.TypeSpec)) + continue + } + // Check the typespec decl is a struct + if _, ok := ident.Obj.Decl.(*ast.StructType); ok { + continue + } + + } + // Check if the lit is a selector + selector, ok := boundStructLit.Type.(*ast.SelectorExpr) + if ok { + getStructsFromSelector(selector, file, context) + continue + } + } + } + } + + return true + }) + } + } +} + +func getStructsFromSelector(selector *ast.SelectorExpr, file *ast.File, context *Context) { + // extract package name from selector + packageName := selector.X.(*ast.Ident).Name + + if context.packages[packageName] == nil { + context.packages[packageName] = &parsedPackage{ + name: packageName, + } + } + + // extract struct name from selector + structName := selector.Sel.Name + + // Find the package name from the imports + for _, imp := range file.Imports { + var match bool + if imp.Name == nil || imp.Name.Name == packageName { + match = true + } + if match == false { + pathSplit := strings.Split(imp.Path.Value, "/") + endPath := strings.Trim(pathSplit[len(pathSplit)-1], `"`) + match = endPath == packageName + } + + if match { + // We have the import + cfg := &packages.Config{ + Mode: packages.NeedName | packages.NeedFiles | packages.NeedImports | packages.NeedDeps | packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedModule, + } + pkgs, err := packages.Load(cfg, strings.Trim(imp.Path.Value, `"`)) + if err != nil { + panic(err) + } + foundPackage := pkgs[0] + + // Iterate the files in the package and find struct types + for _, parsedFile := range foundPackage.Syntax { + ast.Inspect(parsedFile, func(n ast.Node) bool { + if n == nil { + return false + } + switch n.(type) { + case *ast.TypeSpec: + typeSpec := n.(*ast.TypeSpec) + if typeSpec.Name.Name == structName { + context.packages[packageName].boundStructs = append(context.packages[packageName].boundStructs, typeSpec) + findNestedStructs(typeSpec, parsedFile, packageName, context) + } + } + return true + }) + } + + continue + } + } + +} + +func findNestedStructs(t *ast.TypeSpec, parsedFile *ast.File, pkgName string, context *Context) (localStructs []*ast.TypeSpec, externalStructs []*ast.SelectorExpr) { + structType, ok := t.Type.(*ast.StructType) + if !ok { + return nil, nil + } + for _, field := range structType.Fields.List { + for _, ident := range field.Names { + switch t := ident.Obj.Decl.(*ast.Field).Type.(type) { + case *ast.Ident: + if t.Obj == nil { + continue + } + if t.Obj.Kind == ast.Typ { + if _, ok := t.Obj.Decl.(*ast.TypeSpec); ok { + context.packages[pkgName].boundStructs = append(context.packages[pkgName].boundStructs, t.Obj.Decl.(*ast.TypeSpec)) + } + } + case *ast.SelectorExpr: + if ident, ok := t.X.(*ast.Ident); ok { + if ident.IsExported() { + getStructsFromSelector(t, parsedFile, context) + } + } + case *ast.StarExpr: + if sel, ok := t.X.(*ast.SelectorExpr); ok { + if _, ok := sel.X.(*ast.Ident); ok { + if ident.IsExported() { + getStructsFromSelector(sel, parsedFile, context) + } + } + } + } + } + } + return localStructs, externalStructs +} diff --git a/exp/internal/parser/packages_test.go b/exp/internal/parser/packages_test.go new file mode 100644 index 000000000..a3c319dd3 --- /dev/null +++ b/exp/internal/parser/packages_test.go @@ -0,0 +1,58 @@ +package parser + +import ( + "testing" + + "github.com/samber/lo" + "github.com/stretchr/testify/require" +) + +func TestParseDirectory(t *testing.T) { + tests := []struct { + name string + dir string + want []string + wantErr bool + }{ + { + name: "should find single bound service", + dir: "testdata/struct_literal_single", + want: []string{"GreetService"}, + wantErr: false, + }, + { + name: "should find multiple bound services", + dir: "testdata/struct_literal_multiple", + want: []string{"main.GreetService", "main.OtherService"}, + wantErr: false, + }, + { + name: "should find multiple bound services over multiple files", + dir: "testdata/struct_literal_multiple_files", + want: []string{"main.GreetService", "main.OtherService"}, + wantErr: false, + }, + { + name: "should find bound services from other packages", + dir: "../../examples/binding", + want: []string{"main.localStruct", "services.GreetService", "models.Person"}, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := ParseDirectory(tt.dir) + if (err != nil) != tt.wantErr { + t.Errorf("ParseDirectory() error = %v, wantErr %v", err, tt.wantErr) + return + } + for name, pkg := range got.packages { + println("Got package", name) + for _, boundStruct := range pkg.boundStructs { + println("Got bound struct", boundStruct.Name.Name) + require.True(t, lo.Contains(tt.want, name+"."+boundStruct.Name.Name)) + } + } + }) + } +} diff --git a/exp/internal/parser/testdata/imports/alias/main.go b/exp/internal/parser/testdata/imports/alias/main.go deleted file mode 100644 index 5125b75f6..000000000 --- a/exp/internal/parser/testdata/imports/alias/main.go +++ /dev/null @@ -1,35 +0,0 @@ -package main - -import ( - _ "embed" - "log" - - bob "github.com/wailsapp/wails/exp/pkg/application" - "github.com/wailsapp/wails/exp/pkg/options" -) - -type GreetService struct { - SomeVariable int - lowerCase string -} - -func (*GreetService) Greet(name string) string { - return "Hello " + name -} - -func main() { - app := bob.New(options.Application{ - Bind: []interface{}{ - &GreetService{}, - }, - }) - - app.NewWebviewWindow() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/exp/internal/parser/testdata/imports/multiple_files/app.go b/exp/internal/parser/testdata/imports/multiple_files/app.go deleted file mode 100644 index 0d1802b3d..000000000 --- a/exp/internal/parser/testdata/imports/multiple_files/app.go +++ /dev/null @@ -1,35 +0,0 @@ -package main - -import ( - _ "embed" - "log" - - "github.com/wailsapp/wails/exp/pkg/application" - "github.com/wailsapp/wails/exp/pkg/options" -) - -type GreetService struct { - SomeVariable int - lowerCase string -} - -func (*GreetService) Greet(name string) string { - return "Hello " + name -} - -func run() { - app := application.New(options.Application{ - Bind: []interface{}{ - &GreetService{}, - }, - }) - - app.NewWebviewWindow() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/exp/internal/parser/testdata/imports/multiple_files/main.go b/exp/internal/parser/testdata/imports/multiple_files/main.go deleted file mode 100644 index c0aced91b..000000000 --- a/exp/internal/parser/testdata/imports/multiple_files/main.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import ( - _ "embed" -) - -func main() { - run() -} diff --git a/exp/internal/parser/testdata/imports/other_package/go.mod b/exp/internal/parser/testdata/imports/other_package/go.mod deleted file mode 100644 index 4058e72ba..000000000 --- a/exp/internal/parser/testdata/imports/other_package/go.mod +++ /dev/null @@ -1,7 +0,0 @@ -module other_package - -require github.com/wailsapp/wails/exp v0 - -go 1.19 - -replace github.com/wailsapp/wails/exp v0 => ../../../../../../ \ No newline at end of file diff --git a/exp/internal/parser/testdata/imports/other_package/main.go b/exp/internal/parser/testdata/imports/other_package/main.go deleted file mode 100644 index bb616d756..000000000 --- a/exp/internal/parser/testdata/imports/other_package/main.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import ( - "other_package/subpackage" -) - -func main() { - subpackage.Run() -} diff --git a/exp/internal/parser/testdata/imports/other_package/subpackage/app.go b/exp/internal/parser/testdata/imports/other_package/subpackage/app.go deleted file mode 100644 index 4c4c596fe..000000000 --- a/exp/internal/parser/testdata/imports/other_package/subpackage/app.go +++ /dev/null @@ -1,35 +0,0 @@ -package subpackage - -import ( - _ "embed" - "log" - - "github.com/wailsapp/wails/exp/pkg/application" - "github.com/wailsapp/wails/exp/pkg/options" -) - -type GreetService struct { - SomeVariable int - lowerCase string -} - -func (*GreetService) Greet(name string) string { - return "Hello " + name -} - -func Run() { - app := application.New(options.Application{ - Bind: []interface{}{ - &GreetService{}, - }, - }) - - app.NewWebviewWindow() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/exp/internal/parser/testdata/imports/single_file/main.go b/exp/internal/parser/testdata/imports/single_file/main.go deleted file mode 100644 index 4fb639008..000000000 --- a/exp/internal/parser/testdata/imports/single_file/main.go +++ /dev/null @@ -1,35 +0,0 @@ -package main - -import ( - _ "embed" - "log" - - "github.com/wailsapp/wails/exp/pkg/application" - "github.com/wailsapp/wails/exp/pkg/options" -) - -type GreetService struct { - SomeVariable int - lowerCase string -} - -func (*GreetService) Greet(name string) string { - return "Hello " + name -} - -func main() { - app := application.New(options.Application{ - Bind: []interface{}{ - &GreetService{}, - }, - }) - - app.NewWebviewWindow() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/exp/internal/parser/testdata/boundstructs/struct_literal_multiple/main.go b/exp/internal/parser/testdata/struct_literal_multiple/main.go similarity index 100% rename from exp/internal/parser/testdata/boundstructs/struct_literal_multiple/main.go rename to exp/internal/parser/testdata/struct_literal_multiple/main.go diff --git a/exp/internal/parser/testdata/boundstructs/struct_literal_multiple_files/greet.go b/exp/internal/parser/testdata/struct_literal_multiple_files/greet.go similarity index 100% rename from exp/internal/parser/testdata/boundstructs/struct_literal_multiple_files/greet.go rename to exp/internal/parser/testdata/struct_literal_multiple_files/greet.go diff --git a/exp/internal/parser/testdata/boundstructs/struct_literal_multiple_files/main.go b/exp/internal/parser/testdata/struct_literal_multiple_files/main.go similarity index 100% rename from exp/internal/parser/testdata/boundstructs/struct_literal_multiple_files/main.go rename to exp/internal/parser/testdata/struct_literal_multiple_files/main.go diff --git a/exp/internal/parser/testdata/boundstructs/struct_literal_multiple_files/other.go b/exp/internal/parser/testdata/struct_literal_multiple_files/other.go similarity index 100% rename from exp/internal/parser/testdata/boundstructs/struct_literal_multiple_files/other.go rename to exp/internal/parser/testdata/struct_literal_multiple_files/other.go diff --git a/exp/internal/parser/testdata/boundstructs/struct_literal_single/main.go b/exp/internal/parser/testdata/struct_literal_single/main.go similarity index 100% rename from exp/internal/parser/testdata/boundstructs/struct_literal_single/main.go rename to exp/internal/parser/testdata/struct_literal_single/main.go From b0b96c98389da753ea5fe99b22519eae9d665698 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Mon, 16 Jan 2023 20:30:05 +1100 Subject: [PATCH 78/85] Support struct discovery in methods --- exp/examples/binding/services/GreetService.go | 12 +- exp/internal/parser/packages.go | 146 ++++++++++++++++-- exp/internal/parser/packages_test.go | 11 +- 3 files changed, 150 insertions(+), 19 deletions(-) diff --git a/exp/examples/binding/services/GreetService.go b/exp/examples/binding/services/GreetService.go index 61afaffdd..72ea44cd7 100644 --- a/exp/examples/binding/services/GreetService.go +++ b/exp/examples/binding/services/GreetService.go @@ -1,6 +1,8 @@ package services -import "github.com/wailsapp/wails/exp/examples/binding/models" +import ( + "github.com/wailsapp/wails/exp/examples/binding/models" +) type GreetService struct { SomeVariable int @@ -11,3 +13,11 @@ type GreetService struct { func (*GreetService) Greet(name string) string { return "Hello " + name } + +func (g *GreetService) GetPerson() *models.Person { + return g.Parent +} + +func (g *GreetService) SetPerson(person *models.Person) { + g.Parent = person +} diff --git a/exp/internal/parser/packages.go b/exp/internal/parser/packages.go index 28474caf0..56283e5d9 100644 --- a/exp/internal/parser/packages.go +++ b/exp/internal/parser/packages.go @@ -1,6 +1,7 @@ package parser import ( + "fmt" "go/ast" "go/parser" "go/token" @@ -11,10 +12,18 @@ import ( "golang.org/x/tools/go/packages" ) +var Debug = false + +func debug(msg string, args ...interface{}) { + if Debug { + println(fmt.Sprintf(msg, args...)) + } +} + type parsedPackage struct { name string pkg *ast.Package - boundStructs []*ast.TypeSpec + boundStructs map[string]*ast.TypeSpec } type Context struct { @@ -36,8 +45,9 @@ func ParseDirectory(dir string) (*Context, error) { // Iterate through the packages for _, pkg := range pkgs { context.packages[pkg.Name] = &parsedPackage{ - name: pkg.Name, - pkg: pkg, + name: pkg.Name, + pkg: pkg, + boundStructs: make(map[string]*ast.TypeSpec), } } @@ -52,7 +62,7 @@ func findApplicationNewCalls(context *Context) { for _, packageName := range currentPackages { thisPackage := context.packages[packageName] - println("Parsing package", packageName) + debug("Parsing package: %s", packageName) // Iterate through the package's files for _, file := range thisPackage.pkg.Files { // Use an ast.Inspector to find the calls to application.New @@ -140,12 +150,13 @@ func findApplicationNewCalls(context *Context) { ident, ok := boundStructLit.Type.(*ast.Ident) if ok { if ident.Obj == nil { - println("Ident.Obj is nil - check") + debug("Ident.Obj is nil - check") continue } // Check if the ident is a struct type - if _, ok := ident.Obj.Decl.(*ast.TypeSpec); ok { - thisPackage.boundStructs = append(thisPackage.boundStructs, ident.Obj.Decl.(*ast.TypeSpec)) + if t, ok := ident.Obj.Decl.(*ast.TypeSpec); ok { + thisPackage.boundStructs[ident.Name] = t + findNestedStructs(t, file, packageName, context) continue } // Check the typespec decl is a struct @@ -171,12 +182,15 @@ func findApplicationNewCalls(context *Context) { } func getStructsFromSelector(selector *ast.SelectorExpr, file *ast.File, context *Context) { + debug("getStructsFromSelector called with selector '%s' on file '%s.go'", selector.Sel.Name, file.Name.Name) + // extract package name from selector packageName := selector.X.(*ast.Ident).Name if context.packages[packageName] == nil { context.packages[packageName] = &parsedPackage{ - name: packageName, + name: packageName, + boundStructs: make(map[string]*ast.TypeSpec), } } @@ -216,8 +230,12 @@ func getStructsFromSelector(selector *ast.SelectorExpr, file *ast.File, context case *ast.TypeSpec: typeSpec := n.(*ast.TypeSpec) if typeSpec.Name.Name == structName { - context.packages[packageName].boundStructs = append(context.packages[packageName].boundStructs, typeSpec) - findNestedStructs(typeSpec, parsedFile, packageName, context) + if _, ok := context.packages[packageName].boundStructs[structName]; !ok { + debug("Adding struct '%s' in package '%s'", structName, packageName) + context.packages[packageName].boundStructs[typeSpec.Name.Name] = typeSpec + findNestedStructs(typeSpec, parsedFile, packageName, context) + } + return false } } return true @@ -230,10 +248,11 @@ func getStructsFromSelector(selector *ast.SelectorExpr, file *ast.File, context } -func findNestedStructs(t *ast.TypeSpec, parsedFile *ast.File, pkgName string, context *Context) (localStructs []*ast.TypeSpec, externalStructs []*ast.SelectorExpr) { +func findNestedStructs(t *ast.TypeSpec, parsedFile *ast.File, pkgName string, context *Context) { + debug("findNestedStructs called with type '%s' on file '%s.go'", t.Name.Name, parsedFile.Name.Name) structType, ok := t.Type.(*ast.StructType) if !ok { - return nil, nil + return } for _, field := range structType.Fields.List { for _, ident := range field.Names { @@ -244,7 +263,11 @@ func findNestedStructs(t *ast.TypeSpec, parsedFile *ast.File, pkgName string, co } if t.Obj.Kind == ast.Typ { if _, ok := t.Obj.Decl.(*ast.TypeSpec); ok { - context.packages[pkgName].boundStructs = append(context.packages[pkgName].boundStructs, t.Obj.Decl.(*ast.TypeSpec)) + if _, ok := context.packages[pkgName].boundStructs[t.Name]; !ok { + debug("Adding nested struct '%s' to package '%s'", t.Name, pkgName) + context.packages[pkgName].boundStructs[t.Name] = t.Obj.Decl.(*ast.TypeSpec) + findNestedStructs(t.Obj.Decl.(*ast.TypeSpec), parsedFile, pkgName, context) + } } } case *ast.SelectorExpr: @@ -264,5 +287,100 @@ func findNestedStructs(t *ast.TypeSpec, parsedFile *ast.File, pkgName string, co } } } - return localStructs, externalStructs + findStructsInMethods(t.Name.Name, parsedFile, pkgName, context) + +} + +func findStructsInMethods(name string, parsedFile *ast.File, pkgName string, context *Context) { + debug("findStructsInMethods called with type '%s' on file '%s.go'", name, parsedFile.Name.Name) + // Find the struct declaration for the given name + var structDecl *ast.TypeSpec + for _, decl := range parsedFile.Decls { + if fn, ok := decl.(*ast.FuncDecl); ok { + // check the receiver name is the same as the name given + if fn.Recv == nil { + continue + } + // Check if the receiver is a pointer + if starExpr, ok := fn.Recv.List[0].Type.(*ast.StarExpr); ok { + if ident, ok := starExpr.X.(*ast.Ident); ok { + if ident.Name != name { + continue + } + } + } else { + if ident, ok := fn.Recv.List[0].Type.(*ast.Ident); ok { + if ident.Name != name { + continue + } + } + } + findStructsInMethodParams(fn, parsedFile, pkgName, context) + } + } + if structDecl == nil { + return + } + // Iterate the methods in the struct + +} + +func findStructsInMethodParams(f *ast.FuncDecl, parsedFile *ast.File, pkgName string, context *Context) { + debug("findStructsInMethodParams called with type '%s' on file '%s.go'", f.Name.Name, parsedFile.Name.Name) + if f.Type.Params == nil { + for _, field := range f.Type.Params.List { + parseField(field, parsedFile, pkgName, context) + } + } + if f.Type.Results != nil { + for _, field := range f.Type.Results.List { + parseField(field, parsedFile, pkgName, context) + } + } +} + +func parseField(field *ast.Field, parsedFile *ast.File, pkgName string, context *Context) { + if se, ok := field.Type.(*ast.StarExpr); ok { + // Check if the star expr is a struct + if selExp, ok := se.X.(*ast.SelectorExpr); ok { + getStructsFromSelector(selExp, parsedFile, context) + return + } + if ident, ok := se.X.(*ast.Ident); ok { + if ident.Obj == nil { + return + } + if ident.Obj.Kind == ast.Typ { + if _, ok := ident.Obj.Decl.(*ast.TypeSpec); ok { + if _, ok := context.packages[pkgName].boundStructs[ident.Name]; !ok { + debug("Adding field struct '%s' to package '%s'", ident.Name, pkgName) + context.packages[pkgName].boundStructs[ident.Name] = ident.Obj.Decl.(*ast.TypeSpec) + findNestedStructs(ident.Obj.Decl.(*ast.TypeSpec), parsedFile, pkgName, context) + } else { + debug("Struct %s already bound", ident.Name) + } + } + } + } + } + if selExp, ok := field.Type.(*ast.SelectorExpr); ok { + getStructsFromSelector(selExp, parsedFile, context) + return + } + if ident, ok := field.Type.(*ast.Ident); ok { + if ident.Obj == nil { + return + } + if ident.Obj.Kind == ast.Typ { + if _, ok := ident.Obj.Decl.(*ast.TypeSpec); ok { + if _, ok := context.packages[pkgName].boundStructs[ident.Name]; !ok { + debug("Adding field struct '%s' to package '%s'", ident.Name, pkgName) + context.packages[pkgName].boundStructs[ident.Name] = ident.Obj.Decl.(*ast.TypeSpec) + findNestedStructs(ident.Obj.Decl.(*ast.TypeSpec), parsedFile, pkgName, context) + } else { + debug("Struct %s already bound", ident.Name) + } + } + } + } } diff --git a/exp/internal/parser/packages_test.go b/exp/internal/parser/packages_test.go index a3c319dd3..e4f2131d3 100644 --- a/exp/internal/parser/packages_test.go +++ b/exp/internal/parser/packages_test.go @@ -41,18 +41,21 @@ func TestParseDirectory(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + Debug = true got, err := ParseDirectory(tt.dir) if (err != nil) != tt.wantErr { t.Errorf("ParseDirectory() error = %v, wantErr %v", err, tt.wantErr) return } + for name, pkg := range got.packages { - println("Got package", name) - for _, boundStruct := range pkg.boundStructs { - println("Got bound struct", boundStruct.Name.Name) - require.True(t, lo.Contains(tt.want, name+"."+boundStruct.Name.Name)) + for structName, _ := range pkg.boundStructs { + require.True(t, lo.Contains(tt.want, name+"."+structName)) + tt.want = lo.Without(tt.want, name+"."+structName) } } + require.Empty(t, tt.want) + }) } } From 0a09363db70ed8cbe3a40d29015cfba364454737 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Tue, 17 Jan 2023 07:45:41 +1100 Subject: [PATCH 79/85] Support struct discovery over multiple files --- exp/internal/parser/packages.go | 93 +++++++++++++++++++++++++++- exp/internal/parser/packages_test.go | 51 ++++++++++++++- 2 files changed, 142 insertions(+), 2 deletions(-) diff --git a/exp/internal/parser/packages.go b/exp/internal/parser/packages.go index 56283e5d9..07ffda4ff 100644 --- a/exp/internal/parser/packages.go +++ b/exp/internal/parser/packages.go @@ -1,10 +1,12 @@ package parser import ( + "bytes" "fmt" "go/ast" "go/parser" "go/token" + "go/types" "strings" "github.com/samber/lo" @@ -30,6 +32,16 @@ type Context struct { packages map[string]*parsedPackage } +func (c *Context) GetBoundStructs() map[string][]*ast.TypeSpec { + structs := make(map[string][]*ast.TypeSpec) + for _, pkg := range c.packages { + for _, structType := range pkg.boundStructs { + structs[pkg.name] = append(structs[pkg.name], structType) + } + } + return structs +} + func ParseDirectory(dir string) (*Context, error) { // Parse the directory fset := token.NewFileSet() @@ -150,7 +162,9 @@ func findApplicationNewCalls(context *Context) { ident, ok := boundStructLit.Type.(*ast.Ident) if ok { if ident.Obj == nil { - debug("Ident.Obj is nil - check") + structTypeSpec := findStructInPackage(thisPackage.pkg, ident.Name) + thisPackage.boundStructs[ident.Name] = structTypeSpec + findNestedStructs(structTypeSpec, file, packageName, context) continue } // Check if the ident is a struct type @@ -384,3 +398,80 @@ func parseField(field *ast.Field, parsedFile *ast.File, pkgName string, context } } } + +func findStructInPackage(pkg *ast.Package, name string) *ast.TypeSpec { + for _, file := range pkg.Files { + for _, decl := range file.Decls { + if gen, ok := decl.(*ast.GenDecl); ok && gen.Tok == token.TYPE { + for _, spec := range gen.Specs { + if typeSpec, ok := spec.(*ast.TypeSpec); ok { + if typeSpec.Name.Name == name { + if _, ok := typeSpec.Type.(*ast.StructType); ok { + return typeSpec + } + } + } + } + } + } + } + return nil +} + +var goToTS = map[string]string{ + "int": "number", + "int8": "number", + "int16": "number", + "int32": "number", + "int64": "number", + "uint": "number", + "uint8": "number", + "uint16": "number", + "uint32": "number", + "uint64": "number", + "float32": "number", + "float64": "number", + "string": "string", + "bool": "boolean", +} + +func GenerateTypeScript(specs map[string][]*ast.TypeSpec) ([]byte, error) { + var buf bytes.Buffer + + for pkg, pkgSpecs := range specs { + if _, err := fmt.Fprintf(&buf, "namespace %s {\n", pkg); err != nil { + return nil, err + } + + for _, spec := range pkgSpecs { + if structType, ok := spec.Type.(*ast.StructType); ok { + if _, err := fmt.Fprintf(&buf, " class %s {\n", spec.Name.Name); err != nil { + return nil, err + } + + for _, field := range structType.Fields.List { + // Get the Go type of the field + goType := types.ExprString(field.Type) + // Look up the corresponding TypeScript type + tsType, ok := goToTS[goType] + if !ok { + tsType = goType + } + + if _, err := fmt.Fprintf(&buf, " %s: %s;\n", field.Names[0].Name, tsType); err != nil { + return nil, err + } + } + + if _, err := fmt.Fprintf(&buf, " }\n"); err != nil { + return nil, err + } + } + } + + if _, err := fmt.Fprintf(&buf, "}\n"); err != nil { + return nil, err + } + } + return buf.Bytes(), nil +} diff --git a/exp/internal/parser/packages_test.go b/exp/internal/parser/packages_test.go index e4f2131d3..339034fd1 100644 --- a/exp/internal/parser/packages_test.go +++ b/exp/internal/parser/packages_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/samber/lo" + "github.com/stretchr/testify/require" ) @@ -17,7 +18,7 @@ func TestParseDirectory(t *testing.T) { { name: "should find single bound service", dir: "testdata/struct_literal_single", - want: []string{"GreetService"}, + want: []string{"main.GreetService"}, wantErr: false, }, { @@ -55,6 +56,54 @@ func TestParseDirectory(t *testing.T) { } } require.Empty(t, tt.want) + }) + } +} + +func TestGenerateTypeScript(t *testing.T) { + tests := []struct { + name string + dir string + want string + wantErr bool + }{ + { + name: "should find single bound service", + dir: "testdata/struct_literal_single", + want: "", + wantErr: false, + }, + { + name: "should find multiple bound services", + dir: "testdata/struct_literal_multiple", + want: "", + wantErr: false, + }, + { + name: "should find multiple bound services over multiple files", + dir: "testdata/struct_literal_multiple_files", + want: "", + wantErr: false, + }, + { + name: "should find bound services from other packages", + dir: "../../examples/binding", + want: "", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + Debug = true + context, err := ParseDirectory(tt.dir) + if (err != nil) != tt.wantErr { + t.Errorf("ParseDirectory() error = %v, wantErr %v", err, tt.wantErr) + return + } + + ts, err := GenerateTypeScript(context.GetBoundStructs()) + require.NoError(t, err) + require.Equal(t, ts, tt.want) }) } From 8e593e9c35088d67bf2b3c02050c1c7694d6c11f Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Tue, 17 Jan 2023 18:57:35 +1100 Subject: [PATCH 80/85] Start of TS models generation support --- exp/internal/parser/packages.go | 163 ++++++++++++++++++++++++--- exp/internal/parser/packages_test.go | 62 +++++++--- 2 files changed, 198 insertions(+), 27 deletions(-) diff --git a/exp/internal/parser/packages.go b/exp/internal/parser/packages.go index 07ffda4ff..797907a25 100644 --- a/exp/internal/parser/packages.go +++ b/exp/internal/parser/packages.go @@ -7,7 +7,9 @@ import ( "go/parser" "go/token" "go/types" + "sort" "strings" + "unicode" "github.com/samber/lo" @@ -418,6 +420,11 @@ func findStructInPackage(pkg *ast.Package, name string) *ast.TypeSpec { return nil } +type Package struct { + Name string + Specs []*ast.TypeSpec +} + var goToTS = map[string]string{ "int": "number", "int8": "number", @@ -435,31 +442,156 @@ var goToTS = map[string]string{ "bool": "boolean", } -func GenerateTypeScript(specs map[string][]*ast.TypeSpec) ([]byte, error) { - var buf bytes.Buffer +//func GenerateModels(specs map[string][]*ast.TypeSpec) ([]byte, error) { +// var buf bytes.Buffer +// var packages []Package +// for pkg, pkgSpecs := range specs { +// packages = append(packages, Package{Name: pkg, Specs: pkgSpecs}) +// } +// sort.Slice(packages, func(i, j int) bool { return packages[i].Name < packages[j].Name }) +// for _, pkg := range packages { +// if _, err := fmt.Fprintf(&buf, "namespace %s {\n", pkg.Name); err != nil { +// return nil, err +// } +// sort.Slice(pkg.Specs, func(i, j int) bool { return pkg.Specs[i].Name.Name < pkg.Specs[j].Name.Name }) +// for _, spec := range pkg.Specs { +// if structType, ok := spec.Type.(*ast.StructType); ok { +// if _, err := fmt.Fprintf(&buf, " class %s {\n", spec.Name.Name); err != nil { +// return nil, err +// } +// +// for _, field := range structType.Fields.List { +// +// // Get the Go type of the field +// goType := types.ExprString(field.Type) +// // Look up the corresponding TypeScript type +// tsType, ok := goToTS[goType] +// if !ok { +// tsType = goType +// } +// +// if _, err := fmt.Fprintf(&buf, " %s: %s;\n", field.Names[0].Name, tsType); err != nil { +// return nil, err +// } +// } +// +// if _, err := fmt.Fprintf(&buf, " }\n"); err != nil { +// return nil, err +// } +// if _, err := fmt.Fprintf(&buf, " }\n"); err != nil { +// return nil, err +// } +// } +// } +// +// if _, err := fmt.Fprintf(&buf, "}\n"); err != nil { +// return nil, err +// } +// } +// return buf.Bytes(), nil +//} +type allModels struct { + known map[string]map[string]struct{} +} + +func NewAllModels(models map[string][]*ast.TypeSpec) *allModels { + result := &allModels{known: make(map[string]map[string]struct{})} + // iterate over all models + for pkg, pkgSpecs := range models { + for _, spec := range pkgSpecs { + result.known[pkg] = make(map[string]struct{}) + result.known[pkg][spec.Name.Name] = struct{}{} + } + } + return result +} + +func (k *allModels) exists(name string) bool { + // Split the name into package and type + parts := strings.Split(name, ".") + typ := parts[0] + pkg := "main" + if len(parts) == 2 { + pkg = parts[0] + typ = parts[1] + } + + knownPkg, ok := k.known[pkg] + if !ok { + return false + } + _, ok = knownPkg[typ] + return ok +} + +func GenerateModels(specs map[string][]*ast.TypeSpec) ([]byte, error) { + var buf bytes.Buffer + var packages []Package for pkg, pkgSpecs := range specs { - if _, err := fmt.Fprintf(&buf, "namespace %s {\n", pkg); err != nil { + packages = append(packages, Package{Name: pkg, Specs: pkgSpecs}) + } + knownStructs := NewAllModels(specs) + sort.Slice(packages, func(i, j int) bool { return packages[i].Name < packages[j].Name }) + for _, pkg := range packages { + if _, err := fmt.Fprintf(&buf, "namespace %s {\n", pkg.Name); err != nil { return nil, err } - - for _, spec := range pkgSpecs { + sort.Slice(pkg.Specs, func(i, j int) bool { return pkg.Specs[i].Name.Name < pkg.Specs[j].Name.Name }) + for _, spec := range pkg.Specs { if structType, ok := spec.Type.(*ast.StructType); ok { if _, err := fmt.Fprintf(&buf, " class %s {\n", spec.Name.Name); err != nil { return nil, err } for _, field := range structType.Fields.List { - // Get the Go type of the field - goType := types.ExprString(field.Type) - // Look up the corresponding TypeScript type - tsType, ok := goToTS[goType] - if !ok { - tsType = goType + + // Ignore field names that have a lower case first letter + if !unicode.IsUpper(rune(field.Names[0].Name[0])) { + continue } - if _, err := fmt.Fprintf(&buf, " %s: %s;\n", field.Names[0].Name, tsType); err != nil { - return nil, err + // Get the Go type of the field + goType := types.ExprString(field.Type) + // Check if the type is an array + if arrayType, ok := field.Type.(*ast.ArrayType); ok { + // Get the element type of the array + elementType := types.ExprString(arrayType.Elt) + // Look up the corresponding TypeScript type + tsType, ok := goToTS[elementType] + if !ok { + // strip off the * prefix if it is there + if strings.HasPrefix(elementType, "*") { + elementType = elementType[1:] + } + if knownStructs.exists(elementType) { + tsType = elementType + } else { + tsType = "any" + } + } + // Output the field as an array of the corresponding TypeScript type + if _, err := fmt.Fprintf(&buf, " %s: %s[];\n", field.Names[0].Name, tsType); err != nil { + return nil, err + } + } else { + // strip off the * prefix if it is there + if strings.HasPrefix(goType, "*") { + goType = goType[1:] + } + // Look up the corresponding TypeScript type + tsType, ok := goToTS[goType] + if !ok { + if knownStructs.exists(goType) { + tsType = goType + } else { + tsType = "any" + } + } + // Output the field as the corresponding TypeScript type + if _, err := fmt.Fprintf(&buf, " %s: %s;\n", field.Names[0].Name, tsType); err != nil { + return nil, err + } } } @@ -475,3 +607,8 @@ func GenerateTypeScript(specs map[string][]*ast.TypeSpec) ([]byte, error) { } return buf.Bytes(), nil } + +func isLowerCaseFirstLetter(s string) bool { + r := []rune(s) + return unicode.IsLower(r[0]) +} diff --git a/exp/internal/parser/packages_test.go b/exp/internal/parser/packages_test.go index 339034fd1..086ed7307 100644 --- a/exp/internal/parser/packages_test.go +++ b/exp/internal/parser/packages_test.go @@ -68,27 +68,61 @@ func TestGenerateTypeScript(t *testing.T) { wantErr bool }{ { - name: "should find single bound service", - dir: "testdata/struct_literal_single", - want: "", + name: "should find single bound service", + dir: "testdata/struct_literal_single", + want: `namespace main { + class GreetService { + SomeVariable: number; + } +} +`, wantErr: false, }, { - name: "should find multiple bound services", - dir: "testdata/struct_literal_multiple", - want: "", + name: "should find multiple bound services", + dir: "testdata/struct_literal_multiple", + want: `namespace main { + class GreetService { + SomeVariable: number; + } + class OtherService { + } +} +`, wantErr: false, }, { - name: "should find multiple bound services over multiple files", - dir: "testdata/struct_literal_multiple_files", - want: "", + name: "should find multiple bound services over multiple files", + dir: "testdata/struct_literal_multiple_files", + want: `namespace main { + class GreetService { + SomeVariable: number; + } + class OtherService { + } +} +`, wantErr: false, }, { - name: "should find bound services from other packages", - dir: "../../examples/binding", - want: "", + name: "should find bound services from other packages", + dir: "../../examples/binding", + want: `namespace main { + class localStruct { + } +} +namespace models { + class Person { + Name: string; + } +} +namespace services { + class GreetService { + SomeVariable: number; + Parent: models.Person; + } +} +`, wantErr: false, }, } @@ -101,9 +135,9 @@ func TestGenerateTypeScript(t *testing.T) { return } - ts, err := GenerateTypeScript(context.GetBoundStructs()) + ts, err := GenerateModels(context.GetBoundStructs()) require.NoError(t, err) - require.Equal(t, ts, tt.want) + require.Equal(t, tt.want, string(ts)) }) } From a4f729a6a0374e7f33a367842f13ed8ba848223c Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 18 Jan 2023 08:22:31 +1100 Subject: [PATCH 81/85] Rename parser package. Fix linting issues Add README.md --- exp/internal/parser/README.md | 24 +++++++++++++++++++ .../parser/{packages.go => parser.go} | 17 +++++-------- .../{packages_test.go => parser_test.go} | 2 +- 3 files changed, 31 insertions(+), 12 deletions(-) create mode 100644 exp/internal/parser/README.md rename exp/internal/parser/{packages.go => parser.go} (97%) rename exp/internal/parser/{packages_test.go => parser_test.go} (98%) diff --git a/exp/internal/parser/README.md b/exp/internal/parser/README.md new file mode 100644 index 000000000..59de0d749 --- /dev/null +++ b/exp/internal/parser/README.md @@ -0,0 +1,24 @@ +# Parser + +This package contains the static analyser used for parsing Wails projects so that we may: + +- Generate the bindings for the frontend +- Generate Typescript definitions for the structs used by the bindings + +## Implemented + +- [x] Parsing of structs +- [x] Generation of models + - [x] Scalars + - [x] Arrays + - [ ] Maps + - [x] Structs +- [ ] Generation of bindings + +## Limitations + +There are many ways to write a Go program so there are many different program structures that we would need to support. This is a work in progress and will be improved over time. The current limitations are: + +- The call to `application.New()` must be in the `main` package +- Bound structs must be declared as struct literals + diff --git a/exp/internal/parser/packages.go b/exp/internal/parser/parser.go similarity index 97% rename from exp/internal/parser/packages.go rename to exp/internal/parser/parser.go index 797907a25..61d2d9c8d 100644 --- a/exp/internal/parser/packages.go +++ b/exp/internal/parser/parser.go @@ -495,7 +495,7 @@ type allModels struct { known map[string]map[string]struct{} } -func NewAllModels(models map[string][]*ast.TypeSpec) *allModels { +func newAllModels(models map[string][]*ast.TypeSpec) *allModels { result := &allModels{known: make(map[string]map[string]struct{})} // iterate over all models for pkg, pkgSpecs := range models { @@ -527,13 +527,13 @@ func (k *allModels) exists(name string) bool { func GenerateModels(specs map[string][]*ast.TypeSpec) ([]byte, error) { var buf bytes.Buffer - var packages []Package + var pkgs []Package for pkg, pkgSpecs := range specs { - packages = append(packages, Package{Name: pkg, Specs: pkgSpecs}) + pkgs = append(pkgs, Package{Name: pkg, Specs: pkgSpecs}) } - knownStructs := NewAllModels(specs) - sort.Slice(packages, func(i, j int) bool { return packages[i].Name < packages[j].Name }) - for _, pkg := range packages { + knownStructs := newAllModels(specs) + sort.Slice(pkgs, func(i, j int) bool { return pkgs[i].Name < pkgs[j].Name }) + for _, pkg := range pkgs { if _, err := fmt.Fprintf(&buf, "namespace %s {\n", pkg.Name); err != nil { return nil, err } @@ -607,8 +607,3 @@ func GenerateModels(specs map[string][]*ast.TypeSpec) ([]byte, error) { } return buf.Bytes(), nil } - -func isLowerCaseFirstLetter(s string) bool { - r := []rune(s) - return unicode.IsLower(r[0]) -} diff --git a/exp/internal/parser/packages_test.go b/exp/internal/parser/parser_test.go similarity index 98% rename from exp/internal/parser/packages_test.go rename to exp/internal/parser/parser_test.go index 086ed7307..092b91ef6 100644 --- a/exp/internal/parser/packages_test.go +++ b/exp/internal/parser/parser_test.go @@ -50,7 +50,7 @@ func TestParseDirectory(t *testing.T) { } for name, pkg := range got.packages { - for structName, _ := range pkg.boundStructs { + for structName := range pkg.boundStructs { require.True(t, lo.Contains(tt.want, name+"."+structName)) tt.want = lo.Without(tt.want, name+"."+structName) } From b4d64678b584a1aeb45a59761ec4379a85a0e21f Mon Sep 17 00:00:00 2001 From: stffabi Date: Tue, 10 Jan 2023 20:30:32 +0100 Subject: [PATCH 82/85] Basic integration of the assetserver --- exp/examples/plain/main.go | 10 ++++++- exp/go.mod | 5 ++++ exp/go.sum | 14 ++++++++++ exp/internal/runtime/assets.go | 26 ++++++++++++++++++ exp/internal/runtime/assets_dev.go | 27 ++++++++++++++++++ exp/pkg/application/application.go | 29 ++++++++++++++++++++ exp/pkg/application/application_darwin.go | 9 ++++++ exp/pkg/application/webview_window.go | 23 ++++++++++++++++ exp/pkg/application/webview_window.h | 2 +- exp/pkg/application/webview_window.m | 16 +++++++++++ exp/pkg/application/webview_window_darwin.go | 6 ++++ 11 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 exp/internal/runtime/assets.go create mode 100644 exp/internal/runtime/assets_dev.go diff --git a/exp/examples/plain/main.go b/exp/examples/plain/main.go index 0f7171083..ea2728758 100644 --- a/exp/examples/plain/main.go +++ b/exp/examples/plain/main.go @@ -3,6 +3,7 @@ package main import ( _ "embed" "log" + "net/http" "github.com/wailsapp/wails/exp/pkg/options" @@ -20,13 +21,20 @@ func main() { // Create window app.NewWebviewWindowWithOptions(&options.WebviewWindow{ Title: "Plain Bundle", - HTML: `Plain Bundle

Plain Bundle

This is a plain bundle. It has no frontend code.

`, CSS: `body { background-color: rgba(255, 255, 255, 0); } .main { color: white; margin: 20%; }`, Mac: options.MacWindow{ InvisibleTitleBarHeight: 50, Backdrop: options.MacBackdropTranslucent, TitleBar: options.TitleBarHiddenInset, }, + + URL: "/", + Assets: options.Assets{ + Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + w.Write([]byte(`Plain Bundle

Plain Bundle

This is a plain bundle. It has no frontend code but this was Served by the AssetServer's Handler

`)) + }), + }, }) err := app.Run() diff --git a/exp/go.mod b/exp/go.mod index 62732c088..41406f11b 100644 --- a/exp/go.mod +++ b/exp/go.mod @@ -22,7 +22,9 @@ require ( github.com/fatih/color v1.13.0 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect github.com/gookit/color v1.5.2 // indirect + github.com/imdario/mergo v0.3.12 // indirect github.com/joho/godotenv v1.4.0 // indirect + github.com/leaanthony/slicer v1.5.0 // indirect github.com/lithammer/fuzzysearch v1.1.5 // indirect github.com/mattn/go-colorable v0.1.11 // indirect github.com/mattn/go-isatty v0.0.14 // indirect @@ -35,10 +37,13 @@ require ( github.com/radovskyb/watcher v1.0.7 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/sajari/fuzzy v1.0.0 // indirect + github.com/wailsapp/mimetype v1.4.1 // indirect + github.com/wailsapp/wails/v2 v2.3.2-0.20230117193915-45c3a501d9e6 // indirect github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9 // indirect golang.org/x/image v0.0.0-20201208152932-35266b937fa6 // indirect golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect + golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect golang.org/x/sync v0.1.0 // indirect golang.org/x/sys v0.3.0 // indirect golang.org/x/term v0.3.0 // indirect diff --git a/exp/go.sum b/exp/go.sum index 2b249a9e5..5939a361b 100644 --- a/exp/go.sum +++ b/exp/go.sum @@ -28,6 +28,8 @@ github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQ github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= github.com/gookit/color v1.5.2 h1:uLnfXcaFjlrDnQDT+NCBcfhrXqYTx/rcCa6xn01Y8yI= github.com/gookit/color v1.5.2/go.mod h1:w8h4bGiHeeBpvQVePTutdbERIUf3oJE5lZ8HM0UgXyg= +github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/jackmordaunt/icns/v2 v2.2.1 h1:MGklwYP2yohKn2Bw7XxlF69LZe98S1vUfl5OvAulPwg= github.com/jackmordaunt/icns/v2 v2.2.1/go.mod h1:6aYIB9eSzyfHHMKqDf17Xrs1zetQPReAkiUSHzdw4cI= github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= @@ -45,6 +47,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= github.com/leaanthony/clir v1.3.0 h1:L9nPDWrmc/qU9UWZZvRaFajWYuO0np9V5p+5gxyYno0= github.com/leaanthony/clir v1.3.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= +github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0HtY= +github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY= github.com/leaanthony/winicon v1.0.0 h1:ZNt5U5dY71oEoKZ97UVwJRT4e+5xo5o/ieKuHuk8NqQ= github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU= github.com/lithammer/fuzzysearch v1.1.5 h1:Ag7aKU08wp0R9QCfF4GoGST9HbmAIeLP7xwMrOBEp1c= @@ -105,8 +109,12 @@ github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKs github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/tc-hib/winres v0.1.6 h1:qgsYHze+BxQPEYilxIz/KCQGaClvI2+yLBAZs+3+0B8= github.com/tc-hib/winres v0.1.6/go.mod h1:pe6dOR40VOrGz8PkzreVKNvEKnlE8t4yR8A8naL+t7A= +github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs= +github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= github.com/wailsapp/task/v3 v3.19.1 h1:syDKYaPBXgrXKKSJVEWcOEoSFtZzpvxqlHf90YRukRc= github.com/wailsapp/task/v3 v3.19.1/go.mod h1:y7rWakbLR5gFElGgo6rA2dyr6vU/zNIDVfn3S4Of6OI= +github.com/wailsapp/wails/v2 v2.3.2-0.20230117193915-45c3a501d9e6 h1:Wn+nhnS+VytzE0PegUzSh4T3hXJCtggKGD/4U5H9+wQ= +github.com/wailsapp/wails/v2 v2.3.2-0.20230117193915-45c3a501d9e6/go.mod h1:zlNLI0E2c2qA6miiuAHtp0Bac8FaGH0tlhA19OssR/8= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -119,6 +127,9 @@ golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+o golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -128,6 +139,7 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -135,6 +147,7 @@ golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -155,6 +168,7 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8X gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/exp/internal/runtime/assets.go b/exp/internal/runtime/assets.go new file mode 100644 index 000000000..bf3caa37f --- /dev/null +++ b/exp/internal/runtime/assets.go @@ -0,0 +1,26 @@ +//go:build production + +package runtime + +var RuntimeAssetsBundle = &RuntimeAssets{ + desktopIPC: DesktopIPC, + runtimeDesktopJS: DesktopRuntime, +} + +type RuntimeAssets struct { + desktopIPC []byte + websocketIPC []byte + runtimeDesktopJS []byte +} + +func (r *RuntimeAssets) DesktopIPC() []byte { + return r.desktopIPC +} + +func (r *RuntimeAssets) WebsocketIPC() []byte { + return r.websocketIPC +} + +func (r *RuntimeAssets) RuntimeDesktopJS() []byte { + return r.runtimeDesktopJS +} diff --git a/exp/internal/runtime/assets_dev.go b/exp/internal/runtime/assets_dev.go new file mode 100644 index 000000000..1d9915d33 --- /dev/null +++ b/exp/internal/runtime/assets_dev.go @@ -0,0 +1,27 @@ +//go:build !production + +package runtime + +var RuntimeAssetsBundle = &RuntimeAssets{ + desktopIPC: DesktopIPC, + websocketIPC: WebsocketIPC, + runtimeDesktopJS: DesktopRuntime, +} + +type RuntimeAssets struct { + desktopIPC []byte + websocketIPC []byte + runtimeDesktopJS []byte +} + +func (r *RuntimeAssets) DesktopIPC() []byte { + return r.desktopIPC +} + +func (r *RuntimeAssets) WebsocketIPC() []byte { + return r.websocketIPC +} + +func (r *RuntimeAssets) RuntimeDesktopJS() []byte { + return r.runtimeDesktopJS +} diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index 28a102f44..69dacd91e 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -8,6 +8,8 @@ import ( "github.com/wailsapp/wails/exp/pkg/events" "github.com/wailsapp/wails/exp/pkg/options" + + "github.com/wailsapp/wails/v2/pkg/assetserver/webview" ) var globalApplication *App @@ -65,6 +67,13 @@ type windowMessage struct { var windowMessageBuffer = make(chan *windowMessage) +type webViewAssetRequest struct { + windowId uint + request webview.Request +} + +var webviewRequests = make(chan *webViewAssetRequest) + type App struct { options options.Application applicationEventListeners map[uint][]func() @@ -178,6 +187,13 @@ func (a *App) Run() error { a.handleWindowEvent(event) } }() + go func() { + for { + event := <-webviewRequests + a.handleWebViewRequest(event) + event.request.Release() + } + }() go func() { for { event := <-windowMessageBuffer @@ -236,6 +252,19 @@ func (a *App) handleWindowMessage(event *windowMessage) { window.handleMessage(event.message) } +func (a *App) handleWebViewRequest(event *webViewAssetRequest) { + // Get window from window map + a.windowsLock.Lock() + window, ok := a.windows[event.windowId] + a.windowsLock.Unlock() + if !ok { + log.Printf("WebviewWindow #%d not found", event.windowId) + return + } + // Get callback from window + window.handleWebViewRequest(event.request) +} + func (a *App) handleWindowEvent(event *WindowEvent) { // Get window from window map a.windowsLock.Lock() diff --git a/exp/pkg/application/application_darwin.go b/exp/pkg/application/application_darwin.go index 48fb30a0f..be665d362 100644 --- a/exp/pkg/application/application_darwin.go +++ b/exp/pkg/application/application_darwin.go @@ -119,6 +119,7 @@ import ( "unsafe" "github.com/wailsapp/wails/exp/pkg/events" + "github.com/wailsapp/wails/v2/pkg/assetserver/webview" ) type macosApp struct { @@ -203,6 +204,14 @@ func processMessage(windowID C.uint, message *C.char) { } } +//export processURLRequest +func processURLRequest(windowID C.uint, wkUrlSchemeTask unsafe.Pointer) { + webviewRequests <- &webViewAssetRequest{ + windowId: uint(windowID), + request: webview.NewRequest(wkUrlSchemeTask), + } +} + //export processMenuItemClick func processMenuItemClick(menuID C.uint) { menuItemClicked <- uint(menuID) diff --git a/exp/pkg/application/webview_window.go b/exp/pkg/application/webview_window.go index 6e6849830..33356f083 100644 --- a/exp/pkg/application/webview_window.go +++ b/exp/pkg/application/webview_window.go @@ -4,8 +4,12 @@ import ( "fmt" "sync" + "github.com/wailsapp/wails/exp/internal/runtime" "github.com/wailsapp/wails/exp/pkg/events" "github.com/wailsapp/wails/exp/pkg/options" + "github.com/wailsapp/wails/v2/pkg/assetserver" + "github.com/wailsapp/wails/v2/pkg/assetserver/webview" + assetserveroptions "github.com/wailsapp/wails/v2/pkg/options/assetserver" ) type ( @@ -63,6 +67,8 @@ type WebviewWindow struct { implLock sync.RWMutex id uint + assets *assetserver.AssetServer + eventListeners map[uint][]func() eventListenersLock sync.RWMutex } @@ -84,10 +90,21 @@ func NewWindow(options *options.WebviewWindow) *WebviewWindow { if options.Height == 0 { options.Height = 600 } + + opts := assetserveroptions.Options{Assets: options.Assets.FS, Handler: options.Assets.Handler, Middleware: options.Assets.Middleware} + // TODO Bindings, Logger, ServingFrom disk? + srv, err := assetserver.NewAssetServer("", opts, false, nil, runtime.RuntimeAssetsBundle) + if err != nil { + // TODO handle errors + panic(err) + } + return &WebviewWindow{ id: getWindowID(), options: options, eventListeners: make(map[uint][]func()), + + assets: srv, } } @@ -326,6 +343,12 @@ func (w *WebviewWindow) handleMessage(message string) { } } +func (w *WebviewWindow) handleWebViewRequest(request webview.Request) { + url, _ := request.URL() + fmt.Printf("[window %d] Request %s\n", w.id, url) + w.assets.ServeWebViewRequest(request) +} + func (w *WebviewWindow) Center() { if w.impl == nil { return diff --git a/exp/pkg/application/webview_window.h b/exp/pkg/application/webview_window.h index b8962b056..72d56ee36 100644 --- a/exp/pkg/application/webview_window.h +++ b/exp/pkg/application/webview_window.h @@ -16,7 +16,7 @@ @end -@interface WebviewWindowDelegate : NSObject +@interface WebviewWindowDelegate : NSObject @property bool hideOnClose; @property (retain) WKWebView* webView; diff --git a/exp/pkg/application/webview_window.m b/exp/pkg/application/webview_window.m index ff5d22bc4..504871764 100644 --- a/exp/pkg/application/webview_window.m +++ b/exp/pkg/application/webview_window.m @@ -6,6 +6,7 @@ #import "../events/events.h" extern void processMessage(unsigned int, const char*); +extern void processURLRequest(unsigned int, void *); extern bool hasListeners(unsigned int); @implementation WebviewWindow @@ -82,6 +83,21 @@ extern bool hasListeners(unsigned int); - (void)handleLeftMouseUp:(NSWindow *)window { self.leftMouseEvent = nil; } + +- (void)webView:(nonnull WKWebView *)webView startURLSchemeTask:(nonnull id)urlSchemeTask { + processURLRequest(self.windowId, urlSchemeTask); +} + +- (void)webView:(nonnull WKWebView *)webView stopURLSchemeTask:(nonnull id)urlSchemeTask { + NSInputStream *stream = urlSchemeTask.request.HTTPBodyStream; + if (stream) { + NSStreamStatus status = stream.streamStatus; + if (status != NSStreamStatusClosed && status != NSStreamStatusNotOpen) { + [stream close]; + } + } +} + // GENERATED EVENTS START - (void)windowDidBecomeKey:(NSNotification *)notification { if( hasListeners(EventWindowDidBecomeKey) ) { diff --git a/exp/pkg/application/webview_window_darwin.go b/exp/pkg/application/webview_window_darwin.go index d66bc59ea..2f54dbbb9 100644 --- a/exp/pkg/application/webview_window_darwin.go +++ b/exp/pkg/application/webview_window_darwin.go @@ -48,6 +48,7 @@ void* windowNew(unsigned int id, int width, int height, bool fraudulentWebsiteWa WKWebViewConfiguration* config = [[WKWebViewConfiguration alloc] init]; config.suppressesIncrementalRendering = true; config.applicationNameForUserAgent = @"wails.io"; + [config setURLSchemeHandler:delegate forURLScheme:@"wails"]; if (@available(macOS 10.15, *)) { config.preferences.fraudulentWebsiteWarningEnabled = fraudulentWebsiteWarningEnabled; } @@ -913,6 +914,11 @@ func (w *macosWebviewWindow) execJS(js string) { } func (w *macosWebviewWindow) setURL(url string) { + if url == "/" { + // TODO handle this in a central location and handle all urls without scheme and host. This might be platform + // dependant + url = "wails://wails/" + } C.navigationLoadURL(w.nsWindow, C.CString(url)) } From 4c42ef97104caa6f8d8f098d9624feb21d9313a1 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 18 Jan 2023 17:39:44 +1100 Subject: [PATCH 83/85] Create generate bindings command --- exp/cmd/wails/main.go | 1 + exp/go.mod | 2 +- exp/go.sum | 2 + exp/internal/commands/bindings.go | 46 +++++++++++++++ exp/internal/parser/models.go | 95 ++++++++++++++++++++++++++++++ exp/internal/parser/parser.go | 96 +++---------------------------- 6 files changed, 154 insertions(+), 88 deletions(-) create mode 100644 exp/internal/commands/bindings.go create mode 100644 exp/internal/parser/models.go diff --git a/exp/cmd/wails/main.go b/exp/cmd/wails/main.go index 939ced765..6fc8629e6 100644 --- a/exp/cmd/wails/main.go +++ b/exp/cmd/wails/main.go @@ -19,6 +19,7 @@ func main() { generate.NewSubCommandFunction("defaults", "Generate default build assets", commands.Defaults) generate.NewSubCommandFunction("icons", "Generate icons", commands.GenerateIcons) generate.NewSubCommandFunction("syso", "Generate Windows .syso file", commands.GenerateSyso) + generate.NewSubCommandFunction("bindings", "Generate bindings + models", commands.GenerateBindings) err := app.Run() if err != nil { pterm.Error.Println(err) diff --git a/exp/go.mod b/exp/go.mod index 41406f11b..7450716b9 100644 --- a/exp/go.mod +++ b/exp/go.mod @@ -5,7 +5,7 @@ go 1.19 require ( github.com/go-task/task/v3 v3.19.1 github.com/jackmordaunt/icns/v2 v2.2.1 - github.com/leaanthony/clir v1.3.0 + github.com/leaanthony/clir v1.4.0 github.com/leaanthony/winicon v1.0.0 github.com/pterm/pterm v0.12.51 github.com/samber/lo v1.37.0 diff --git a/exp/go.sum b/exp/go.sum index 5939a361b..b7c637b8b 100644 --- a/exp/go.sum +++ b/exp/go.sum @@ -47,6 +47,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= github.com/leaanthony/clir v1.3.0 h1:L9nPDWrmc/qU9UWZZvRaFajWYuO0np9V5p+5gxyYno0= github.com/leaanthony/clir v1.3.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= +github.com/leaanthony/clir v1.4.0 h1:o+XoDoGV4wlncx0KmLmKnskm2TF40XMZrXquOXwBF7w= +github.com/leaanthony/clir v1.4.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0HtY= github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY= github.com/leaanthony/winicon v1.0.0 h1:ZNt5U5dY71oEoKZ97UVwJRT4e+5xo5o/ieKuHuk8NqQ= diff --git a/exp/internal/commands/bindings.go b/exp/internal/commands/bindings.go new file mode 100644 index 000000000..ba2407552 --- /dev/null +++ b/exp/internal/commands/bindings.go @@ -0,0 +1,46 @@ +package commands + +import ( + "bytes" + "fmt" + "os" + + "github.com/wailsapp/wails/exp/internal/parser" +) + +type GenerateBindingsOptions struct { + ModelsFilename string `name:"m" description:"The filename for the models file" default:"models.ts"` + BindingsFilename string `name:"b" description:"The filename for the bindings file" default:"bindings.js"` + ProjectDirectory string `name:"d" description:"The project directory" default:"."` +} + +func GenerateBindings(options *GenerateBindingsOptions) error { + + parserContext, err := parser.ParseDirectory(options.ProjectDirectory) + if err != nil { + return fmt.Errorf("error parsing project: %v", err) + } + + // Generate models + modelsData, err := parser.GenerateModels(parserContext) + if err != nil { + return fmt.Errorf("error generating models: %v", err) + } + + // Write file + if options.ModelsFilename == "" { + options.ModelsFilename = "models.ts" + } + var modelsFileData bytes.Buffer + modelsFileData.WriteString(`// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL +// This file is automatically generated. DO NOT EDIT + +`) + modelsFileData.Write(modelsData) + err = os.WriteFile(options.ModelsFilename, modelsFileData.Bytes(), 0755) + if err != nil { + return fmt.Errorf("error writing models file: %v", err) + } + + return nil +} diff --git a/exp/internal/parser/models.go b/exp/internal/parser/models.go new file mode 100644 index 000000000..4f728e8b2 --- /dev/null +++ b/exp/internal/parser/models.go @@ -0,0 +1,95 @@ +package parser + +import ( + "bytes" + "fmt" + "go/ast" + "go/types" + "sort" + "strings" + "unicode" +) + +func GenerateModels(context *Context) ([]byte, error) { + var buf bytes.Buffer + var pkgs []Package + specs := context.GetBoundStructs() + for pkg, pkgSpecs := range specs { + pkgs = append(pkgs, Package{Name: pkg, Specs: pkgSpecs}) + } + knownStructs := newAllModels(specs) + sort.Slice(pkgs, func(i, j int) bool { return pkgs[i].Name < pkgs[j].Name }) + for _, pkg := range pkgs { + if _, err := fmt.Fprintf(&buf, "namespace %s {\n", pkg.Name); err != nil { + return nil, err + } + sort.Slice(pkg.Specs, func(i, j int) bool { return pkg.Specs[i].Name.Name < pkg.Specs[j].Name.Name }) + for _, spec := range pkg.Specs { + if structType, ok := spec.Type.(*ast.StructType); ok { + if _, err := fmt.Fprintf(&buf, " class %s {\n", spec.Name.Name); err != nil { + return nil, err + } + + for _, field := range structType.Fields.List { + + // Ignore field names that have a lower case first letter + if !unicode.IsUpper(rune(field.Names[0].Name[0])) { + continue + } + + // Get the Go type of the field + goType := types.ExprString(field.Type) + // Check if the type is an array + if arrayType, ok := field.Type.(*ast.ArrayType); ok { + // Get the element type of the array + elementType := types.ExprString(arrayType.Elt) + // Look up the corresponding TypeScript type + tsType, ok := goToTS[elementType] + if !ok { + // strip off the * prefix if it is there + if strings.HasPrefix(elementType, "*") { + elementType = elementType[1:] + } + if knownStructs.exists(elementType) { + tsType = elementType + } else { + tsType = "any" + } + } + // Output the field as an array of the corresponding TypeScript type + if _, err := fmt.Fprintf(&buf, " %s: %s[];\n", field.Names[0].Name, tsType); err != nil { + return nil, err + } + } else { + // strip off the * prefix if it is there + if strings.HasPrefix(goType, "*") { + goType = goType[1:] + } + // Look up the corresponding TypeScript type + tsType, ok := goToTS[goType] + if !ok { + if knownStructs.exists(goType) { + tsType = goType + } else { + tsType = "any" + } + } + // Output the field as the corresponding TypeScript type + if _, err := fmt.Fprintf(&buf, " %s: %s;\n", field.Names[0].Name, tsType); err != nil { + return nil, err + } + } + } + + if _, err := fmt.Fprintf(&buf, " }\n"); err != nil { + return nil, err + } + } + } + + if _, err := fmt.Fprintf(&buf, "}\n\n"); err != nil { + return nil, err + } + } + return buf.Bytes(), nil +} diff --git a/exp/internal/parser/parser.go b/exp/internal/parser/parser.go index 61d2d9c8d..79c1ca728 100644 --- a/exp/internal/parser/parser.go +++ b/exp/internal/parser/parser.go @@ -1,15 +1,12 @@ package parser import ( - "bytes" "fmt" "go/ast" "go/parser" "go/token" - "go/types" - "sort" + "os" "strings" - "unicode" "github.com/samber/lo" @@ -47,6 +44,14 @@ func (c *Context) GetBoundStructs() map[string][]*ast.TypeSpec { func ParseDirectory(dir string) (*Context, error) { // Parse the directory fset := token.NewFileSet() + if dir == "." || dir == "" { + cwd, err := os.Getwd() + if err != nil { + return nil, err + } + dir = cwd + } + println("Parsing directory " + dir) pkgs, err := parser.ParseDir(fset, dir, nil, parser.AllErrors) if err != nil { return nil, err @@ -524,86 +529,3 @@ func (k *allModels) exists(name string) bool { _, ok = knownPkg[typ] return ok } - -func GenerateModels(specs map[string][]*ast.TypeSpec) ([]byte, error) { - var buf bytes.Buffer - var pkgs []Package - for pkg, pkgSpecs := range specs { - pkgs = append(pkgs, Package{Name: pkg, Specs: pkgSpecs}) - } - knownStructs := newAllModels(specs) - sort.Slice(pkgs, func(i, j int) bool { return pkgs[i].Name < pkgs[j].Name }) - for _, pkg := range pkgs { - if _, err := fmt.Fprintf(&buf, "namespace %s {\n", pkg.Name); err != nil { - return nil, err - } - sort.Slice(pkg.Specs, func(i, j int) bool { return pkg.Specs[i].Name.Name < pkg.Specs[j].Name.Name }) - for _, spec := range pkg.Specs { - if structType, ok := spec.Type.(*ast.StructType); ok { - if _, err := fmt.Fprintf(&buf, " class %s {\n", spec.Name.Name); err != nil { - return nil, err - } - - for _, field := range structType.Fields.List { - - // Ignore field names that have a lower case first letter - if !unicode.IsUpper(rune(field.Names[0].Name[0])) { - continue - } - - // Get the Go type of the field - goType := types.ExprString(field.Type) - // Check if the type is an array - if arrayType, ok := field.Type.(*ast.ArrayType); ok { - // Get the element type of the array - elementType := types.ExprString(arrayType.Elt) - // Look up the corresponding TypeScript type - tsType, ok := goToTS[elementType] - if !ok { - // strip off the * prefix if it is there - if strings.HasPrefix(elementType, "*") { - elementType = elementType[1:] - } - if knownStructs.exists(elementType) { - tsType = elementType - } else { - tsType = "any" - } - } - // Output the field as an array of the corresponding TypeScript type - if _, err := fmt.Fprintf(&buf, " %s: %s[];\n", field.Names[0].Name, tsType); err != nil { - return nil, err - } - } else { - // strip off the * prefix if it is there - if strings.HasPrefix(goType, "*") { - goType = goType[1:] - } - // Look up the corresponding TypeScript type - tsType, ok := goToTS[goType] - if !ok { - if knownStructs.exists(goType) { - tsType = goType - } else { - tsType = "any" - } - } - // Output the field as the corresponding TypeScript type - if _, err := fmt.Fprintf(&buf, " %s: %s;\n", field.Names[0].Name, tsType); err != nil { - return nil, err - } - } - } - - if _, err := fmt.Fprintf(&buf, " }\n"); err != nil { - return nil, err - } - } - } - - if _, err := fmt.Fprintf(&buf, "}\n"); err != nil { - return nil, err - } - } - return buf.Bytes(), nil -} From 2374bb7e0ead04d0bfac10cca17487c36178dd68 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 18 Jan 2023 20:57:31 +1100 Subject: [PATCH 84/85] Update clir --- exp/go.mod | 4 ++-- exp/go.sum | 8 ++++---- exp/internal/commands/bindings.go | 4 ---- exp/internal/parser/parser_test.go | 2 +- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/exp/go.mod b/exp/go.mod index 7450716b9..2967a8240 100644 --- a/exp/go.mod +++ b/exp/go.mod @@ -5,12 +5,13 @@ go 1.19 require ( github.com/go-task/task/v3 v3.19.1 github.com/jackmordaunt/icns/v2 v2.2.1 - github.com/leaanthony/clir v1.4.0 + github.com/leaanthony/clir v1.5.0 github.com/leaanthony/winicon v1.0.0 github.com/pterm/pterm v0.12.51 github.com/samber/lo v1.37.0 github.com/stretchr/testify v1.8.1 github.com/tc-hib/winres v0.1.6 + github.com/wailsapp/wails/v2 v2.3.2-0.20230117193915-45c3a501d9e6 golang.org/x/tools v0.1.12 ) @@ -38,7 +39,6 @@ require ( github.com/rivo/uniseg v0.2.0 // indirect github.com/sajari/fuzzy v1.0.0 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect - github.com/wailsapp/wails/v2 v2.3.2-0.20230117193915-45c3a501d9e6 // indirect github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9 // indirect golang.org/x/image v0.0.0-20201208152932-35266b937fa6 // indirect diff --git a/exp/go.sum b/exp/go.sum index b7c637b8b..90fb6b9b3 100644 --- a/exp/go.sum +++ b/exp/go.sum @@ -45,16 +45,15 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= -github.com/leaanthony/clir v1.3.0 h1:L9nPDWrmc/qU9UWZZvRaFajWYuO0np9V5p+5gxyYno0= -github.com/leaanthony/clir v1.3.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= -github.com/leaanthony/clir v1.4.0 h1:o+XoDoGV4wlncx0KmLmKnskm2TF40XMZrXquOXwBF7w= -github.com/leaanthony/clir v1.4.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= +github.com/leaanthony/clir v1.5.0 h1:zaH7fgsZ5OLfr0YwJBwQ+EYxCjXQsHF+CRudIiZb0KQ= +github.com/leaanthony/clir v1.5.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0HtY= github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY= github.com/leaanthony/winicon v1.0.0 h1:ZNt5U5dY71oEoKZ97UVwJRT4e+5xo5o/ieKuHuk8NqQ= github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU= github.com/lithammer/fuzzysearch v1.1.5 h1:Ag7aKU08wp0R9QCfF4GoGST9HbmAIeLP7xwMrOBEp1c= github.com/lithammer/fuzzysearch v1.1.5/go.mod h1:1R1LRNk7yKid1BaQkmuLQaHruxcC4HmAH30Dh61Ih1Q= +github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= @@ -170,6 +169,7 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8X gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/exp/internal/commands/bindings.go b/exp/internal/commands/bindings.go index ba2407552..56e17e6b1 100644 --- a/exp/internal/commands/bindings.go +++ b/exp/internal/commands/bindings.go @@ -27,10 +27,6 @@ func GenerateBindings(options *GenerateBindingsOptions) error { return fmt.Errorf("error generating models: %v", err) } - // Write file - if options.ModelsFilename == "" { - options.ModelsFilename = "models.ts" - } var modelsFileData bytes.Buffer modelsFileData.WriteString(`// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL // This file is automatically generated. DO NOT EDIT diff --git a/exp/internal/parser/parser_test.go b/exp/internal/parser/parser_test.go index 092b91ef6..468966a08 100644 --- a/exp/internal/parser/parser_test.go +++ b/exp/internal/parser/parser_test.go @@ -135,7 +135,7 @@ namespace services { return } - ts, err := GenerateModels(context.GetBoundStructs()) + ts, err := GenerateModels(context) require.NoError(t, err) require.Equal(t, tt.want, string(ts)) From d24d82f86d979beff24b407089033ca4084e0ddf Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 18 Jan 2023 21:34:11 +1100 Subject: [PATCH 85/85] Rename exp -> v3 --- .gitignore | 4 ++-- {exp => v3}/.gitignore | 0 {exp => v3}/Taskfile.yaml | 0 {exp => v3}/cmd/wails/README.md | 0 {exp => v3}/cmd/wails/main.go | 2 +- {exp => v3}/examples/binding/main.go | 6 +++--- {exp => v3}/examples/binding/models/person.go | 0 .../examples/binding/services/GreetService.go | 2 +- {exp => v3}/examples/build/README.md | 0 {exp => v3}/examples/build/Taskfile.yml | 0 {exp => v3}/examples/build/build/Info.dev.plist | 0 {exp => v3}/examples/build/build/Info.plist | 0 {exp => v3}/examples/build/build/appicon.png | Bin {exp => v3}/examples/build/build/icons.icns | Bin {exp => v3}/examples/build/build/icons.ico | Bin {exp => v3}/examples/build/build/info.json | 0 {exp => v3}/examples/build/build/wails.exe.manifest | 0 .../build/buildtest.app/Contents/Info.plist | 0 .../buildtest.app/Contents/Resources/icons.icns | Bin {exp => v3}/examples/build/main.go | 6 +++--- {exp => v3}/examples/clipboard/main.go | 4 ++-- {exp => v3}/examples/dialogs/main.go | 4 ++-- {exp => v3}/examples/kitchensink/main.go | 4 ++-- {exp => v3}/examples/menu/main.go | 4 ++-- {exp => v3}/examples/plain/main.go | 4 ++-- {exp => v3}/examples/systray/main.go | 4 ++-- {exp => v3}/examples/window/main.go | 6 +++--- {exp => v3}/go.mod | 2 +- {exp => v3}/go.sum | 0 {exp => v3}/internal/commands/bindings.go | 2 +- {exp => v3}/internal/commands/defaults.go | 0 .../internal/commands/defaults/Info.dev.plist | 0 {exp => v3}/internal/commands/defaults/Info.plist | 0 {exp => v3}/internal/commands/defaults/appicon.png | Bin {exp => v3}/internal/commands/defaults/icons.icns | Bin {exp => v3}/internal/commands/defaults/icons.ico | Bin {exp => v3}/internal/commands/defaults/info.json | 0 .../internal/commands/defaults/wails.exe.manifest | 0 {exp => v3}/internal/commands/icons.go | 0 {exp => v3}/internal/commands/icons_test.go | 0 {exp => v3}/internal/commands/init.go | 0 {exp => v3}/internal/commands/syso.go | 0 {exp => v3}/internal/commands/syso_test.go | 0 {exp => v3}/internal/commands/task.go | 0 {exp => v3}/internal/commands/task_test.go | 0 {exp => v3}/internal/parser/README.md | 0 {exp => v3}/internal/parser/models.go | 0 {exp => v3}/internal/parser/parser.go | 0 {exp => v3}/internal/parser/parser_test.go | 0 .../parser/testdata/struct_literal_multiple/main.go | 4 ++-- .../testdata/struct_literal_multiple_files/greet.go | 0 .../testdata/struct_literal_multiple_files/main.go | 4 ++-- .../testdata/struct_literal_multiple_files/other.go | 0 .../parser/testdata/struct_literal_single/main.go | 4 ++-- {exp => v3}/internal/runtime/assets.go | 0 {exp => v3}/internal/runtime/assets_dev.go | 0 {exp => v3}/internal/runtime/desktop/bindings.js | 0 {exp => v3}/internal/runtime/desktop/browser.js | 0 {exp => v3}/internal/runtime/desktop/calls.js | 0 {exp => v3}/internal/runtime/desktop/events.js | 0 {exp => v3}/internal/runtime/desktop/events.test.js | 0 {exp => v3}/internal/runtime/desktop/ipc.js | 0 {exp => v3}/internal/runtime/desktop/log.js | 0 {exp => v3}/internal/runtime/desktop/main.js | 0 {exp => v3}/internal/runtime/desktop/screen.js | 0 {exp => v3}/internal/runtime/desktop/window.js | 0 {exp => v3}/internal/runtime/dev/Overlay.svelte | 0 {exp => v3}/internal/runtime/dev/build.js | 0 {exp => v3}/internal/runtime/dev/log.js | 0 {exp => v3}/internal/runtime/dev/main.js | 0 {exp => v3}/internal/runtime/dev/package-lock.json | 0 {exp => v3}/internal/runtime/dev/package.json | 0 {exp => v3}/internal/runtime/dev/store.js | 0 {exp => v3}/internal/runtime/ipc.go | 0 {exp => v3}/internal/runtime/ipc.js | 0 {exp => v3}/internal/runtime/ipc_websocket.js | 0 {exp => v3}/internal/runtime/package-lock.json | 0 {exp => v3}/internal/runtime/package.json | 0 .../internal/runtime/runtime_debug_darwin.go | 0 .../runtime/runtime_debug_desktop_darwin.js | 0 .../internal/runtime/runtime_debug_desktop_linux.js | 0 .../runtime/runtime_debug_desktop_windows.js | 0 {exp => v3}/internal/runtime/runtime_debug_linux.go | 0 .../internal/runtime/runtime_debug_windows.go | 0 .../internal/runtime/runtime_production_darwin.go | 0 .../runtime/runtime_production_desktop_darwin.js | 0 .../runtime/runtime_production_desktop_linux.js | 0 .../runtime/runtime_production_desktop_windows.js | 0 .../internal/runtime/runtime_production_linux.go | 0 .../internal/runtime/runtime_production_windows.go | 0 {exp => v3}/internal/runtime/vite.config.ts | 0 {exp => v3}/pkg/application/TODO.md | 0 {exp => v3}/pkg/application/app_delegate.h | 0 {exp => v3}/pkg/application/app_delegate.m | 0 {exp => v3}/pkg/application/application.go | 4 ++-- {exp => v3}/pkg/application/application.h | 0 {exp => v3}/pkg/application/application_darwin.go | 2 +- {exp => v3}/pkg/application/clipboard.go | 0 {exp => v3}/pkg/application/clipboard_darwin.go | 0 {exp => v3}/pkg/application/context.go | 0 {exp => v3}/pkg/application/dialogs.go | 0 {exp => v3}/pkg/application/dialogs_darwin.go | 0 {exp => v3}/pkg/application/dialogs_delegate.h | 0 {exp => v3}/pkg/application/dialogs_delegate.m | 0 {exp => v3}/pkg/application/errors.go | 0 {exp => v3}/pkg/application/events.go | 0 {exp => v3}/pkg/application/icons.go | 0 {exp => v3}/pkg/application/keys.go | 0 {exp => v3}/pkg/application/keys_darwin.go | 0 {exp => v3}/pkg/application/mainthread.go | 0 {exp => v3}/pkg/application/mainthread_darwin.go | 0 {exp => v3}/pkg/application/menu.go | 0 {exp => v3}/pkg/application/menu_darwin.go | 0 {exp => v3}/pkg/application/menuitem.go | 0 {exp => v3}/pkg/application/menuitem.h | 0 {exp => v3}/pkg/application/menuitem.m | 0 {exp => v3}/pkg/application/menuitem_darwin.go | 0 {exp => v3}/pkg/application/roles.go | 0 {exp => v3}/pkg/application/screen.go | 0 {exp => v3}/pkg/application/screen_darwin.go | 0 {exp => v3}/pkg/application/systemtray.go | 0 {exp => v3}/pkg/application/systemtray_darwin.go | 0 {exp => v3}/pkg/application/webview_window.go | 6 +++--- {exp => v3}/pkg/application/webview_window.h | 0 {exp => v3}/pkg/application/webview_window.m | 0 .../pkg/application/webview_window_darwin.go | 4 ++-- .../pkg/application/webview_window_devtools.go | 0 {exp => v3}/pkg/events/events.go | 0 {exp => v3}/pkg/events/events.h | 0 {exp => v3}/pkg/events/events.txt | 0 {exp => v3}/pkg/events/events_darwin.go | 0 {exp => v3}/pkg/options/application.go | 0 {exp => v3}/pkg/options/mac.go | 0 {exp => v3}/pkg/options/window.go | 0 {exp => v3}/tasks/Taskfile.yml | 0 {exp => v3}/tasks/events/generate.go | 0 {exp => v3}/tasks/png2bytes/png2bytes.go | 0 137 files changed, 41 insertions(+), 41 deletions(-) rename {exp => v3}/.gitignore (100%) rename {exp => v3}/Taskfile.yaml (100%) rename {exp => v3}/cmd/wails/README.md (100%) rename {exp => v3}/cmd/wails/main.go (94%) rename {exp => v3}/examples/binding/main.go (66%) rename {exp => v3}/examples/binding/models/person.go (100%) rename {exp => v3}/examples/binding/services/GreetService.go (86%) rename {exp => v3}/examples/build/README.md (100%) rename {exp => v3}/examples/build/Taskfile.yml (100%) rename {exp => v3}/examples/build/build/Info.dev.plist (100%) rename {exp => v3}/examples/build/build/Info.plist (100%) rename {exp => v3}/examples/build/build/appicon.png (100%) rename {exp => v3}/examples/build/build/icons.icns (100%) rename {exp => v3}/examples/build/build/icons.ico (100%) rename {exp => v3}/examples/build/build/info.json (100%) rename {exp => v3}/examples/build/build/wails.exe.manifest (100%) rename {exp => v3}/examples/build/buildtest.app/Contents/Info.plist (100%) rename {exp => v3}/examples/build/buildtest.app/Contents/Resources/icons.icns (100%) rename {exp => v3}/examples/build/main.go (98%) rename {exp => v3}/examples/clipboard/main.go (95%) rename {exp => v3}/examples/dialogs/main.go (99%) rename {exp => v3}/examples/kitchensink/main.go (98%) rename {exp => v3}/examples/menu/main.go (96%) rename {exp => v3}/examples/plain/main.go (92%) rename {exp => v3}/examples/systray/main.go (90%) rename {exp => v3}/examples/window/main.go (98%) rename {exp => v3}/go.mod (98%) rename {exp => v3}/go.sum (100%) rename {exp => v3}/internal/commands/bindings.go (95%) rename {exp => v3}/internal/commands/defaults.go (100%) rename {exp => v3}/internal/commands/defaults/Info.dev.plist (100%) rename {exp => v3}/internal/commands/defaults/Info.plist (100%) rename {exp => v3}/internal/commands/defaults/appicon.png (100%) rename {exp => v3}/internal/commands/defaults/icons.icns (100%) rename {exp => v3}/internal/commands/defaults/icons.ico (100%) rename {exp => v3}/internal/commands/defaults/info.json (100%) rename {exp => v3}/internal/commands/defaults/wails.exe.manifest (100%) rename {exp => v3}/internal/commands/icons.go (100%) rename {exp => v3}/internal/commands/icons_test.go (100%) rename {exp => v3}/internal/commands/init.go (100%) rename {exp => v3}/internal/commands/syso.go (100%) rename {exp => v3}/internal/commands/syso_test.go (100%) rename {exp => v3}/internal/commands/task.go (100%) rename {exp => v3}/internal/commands/task_test.go (100%) rename {exp => v3}/internal/parser/README.md (100%) rename {exp => v3}/internal/parser/models.go (100%) rename {exp => v3}/internal/parser/parser.go (100%) rename {exp => v3}/internal/parser/parser_test.go (100%) rename {exp => v3}/internal/parser/testdata/struct_literal_multiple/main.go (82%) rename {exp => v3}/internal/parser/testdata/struct_literal_multiple_files/greet.go (100%) rename {exp => v3}/internal/parser/testdata/struct_literal_multiple_files/main.go (73%) rename {exp => v3}/internal/parser/testdata/struct_literal_multiple_files/other.go (100%) rename {exp => v3}/internal/parser/testdata/struct_literal_single/main.go (80%) rename {exp => v3}/internal/runtime/assets.go (100%) rename {exp => v3}/internal/runtime/assets_dev.go (100%) rename {exp => v3}/internal/runtime/desktop/bindings.js (100%) rename {exp => v3}/internal/runtime/desktop/browser.js (100%) rename {exp => v3}/internal/runtime/desktop/calls.js (100%) rename {exp => v3}/internal/runtime/desktop/events.js (100%) rename {exp => v3}/internal/runtime/desktop/events.test.js (100%) rename {exp => v3}/internal/runtime/desktop/ipc.js (100%) rename {exp => v3}/internal/runtime/desktop/log.js (100%) rename {exp => v3}/internal/runtime/desktop/main.js (100%) rename {exp => v3}/internal/runtime/desktop/screen.js (100%) rename {exp => v3}/internal/runtime/desktop/window.js (100%) rename {exp => v3}/internal/runtime/dev/Overlay.svelte (100%) rename {exp => v3}/internal/runtime/dev/build.js (100%) rename {exp => v3}/internal/runtime/dev/log.js (100%) rename {exp => v3}/internal/runtime/dev/main.js (100%) rename {exp => v3}/internal/runtime/dev/package-lock.json (100%) rename {exp => v3}/internal/runtime/dev/package.json (100%) rename {exp => v3}/internal/runtime/dev/store.js (100%) rename {exp => v3}/internal/runtime/ipc.go (100%) rename {exp => v3}/internal/runtime/ipc.js (100%) rename {exp => v3}/internal/runtime/ipc_websocket.js (100%) rename {exp => v3}/internal/runtime/package-lock.json (100%) rename {exp => v3}/internal/runtime/package.json (100%) rename {exp => v3}/internal/runtime/runtime_debug_darwin.go (100%) rename {exp => v3}/internal/runtime/runtime_debug_desktop_darwin.js (100%) rename {exp => v3}/internal/runtime/runtime_debug_desktop_linux.js (100%) rename {exp => v3}/internal/runtime/runtime_debug_desktop_windows.js (100%) rename {exp => v3}/internal/runtime/runtime_debug_linux.go (100%) rename {exp => v3}/internal/runtime/runtime_debug_windows.go (100%) rename {exp => v3}/internal/runtime/runtime_production_darwin.go (100%) rename {exp => v3}/internal/runtime/runtime_production_desktop_darwin.js (100%) rename {exp => v3}/internal/runtime/runtime_production_desktop_linux.js (100%) rename {exp => v3}/internal/runtime/runtime_production_desktop_windows.js (100%) rename {exp => v3}/internal/runtime/runtime_production_linux.go (100%) rename {exp => v3}/internal/runtime/runtime_production_windows.go (100%) rename {exp => v3}/internal/runtime/vite.config.ts (100%) rename {exp => v3}/pkg/application/TODO.md (100%) rename {exp => v3}/pkg/application/app_delegate.h (100%) rename {exp => v3}/pkg/application/app_delegate.m (100%) rename {exp => v3}/pkg/application/application.go (98%) rename {exp => v3}/pkg/application/application.h (100%) rename {exp => v3}/pkg/application/application_darwin.go (99%) rename {exp => v3}/pkg/application/clipboard.go (100%) rename {exp => v3}/pkg/application/clipboard_darwin.go (100%) rename {exp => v3}/pkg/application/context.go (100%) rename {exp => v3}/pkg/application/dialogs.go (100%) rename {exp => v3}/pkg/application/dialogs_darwin.go (100%) rename {exp => v3}/pkg/application/dialogs_delegate.h (100%) rename {exp => v3}/pkg/application/dialogs_delegate.m (100%) rename {exp => v3}/pkg/application/errors.go (100%) rename {exp => v3}/pkg/application/events.go (100%) rename {exp => v3}/pkg/application/icons.go (100%) rename {exp => v3}/pkg/application/keys.go (100%) rename {exp => v3}/pkg/application/keys_darwin.go (100%) rename {exp => v3}/pkg/application/mainthread.go (100%) rename {exp => v3}/pkg/application/mainthread_darwin.go (100%) rename {exp => v3}/pkg/application/menu.go (100%) rename {exp => v3}/pkg/application/menu_darwin.go (100%) rename {exp => v3}/pkg/application/menuitem.go (100%) rename {exp => v3}/pkg/application/menuitem.h (100%) rename {exp => v3}/pkg/application/menuitem.m (100%) rename {exp => v3}/pkg/application/menuitem_darwin.go (100%) rename {exp => v3}/pkg/application/roles.go (100%) rename {exp => v3}/pkg/application/screen.go (100%) rename {exp => v3}/pkg/application/screen_darwin.go (100%) rename {exp => v3}/pkg/application/systemtray.go (100%) rename {exp => v3}/pkg/application/systemtray_darwin.go (100%) rename {exp => v3}/pkg/application/webview_window.go (98%) rename {exp => v3}/pkg/application/webview_window.h (100%) rename {exp => v3}/pkg/application/webview_window.m (100%) rename {exp => v3}/pkg/application/webview_window_darwin.go (99%) rename {exp => v3}/pkg/application/webview_window_devtools.go (100%) rename {exp => v3}/pkg/events/events.go (100%) rename {exp => v3}/pkg/events/events.h (100%) rename {exp => v3}/pkg/events/events.txt (100%) rename {exp => v3}/pkg/events/events_darwin.go (100%) rename {exp => v3}/pkg/options/application.go (100%) rename {exp => v3}/pkg/options/mac.go (100%) rename {exp => v3}/pkg/options/window.go (100%) rename {exp => v3}/tasks/Taskfile.yml (100%) rename {exp => v3}/tasks/events/generate.go (100%) rename {exp => v3}/tasks/png2bytes/png2bytes.go (100%) diff --git a/.gitignore b/.gitignore index 567f8ea27..9e173452f 100644 --- a/.gitignore +++ b/.gitignore @@ -32,5 +32,5 @@ v2/cmd/wails/internal/commands/initialise/templates/testtemplates/ .env /website/static/img/.cache.json -/exp/.task -/exp/examples/build/bin/testapp +/v3/.task +/v3/examples/build/bin/testapp diff --git a/exp/.gitignore b/v3/.gitignore similarity index 100% rename from exp/.gitignore rename to v3/.gitignore diff --git a/exp/Taskfile.yaml b/v3/Taskfile.yaml similarity index 100% rename from exp/Taskfile.yaml rename to v3/Taskfile.yaml diff --git a/exp/cmd/wails/README.md b/v3/cmd/wails/README.md similarity index 100% rename from exp/cmd/wails/README.md rename to v3/cmd/wails/README.md diff --git a/exp/cmd/wails/main.go b/v3/cmd/wails/main.go similarity index 94% rename from exp/cmd/wails/main.go rename to v3/cmd/wails/main.go index 6fc8629e6..635316852 100644 --- a/exp/cmd/wails/main.go +++ b/v3/cmd/wails/main.go @@ -6,7 +6,7 @@ import ( "github.com/pterm/pterm" "github.com/leaanthony/clir" - "github.com/wailsapp/wails/exp/internal/commands" + "github.com/wailsapp/wails/v3/internal/commands" ) func main() { diff --git a/exp/examples/binding/main.go b/v3/examples/binding/main.go similarity index 66% rename from exp/examples/binding/main.go rename to v3/examples/binding/main.go index dc77f289b..f6669c278 100644 --- a/exp/examples/binding/main.go +++ b/v3/examples/binding/main.go @@ -4,10 +4,10 @@ import ( _ "embed" "log" - "github.com/wailsapp/wails/exp/examples/binding/services" + "github.com/wailsapp/wails/v3/examples/binding/services" - "github.com/wailsapp/wails/exp/pkg/application" - "github.com/wailsapp/wails/exp/pkg/options" + "github.com/wailsapp/wails/v3/pkg/application" + "github.com/wailsapp/wails/v3/pkg/options" ) type localStruct struct{} diff --git a/exp/examples/binding/models/person.go b/v3/examples/binding/models/person.go similarity index 100% rename from exp/examples/binding/models/person.go rename to v3/examples/binding/models/person.go diff --git a/exp/examples/binding/services/GreetService.go b/v3/examples/binding/services/GreetService.go similarity index 86% rename from exp/examples/binding/services/GreetService.go rename to v3/examples/binding/services/GreetService.go index 72ea44cd7..13a6f4571 100644 --- a/exp/examples/binding/services/GreetService.go +++ b/v3/examples/binding/services/GreetService.go @@ -1,7 +1,7 @@ package services import ( - "github.com/wailsapp/wails/exp/examples/binding/models" + "github.com/wailsapp/wails/v3/examples/binding/models" ) type GreetService struct { diff --git a/exp/examples/build/README.md b/v3/examples/build/README.md similarity index 100% rename from exp/examples/build/README.md rename to v3/examples/build/README.md diff --git a/exp/examples/build/Taskfile.yml b/v3/examples/build/Taskfile.yml similarity index 100% rename from exp/examples/build/Taskfile.yml rename to v3/examples/build/Taskfile.yml diff --git a/exp/examples/build/build/Info.dev.plist b/v3/examples/build/build/Info.dev.plist similarity index 100% rename from exp/examples/build/build/Info.dev.plist rename to v3/examples/build/build/Info.dev.plist diff --git a/exp/examples/build/build/Info.plist b/v3/examples/build/build/Info.plist similarity index 100% rename from exp/examples/build/build/Info.plist rename to v3/examples/build/build/Info.plist diff --git a/exp/examples/build/build/appicon.png b/v3/examples/build/build/appicon.png similarity index 100% rename from exp/examples/build/build/appicon.png rename to v3/examples/build/build/appicon.png diff --git a/exp/examples/build/build/icons.icns b/v3/examples/build/build/icons.icns similarity index 100% rename from exp/examples/build/build/icons.icns rename to v3/examples/build/build/icons.icns diff --git a/exp/examples/build/build/icons.ico b/v3/examples/build/build/icons.ico similarity index 100% rename from exp/examples/build/build/icons.ico rename to v3/examples/build/build/icons.ico diff --git a/exp/examples/build/build/info.json b/v3/examples/build/build/info.json similarity index 100% rename from exp/examples/build/build/info.json rename to v3/examples/build/build/info.json diff --git a/exp/examples/build/build/wails.exe.manifest b/v3/examples/build/build/wails.exe.manifest similarity index 100% rename from exp/examples/build/build/wails.exe.manifest rename to v3/examples/build/build/wails.exe.manifest diff --git a/exp/examples/build/buildtest.app/Contents/Info.plist b/v3/examples/build/buildtest.app/Contents/Info.plist similarity index 100% rename from exp/examples/build/buildtest.app/Contents/Info.plist rename to v3/examples/build/buildtest.app/Contents/Info.plist diff --git a/exp/examples/build/buildtest.app/Contents/Resources/icons.icns b/v3/examples/build/buildtest.app/Contents/Resources/icons.icns similarity index 100% rename from exp/examples/build/buildtest.app/Contents/Resources/icons.icns rename to v3/examples/build/buildtest.app/Contents/Resources/icons.icns diff --git a/exp/examples/build/main.go b/v3/examples/build/main.go similarity index 98% rename from exp/examples/build/main.go rename to v3/examples/build/main.go index 269d324c0..b8092bcf6 100755 --- a/exp/examples/build/main.go +++ b/v3/examples/build/main.go @@ -9,11 +9,11 @@ import ( "strconv" "time" - "github.com/wailsapp/wails/exp/pkg/options" + "github.com/wailsapp/wails/v3/pkg/options" - "github.com/wailsapp/wails/exp/pkg/events" + "github.com/wailsapp/wails/v3/pkg/events" - "github.com/wailsapp/wails/exp/pkg/application" + "github.com/wailsapp/wails/v3/pkg/application" ) func main() { diff --git a/exp/examples/clipboard/main.go b/v3/examples/clipboard/main.go similarity index 95% rename from exp/examples/clipboard/main.go rename to v3/examples/clipboard/main.go index e0afcb856..bb2740ca3 100644 --- a/exp/examples/clipboard/main.go +++ b/v3/examples/clipboard/main.go @@ -5,9 +5,9 @@ import ( "log" "time" - "github.com/wailsapp/wails/exp/pkg/options" + "github.com/wailsapp/wails/v3/pkg/options" - "github.com/wailsapp/wails/exp/pkg/application" + "github.com/wailsapp/wails/v3/pkg/application" ) func main() { diff --git a/exp/examples/dialogs/main.go b/v3/examples/dialogs/main.go similarity index 99% rename from exp/examples/dialogs/main.go rename to v3/examples/dialogs/main.go index eaf8aae58..4ae46a236 100644 --- a/exp/examples/dialogs/main.go +++ b/v3/examples/dialogs/main.go @@ -7,9 +7,9 @@ import ( "runtime" "strings" - "github.com/wailsapp/wails/exp/pkg/options" + "github.com/wailsapp/wails/v3/pkg/options" - "github.com/wailsapp/wails/exp/pkg/application" + "github.com/wailsapp/wails/v3/pkg/application" ) func main() { diff --git a/exp/examples/kitchensink/main.go b/v3/examples/kitchensink/main.go similarity index 98% rename from exp/examples/kitchensink/main.go rename to v3/examples/kitchensink/main.go index 53fa91eca..851e4b787 100644 --- a/exp/examples/kitchensink/main.go +++ b/v3/examples/kitchensink/main.go @@ -7,8 +7,8 @@ import ( "sync" "time" - "github.com/wailsapp/wails/exp/pkg/application" - "github.com/wailsapp/wails/exp/pkg/options" + "github.com/wailsapp/wails/v3/pkg/application" + "github.com/wailsapp/wails/v3/pkg/options" ) func main() { diff --git a/exp/examples/menu/main.go b/v3/examples/menu/main.go similarity index 96% rename from exp/examples/menu/main.go rename to v3/examples/menu/main.go index d91705eb4..0310f4fec 100644 --- a/exp/examples/menu/main.go +++ b/v3/examples/menu/main.go @@ -4,9 +4,9 @@ import ( _ "embed" "log" - "github.com/wailsapp/wails/exp/pkg/options" + "github.com/wailsapp/wails/v3/pkg/options" - "github.com/wailsapp/wails/exp/pkg/application" + "github.com/wailsapp/wails/v3/pkg/application" ) func main() { diff --git a/exp/examples/plain/main.go b/v3/examples/plain/main.go similarity index 92% rename from exp/examples/plain/main.go rename to v3/examples/plain/main.go index ea2728758..1257ee2a0 100644 --- a/exp/examples/plain/main.go +++ b/v3/examples/plain/main.go @@ -5,9 +5,9 @@ import ( "log" "net/http" - "github.com/wailsapp/wails/exp/pkg/options" + "github.com/wailsapp/wails/v3/pkg/options" - "github.com/wailsapp/wails/exp/pkg/application" + "github.com/wailsapp/wails/v3/pkg/application" ) func main() { diff --git a/exp/examples/systray/main.go b/v3/examples/systray/main.go similarity index 90% rename from exp/examples/systray/main.go rename to v3/examples/systray/main.go index 5508ad904..054b2a9bc 100644 --- a/exp/examples/systray/main.go +++ b/v3/examples/systray/main.go @@ -5,9 +5,9 @@ import ( "log" "runtime" - "github.com/wailsapp/wails/exp/pkg/options" + "github.com/wailsapp/wails/v3/pkg/options" - "github.com/wailsapp/wails/exp/pkg/application" + "github.com/wailsapp/wails/v3/pkg/application" ) func main() { diff --git a/exp/examples/window/main.go b/v3/examples/window/main.go similarity index 98% rename from exp/examples/window/main.go rename to v3/examples/window/main.go index 80b249a37..9d7a84a56 100644 --- a/exp/examples/window/main.go +++ b/v3/examples/window/main.go @@ -9,11 +9,11 @@ import ( "strconv" "time" - "github.com/wailsapp/wails/exp/pkg/options" + "github.com/wailsapp/wails/v3/pkg/options" - "github.com/wailsapp/wails/exp/pkg/events" + "github.com/wailsapp/wails/v3/pkg/events" - "github.com/wailsapp/wails/exp/pkg/application" + "github.com/wailsapp/wails/v3/pkg/application" ) func main() { diff --git a/exp/go.mod b/v3/go.mod similarity index 98% rename from exp/go.mod rename to v3/go.mod index 2967a8240..416e36ff2 100644 --- a/exp/go.mod +++ b/v3/go.mod @@ -1,4 +1,4 @@ -module github.com/wailsapp/wails/exp +module github.com/wailsapp/wails/v3 go 1.19 diff --git a/exp/go.sum b/v3/go.sum similarity index 100% rename from exp/go.sum rename to v3/go.sum diff --git a/exp/internal/commands/bindings.go b/v3/internal/commands/bindings.go similarity index 95% rename from exp/internal/commands/bindings.go rename to v3/internal/commands/bindings.go index 56e17e6b1..719580b39 100644 --- a/exp/internal/commands/bindings.go +++ b/v3/internal/commands/bindings.go @@ -5,7 +5,7 @@ import ( "fmt" "os" - "github.com/wailsapp/wails/exp/internal/parser" + "github.com/wailsapp/wails/v3/internal/parser" ) type GenerateBindingsOptions struct { diff --git a/exp/internal/commands/defaults.go b/v3/internal/commands/defaults.go similarity index 100% rename from exp/internal/commands/defaults.go rename to v3/internal/commands/defaults.go diff --git a/exp/internal/commands/defaults/Info.dev.plist b/v3/internal/commands/defaults/Info.dev.plist similarity index 100% rename from exp/internal/commands/defaults/Info.dev.plist rename to v3/internal/commands/defaults/Info.dev.plist diff --git a/exp/internal/commands/defaults/Info.plist b/v3/internal/commands/defaults/Info.plist similarity index 100% rename from exp/internal/commands/defaults/Info.plist rename to v3/internal/commands/defaults/Info.plist diff --git a/exp/internal/commands/defaults/appicon.png b/v3/internal/commands/defaults/appicon.png similarity index 100% rename from exp/internal/commands/defaults/appicon.png rename to v3/internal/commands/defaults/appicon.png diff --git a/exp/internal/commands/defaults/icons.icns b/v3/internal/commands/defaults/icons.icns similarity index 100% rename from exp/internal/commands/defaults/icons.icns rename to v3/internal/commands/defaults/icons.icns diff --git a/exp/internal/commands/defaults/icons.ico b/v3/internal/commands/defaults/icons.ico similarity index 100% rename from exp/internal/commands/defaults/icons.ico rename to v3/internal/commands/defaults/icons.ico diff --git a/exp/internal/commands/defaults/info.json b/v3/internal/commands/defaults/info.json similarity index 100% rename from exp/internal/commands/defaults/info.json rename to v3/internal/commands/defaults/info.json diff --git a/exp/internal/commands/defaults/wails.exe.manifest b/v3/internal/commands/defaults/wails.exe.manifest similarity index 100% rename from exp/internal/commands/defaults/wails.exe.manifest rename to v3/internal/commands/defaults/wails.exe.manifest diff --git a/exp/internal/commands/icons.go b/v3/internal/commands/icons.go similarity index 100% rename from exp/internal/commands/icons.go rename to v3/internal/commands/icons.go diff --git a/exp/internal/commands/icons_test.go b/v3/internal/commands/icons_test.go similarity index 100% rename from exp/internal/commands/icons_test.go rename to v3/internal/commands/icons_test.go diff --git a/exp/internal/commands/init.go b/v3/internal/commands/init.go similarity index 100% rename from exp/internal/commands/init.go rename to v3/internal/commands/init.go diff --git a/exp/internal/commands/syso.go b/v3/internal/commands/syso.go similarity index 100% rename from exp/internal/commands/syso.go rename to v3/internal/commands/syso.go diff --git a/exp/internal/commands/syso_test.go b/v3/internal/commands/syso_test.go similarity index 100% rename from exp/internal/commands/syso_test.go rename to v3/internal/commands/syso_test.go diff --git a/exp/internal/commands/task.go b/v3/internal/commands/task.go similarity index 100% rename from exp/internal/commands/task.go rename to v3/internal/commands/task.go diff --git a/exp/internal/commands/task_test.go b/v3/internal/commands/task_test.go similarity index 100% rename from exp/internal/commands/task_test.go rename to v3/internal/commands/task_test.go diff --git a/exp/internal/parser/README.md b/v3/internal/parser/README.md similarity index 100% rename from exp/internal/parser/README.md rename to v3/internal/parser/README.md diff --git a/exp/internal/parser/models.go b/v3/internal/parser/models.go similarity index 100% rename from exp/internal/parser/models.go rename to v3/internal/parser/models.go diff --git a/exp/internal/parser/parser.go b/v3/internal/parser/parser.go similarity index 100% rename from exp/internal/parser/parser.go rename to v3/internal/parser/parser.go diff --git a/exp/internal/parser/parser_test.go b/v3/internal/parser/parser_test.go similarity index 100% rename from exp/internal/parser/parser_test.go rename to v3/internal/parser/parser_test.go diff --git a/exp/internal/parser/testdata/struct_literal_multiple/main.go b/v3/internal/parser/testdata/struct_literal_multiple/main.go similarity index 82% rename from exp/internal/parser/testdata/struct_literal_multiple/main.go rename to v3/internal/parser/testdata/struct_literal_multiple/main.go index 026f1266f..4f0bf8bd3 100644 --- a/exp/internal/parser/testdata/struct_literal_multiple/main.go +++ b/v3/internal/parser/testdata/struct_literal_multiple/main.go @@ -4,8 +4,8 @@ import ( _ "embed" "log" - "github.com/wailsapp/wails/exp/pkg/application" - "github.com/wailsapp/wails/exp/pkg/options" + "github.com/wailsapp/wails/v3/pkg/application" + "github.com/wailsapp/wails/v3/pkg/options" ) type GreetService struct { diff --git a/exp/internal/parser/testdata/struct_literal_multiple_files/greet.go b/v3/internal/parser/testdata/struct_literal_multiple_files/greet.go similarity index 100% rename from exp/internal/parser/testdata/struct_literal_multiple_files/greet.go rename to v3/internal/parser/testdata/struct_literal_multiple_files/greet.go diff --git a/exp/internal/parser/testdata/struct_literal_multiple_files/main.go b/v3/internal/parser/testdata/struct_literal_multiple_files/main.go similarity index 73% rename from exp/internal/parser/testdata/struct_literal_multiple_files/main.go rename to v3/internal/parser/testdata/struct_literal_multiple_files/main.go index c96953f6e..fd801c1bf 100644 --- a/exp/internal/parser/testdata/struct_literal_multiple_files/main.go +++ b/v3/internal/parser/testdata/struct_literal_multiple_files/main.go @@ -4,8 +4,8 @@ import ( _ "embed" "log" - "github.com/wailsapp/wails/exp/pkg/application" - "github.com/wailsapp/wails/exp/pkg/options" + "github.com/wailsapp/wails/v3/pkg/application" + "github.com/wailsapp/wails/v3/pkg/options" ) func main() { diff --git a/exp/internal/parser/testdata/struct_literal_multiple_files/other.go b/v3/internal/parser/testdata/struct_literal_multiple_files/other.go similarity index 100% rename from exp/internal/parser/testdata/struct_literal_multiple_files/other.go rename to v3/internal/parser/testdata/struct_literal_multiple_files/other.go diff --git a/exp/internal/parser/testdata/struct_literal_single/main.go b/v3/internal/parser/testdata/struct_literal_single/main.go similarity index 80% rename from exp/internal/parser/testdata/struct_literal_single/main.go rename to v3/internal/parser/testdata/struct_literal_single/main.go index 4fb639008..cfc684e1c 100644 --- a/exp/internal/parser/testdata/struct_literal_single/main.go +++ b/v3/internal/parser/testdata/struct_literal_single/main.go @@ -4,8 +4,8 @@ import ( _ "embed" "log" - "github.com/wailsapp/wails/exp/pkg/application" - "github.com/wailsapp/wails/exp/pkg/options" + "github.com/wailsapp/wails/v3/pkg/application" + "github.com/wailsapp/wails/v3/pkg/options" ) type GreetService struct { diff --git a/exp/internal/runtime/assets.go b/v3/internal/runtime/assets.go similarity index 100% rename from exp/internal/runtime/assets.go rename to v3/internal/runtime/assets.go diff --git a/exp/internal/runtime/assets_dev.go b/v3/internal/runtime/assets_dev.go similarity index 100% rename from exp/internal/runtime/assets_dev.go rename to v3/internal/runtime/assets_dev.go diff --git a/exp/internal/runtime/desktop/bindings.js b/v3/internal/runtime/desktop/bindings.js similarity index 100% rename from exp/internal/runtime/desktop/bindings.js rename to v3/internal/runtime/desktop/bindings.js diff --git a/exp/internal/runtime/desktop/browser.js b/v3/internal/runtime/desktop/browser.js similarity index 100% rename from exp/internal/runtime/desktop/browser.js rename to v3/internal/runtime/desktop/browser.js diff --git a/exp/internal/runtime/desktop/calls.js b/v3/internal/runtime/desktop/calls.js similarity index 100% rename from exp/internal/runtime/desktop/calls.js rename to v3/internal/runtime/desktop/calls.js diff --git a/exp/internal/runtime/desktop/events.js b/v3/internal/runtime/desktop/events.js similarity index 100% rename from exp/internal/runtime/desktop/events.js rename to v3/internal/runtime/desktop/events.js diff --git a/exp/internal/runtime/desktop/events.test.js b/v3/internal/runtime/desktop/events.test.js similarity index 100% rename from exp/internal/runtime/desktop/events.test.js rename to v3/internal/runtime/desktop/events.test.js diff --git a/exp/internal/runtime/desktop/ipc.js b/v3/internal/runtime/desktop/ipc.js similarity index 100% rename from exp/internal/runtime/desktop/ipc.js rename to v3/internal/runtime/desktop/ipc.js diff --git a/exp/internal/runtime/desktop/log.js b/v3/internal/runtime/desktop/log.js similarity index 100% rename from exp/internal/runtime/desktop/log.js rename to v3/internal/runtime/desktop/log.js diff --git a/exp/internal/runtime/desktop/main.js b/v3/internal/runtime/desktop/main.js similarity index 100% rename from exp/internal/runtime/desktop/main.js rename to v3/internal/runtime/desktop/main.js diff --git a/exp/internal/runtime/desktop/screen.js b/v3/internal/runtime/desktop/screen.js similarity index 100% rename from exp/internal/runtime/desktop/screen.js rename to v3/internal/runtime/desktop/screen.js diff --git a/exp/internal/runtime/desktop/window.js b/v3/internal/runtime/desktop/window.js similarity index 100% rename from exp/internal/runtime/desktop/window.js rename to v3/internal/runtime/desktop/window.js diff --git a/exp/internal/runtime/dev/Overlay.svelte b/v3/internal/runtime/dev/Overlay.svelte similarity index 100% rename from exp/internal/runtime/dev/Overlay.svelte rename to v3/internal/runtime/dev/Overlay.svelte diff --git a/exp/internal/runtime/dev/build.js b/v3/internal/runtime/dev/build.js similarity index 100% rename from exp/internal/runtime/dev/build.js rename to v3/internal/runtime/dev/build.js diff --git a/exp/internal/runtime/dev/log.js b/v3/internal/runtime/dev/log.js similarity index 100% rename from exp/internal/runtime/dev/log.js rename to v3/internal/runtime/dev/log.js diff --git a/exp/internal/runtime/dev/main.js b/v3/internal/runtime/dev/main.js similarity index 100% rename from exp/internal/runtime/dev/main.js rename to v3/internal/runtime/dev/main.js diff --git a/exp/internal/runtime/dev/package-lock.json b/v3/internal/runtime/dev/package-lock.json similarity index 100% rename from exp/internal/runtime/dev/package-lock.json rename to v3/internal/runtime/dev/package-lock.json diff --git a/exp/internal/runtime/dev/package.json b/v3/internal/runtime/dev/package.json similarity index 100% rename from exp/internal/runtime/dev/package.json rename to v3/internal/runtime/dev/package.json diff --git a/exp/internal/runtime/dev/store.js b/v3/internal/runtime/dev/store.js similarity index 100% rename from exp/internal/runtime/dev/store.js rename to v3/internal/runtime/dev/store.js diff --git a/exp/internal/runtime/ipc.go b/v3/internal/runtime/ipc.go similarity index 100% rename from exp/internal/runtime/ipc.go rename to v3/internal/runtime/ipc.go diff --git a/exp/internal/runtime/ipc.js b/v3/internal/runtime/ipc.js similarity index 100% rename from exp/internal/runtime/ipc.js rename to v3/internal/runtime/ipc.js diff --git a/exp/internal/runtime/ipc_websocket.js b/v3/internal/runtime/ipc_websocket.js similarity index 100% rename from exp/internal/runtime/ipc_websocket.js rename to v3/internal/runtime/ipc_websocket.js diff --git a/exp/internal/runtime/package-lock.json b/v3/internal/runtime/package-lock.json similarity index 100% rename from exp/internal/runtime/package-lock.json rename to v3/internal/runtime/package-lock.json diff --git a/exp/internal/runtime/package.json b/v3/internal/runtime/package.json similarity index 100% rename from exp/internal/runtime/package.json rename to v3/internal/runtime/package.json diff --git a/exp/internal/runtime/runtime_debug_darwin.go b/v3/internal/runtime/runtime_debug_darwin.go similarity index 100% rename from exp/internal/runtime/runtime_debug_darwin.go rename to v3/internal/runtime/runtime_debug_darwin.go diff --git a/exp/internal/runtime/runtime_debug_desktop_darwin.js b/v3/internal/runtime/runtime_debug_desktop_darwin.js similarity index 100% rename from exp/internal/runtime/runtime_debug_desktop_darwin.js rename to v3/internal/runtime/runtime_debug_desktop_darwin.js diff --git a/exp/internal/runtime/runtime_debug_desktop_linux.js b/v3/internal/runtime/runtime_debug_desktop_linux.js similarity index 100% rename from exp/internal/runtime/runtime_debug_desktop_linux.js rename to v3/internal/runtime/runtime_debug_desktop_linux.js diff --git a/exp/internal/runtime/runtime_debug_desktop_windows.js b/v3/internal/runtime/runtime_debug_desktop_windows.js similarity index 100% rename from exp/internal/runtime/runtime_debug_desktop_windows.js rename to v3/internal/runtime/runtime_debug_desktop_windows.js diff --git a/exp/internal/runtime/runtime_debug_linux.go b/v3/internal/runtime/runtime_debug_linux.go similarity index 100% rename from exp/internal/runtime/runtime_debug_linux.go rename to v3/internal/runtime/runtime_debug_linux.go diff --git a/exp/internal/runtime/runtime_debug_windows.go b/v3/internal/runtime/runtime_debug_windows.go similarity index 100% rename from exp/internal/runtime/runtime_debug_windows.go rename to v3/internal/runtime/runtime_debug_windows.go diff --git a/exp/internal/runtime/runtime_production_darwin.go b/v3/internal/runtime/runtime_production_darwin.go similarity index 100% rename from exp/internal/runtime/runtime_production_darwin.go rename to v3/internal/runtime/runtime_production_darwin.go diff --git a/exp/internal/runtime/runtime_production_desktop_darwin.js b/v3/internal/runtime/runtime_production_desktop_darwin.js similarity index 100% rename from exp/internal/runtime/runtime_production_desktop_darwin.js rename to v3/internal/runtime/runtime_production_desktop_darwin.js diff --git a/exp/internal/runtime/runtime_production_desktop_linux.js b/v3/internal/runtime/runtime_production_desktop_linux.js similarity index 100% rename from exp/internal/runtime/runtime_production_desktop_linux.js rename to v3/internal/runtime/runtime_production_desktop_linux.js diff --git a/exp/internal/runtime/runtime_production_desktop_windows.js b/v3/internal/runtime/runtime_production_desktop_windows.js similarity index 100% rename from exp/internal/runtime/runtime_production_desktop_windows.js rename to v3/internal/runtime/runtime_production_desktop_windows.js diff --git a/exp/internal/runtime/runtime_production_linux.go b/v3/internal/runtime/runtime_production_linux.go similarity index 100% rename from exp/internal/runtime/runtime_production_linux.go rename to v3/internal/runtime/runtime_production_linux.go diff --git a/exp/internal/runtime/runtime_production_windows.go b/v3/internal/runtime/runtime_production_windows.go similarity index 100% rename from exp/internal/runtime/runtime_production_windows.go rename to v3/internal/runtime/runtime_production_windows.go diff --git a/exp/internal/runtime/vite.config.ts b/v3/internal/runtime/vite.config.ts similarity index 100% rename from exp/internal/runtime/vite.config.ts rename to v3/internal/runtime/vite.config.ts diff --git a/exp/pkg/application/TODO.md b/v3/pkg/application/TODO.md similarity index 100% rename from exp/pkg/application/TODO.md rename to v3/pkg/application/TODO.md diff --git a/exp/pkg/application/app_delegate.h b/v3/pkg/application/app_delegate.h similarity index 100% rename from exp/pkg/application/app_delegate.h rename to v3/pkg/application/app_delegate.h diff --git a/exp/pkg/application/app_delegate.m b/v3/pkg/application/app_delegate.m similarity index 100% rename from exp/pkg/application/app_delegate.m rename to v3/pkg/application/app_delegate.m diff --git a/exp/pkg/application/application.go b/v3/pkg/application/application.go similarity index 98% rename from exp/pkg/application/application.go rename to v3/pkg/application/application.go index 69dacd91e..b640aa2ea 100644 --- a/exp/pkg/application/application.go +++ b/v3/pkg/application/application.go @@ -6,8 +6,8 @@ import ( "runtime" "sync" - "github.com/wailsapp/wails/exp/pkg/events" - "github.com/wailsapp/wails/exp/pkg/options" + "github.com/wailsapp/wails/v3/pkg/events" + "github.com/wailsapp/wails/v3/pkg/options" "github.com/wailsapp/wails/v2/pkg/assetserver/webview" ) diff --git a/exp/pkg/application/application.h b/v3/pkg/application/application.h similarity index 100% rename from exp/pkg/application/application.h rename to v3/pkg/application/application.h diff --git a/exp/pkg/application/application_darwin.go b/v3/pkg/application/application_darwin.go similarity index 99% rename from exp/pkg/application/application_darwin.go rename to v3/pkg/application/application_darwin.go index be665d362..b24fe4c5d 100644 --- a/exp/pkg/application/application_darwin.go +++ b/v3/pkg/application/application_darwin.go @@ -118,8 +118,8 @@ import "C" import ( "unsafe" - "github.com/wailsapp/wails/exp/pkg/events" "github.com/wailsapp/wails/v2/pkg/assetserver/webview" + "github.com/wailsapp/wails/v3/pkg/events" ) type macosApp struct { diff --git a/exp/pkg/application/clipboard.go b/v3/pkg/application/clipboard.go similarity index 100% rename from exp/pkg/application/clipboard.go rename to v3/pkg/application/clipboard.go diff --git a/exp/pkg/application/clipboard_darwin.go b/v3/pkg/application/clipboard_darwin.go similarity index 100% rename from exp/pkg/application/clipboard_darwin.go rename to v3/pkg/application/clipboard_darwin.go diff --git a/exp/pkg/application/context.go b/v3/pkg/application/context.go similarity index 100% rename from exp/pkg/application/context.go rename to v3/pkg/application/context.go diff --git a/exp/pkg/application/dialogs.go b/v3/pkg/application/dialogs.go similarity index 100% rename from exp/pkg/application/dialogs.go rename to v3/pkg/application/dialogs.go diff --git a/exp/pkg/application/dialogs_darwin.go b/v3/pkg/application/dialogs_darwin.go similarity index 100% rename from exp/pkg/application/dialogs_darwin.go rename to v3/pkg/application/dialogs_darwin.go diff --git a/exp/pkg/application/dialogs_delegate.h b/v3/pkg/application/dialogs_delegate.h similarity index 100% rename from exp/pkg/application/dialogs_delegate.h rename to v3/pkg/application/dialogs_delegate.h diff --git a/exp/pkg/application/dialogs_delegate.m b/v3/pkg/application/dialogs_delegate.m similarity index 100% rename from exp/pkg/application/dialogs_delegate.m rename to v3/pkg/application/dialogs_delegate.m diff --git a/exp/pkg/application/errors.go b/v3/pkg/application/errors.go similarity index 100% rename from exp/pkg/application/errors.go rename to v3/pkg/application/errors.go diff --git a/exp/pkg/application/events.go b/v3/pkg/application/events.go similarity index 100% rename from exp/pkg/application/events.go rename to v3/pkg/application/events.go diff --git a/exp/pkg/application/icons.go b/v3/pkg/application/icons.go similarity index 100% rename from exp/pkg/application/icons.go rename to v3/pkg/application/icons.go diff --git a/exp/pkg/application/keys.go b/v3/pkg/application/keys.go similarity index 100% rename from exp/pkg/application/keys.go rename to v3/pkg/application/keys.go diff --git a/exp/pkg/application/keys_darwin.go b/v3/pkg/application/keys_darwin.go similarity index 100% rename from exp/pkg/application/keys_darwin.go rename to v3/pkg/application/keys_darwin.go diff --git a/exp/pkg/application/mainthread.go b/v3/pkg/application/mainthread.go similarity index 100% rename from exp/pkg/application/mainthread.go rename to v3/pkg/application/mainthread.go diff --git a/exp/pkg/application/mainthread_darwin.go b/v3/pkg/application/mainthread_darwin.go similarity index 100% rename from exp/pkg/application/mainthread_darwin.go rename to v3/pkg/application/mainthread_darwin.go diff --git a/exp/pkg/application/menu.go b/v3/pkg/application/menu.go similarity index 100% rename from exp/pkg/application/menu.go rename to v3/pkg/application/menu.go diff --git a/exp/pkg/application/menu_darwin.go b/v3/pkg/application/menu_darwin.go similarity index 100% rename from exp/pkg/application/menu_darwin.go rename to v3/pkg/application/menu_darwin.go diff --git a/exp/pkg/application/menuitem.go b/v3/pkg/application/menuitem.go similarity index 100% rename from exp/pkg/application/menuitem.go rename to v3/pkg/application/menuitem.go diff --git a/exp/pkg/application/menuitem.h b/v3/pkg/application/menuitem.h similarity index 100% rename from exp/pkg/application/menuitem.h rename to v3/pkg/application/menuitem.h diff --git a/exp/pkg/application/menuitem.m b/v3/pkg/application/menuitem.m similarity index 100% rename from exp/pkg/application/menuitem.m rename to v3/pkg/application/menuitem.m diff --git a/exp/pkg/application/menuitem_darwin.go b/v3/pkg/application/menuitem_darwin.go similarity index 100% rename from exp/pkg/application/menuitem_darwin.go rename to v3/pkg/application/menuitem_darwin.go diff --git a/exp/pkg/application/roles.go b/v3/pkg/application/roles.go similarity index 100% rename from exp/pkg/application/roles.go rename to v3/pkg/application/roles.go diff --git a/exp/pkg/application/screen.go b/v3/pkg/application/screen.go similarity index 100% rename from exp/pkg/application/screen.go rename to v3/pkg/application/screen.go diff --git a/exp/pkg/application/screen_darwin.go b/v3/pkg/application/screen_darwin.go similarity index 100% rename from exp/pkg/application/screen_darwin.go rename to v3/pkg/application/screen_darwin.go diff --git a/exp/pkg/application/systemtray.go b/v3/pkg/application/systemtray.go similarity index 100% rename from exp/pkg/application/systemtray.go rename to v3/pkg/application/systemtray.go diff --git a/exp/pkg/application/systemtray_darwin.go b/v3/pkg/application/systemtray_darwin.go similarity index 100% rename from exp/pkg/application/systemtray_darwin.go rename to v3/pkg/application/systemtray_darwin.go diff --git a/exp/pkg/application/webview_window.go b/v3/pkg/application/webview_window.go similarity index 98% rename from exp/pkg/application/webview_window.go rename to v3/pkg/application/webview_window.go index 33356f083..443eb6c8c 100644 --- a/exp/pkg/application/webview_window.go +++ b/v3/pkg/application/webview_window.go @@ -4,12 +4,12 @@ import ( "fmt" "sync" - "github.com/wailsapp/wails/exp/internal/runtime" - "github.com/wailsapp/wails/exp/pkg/events" - "github.com/wailsapp/wails/exp/pkg/options" "github.com/wailsapp/wails/v2/pkg/assetserver" "github.com/wailsapp/wails/v2/pkg/assetserver/webview" assetserveroptions "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "github.com/wailsapp/wails/v3/internal/runtime" + "github.com/wailsapp/wails/v3/pkg/events" + "github.com/wailsapp/wails/v3/pkg/options" ) type ( diff --git a/exp/pkg/application/webview_window.h b/v3/pkg/application/webview_window.h similarity index 100% rename from exp/pkg/application/webview_window.h rename to v3/pkg/application/webview_window.h diff --git a/exp/pkg/application/webview_window.m b/v3/pkg/application/webview_window.m similarity index 100% rename from exp/pkg/application/webview_window.m rename to v3/pkg/application/webview_window.m diff --git a/exp/pkg/application/webview_window_darwin.go b/v3/pkg/application/webview_window_darwin.go similarity index 99% rename from exp/pkg/application/webview_window_darwin.go rename to v3/pkg/application/webview_window_darwin.go index 2f54dbbb9..26affa35a 100644 --- a/exp/pkg/application/webview_window_darwin.go +++ b/v3/pkg/application/webview_window_darwin.go @@ -750,9 +750,9 @@ import ( "sync" "unsafe" - "github.com/wailsapp/wails/exp/pkg/events" + "github.com/wailsapp/wails/v3/pkg/events" - "github.com/wailsapp/wails/exp/pkg/options" + "github.com/wailsapp/wails/v3/pkg/options" ) var showDevTools = func(window unsafe.Pointer) {} diff --git a/exp/pkg/application/webview_window_devtools.go b/v3/pkg/application/webview_window_devtools.go similarity index 100% rename from exp/pkg/application/webview_window_devtools.go rename to v3/pkg/application/webview_window_devtools.go diff --git a/exp/pkg/events/events.go b/v3/pkg/events/events.go similarity index 100% rename from exp/pkg/events/events.go rename to v3/pkg/events/events.go diff --git a/exp/pkg/events/events.h b/v3/pkg/events/events.h similarity index 100% rename from exp/pkg/events/events.h rename to v3/pkg/events/events.h diff --git a/exp/pkg/events/events.txt b/v3/pkg/events/events.txt similarity index 100% rename from exp/pkg/events/events.txt rename to v3/pkg/events/events.txt diff --git a/exp/pkg/events/events_darwin.go b/v3/pkg/events/events_darwin.go similarity index 100% rename from exp/pkg/events/events_darwin.go rename to v3/pkg/events/events_darwin.go diff --git a/exp/pkg/options/application.go b/v3/pkg/options/application.go similarity index 100% rename from exp/pkg/options/application.go rename to v3/pkg/options/application.go diff --git a/exp/pkg/options/mac.go b/v3/pkg/options/mac.go similarity index 100% rename from exp/pkg/options/mac.go rename to v3/pkg/options/mac.go diff --git a/exp/pkg/options/window.go b/v3/pkg/options/window.go similarity index 100% rename from exp/pkg/options/window.go rename to v3/pkg/options/window.go diff --git a/exp/tasks/Taskfile.yml b/v3/tasks/Taskfile.yml similarity index 100% rename from exp/tasks/Taskfile.yml rename to v3/tasks/Taskfile.yml diff --git a/exp/tasks/events/generate.go b/v3/tasks/events/generate.go similarity index 100% rename from exp/tasks/events/generate.go rename to v3/tasks/events/generate.go diff --git a/exp/tasks/png2bytes/png2bytes.go b/v3/tasks/png2bytes/png2bytes.go similarity index 100% rename from exp/tasks/png2bytes/png2bytes.go rename to v3/tasks/png2bytes/png2bytes.go