diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 7dc5b1c8..cb619758 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -40,4 +40,9 @@ Wails is what it is because of the time and effort given by these great people. * [Balakrishna Prasad Ganne](https://github.com/aayush420) * [Charaf Rezrazi](https://github.com/Rezrazi) * [misitebao](https://github.com/misitebao) - * [Elie Grenon](https://github.com/DrunkenPoney) \ No newline at end of file + * [Elie Grenon](https://github.com/DrunkenPoney) + * [SophieAu](https://github.com/SophieAu) + * [Alexander Matviychuk](https://github.com/alexmat) + * [RH12503](https://github.com/RH12503) + * [hi019](https://github.com/hi019) + \ No newline at end of file diff --git a/cmd/helpers.go b/cmd/helpers.go index 6b93b456..d7a65fae 100644 --- a/cmd/helpers.go +++ b/cmd/helpers.go @@ -595,3 +595,9 @@ func ldFlags(po *ProjectOptions, buildMode string) string { } return ldflags } + +func getGitConfigValue(key string) (string, error) { + output, err := exec.Command("git", "config", "--get", "--null", key).Output() + // When using --null git appends a null character (\u0000) to the command output + return strings.TrimRight(string(output), "\u0000"), err +} diff --git a/cmd/linux.go b/cmd/linux.go index 4d5b91ca..4d55bc04 100644 --- a/cmd/linux.go +++ b/cmd/linux.go @@ -67,6 +67,8 @@ const ( Ctlos // EndeavourOS linux distribution EndeavourOS + // Crux linux distribution + Crux ) // DistroInfo contains all the information relating to a linux distribution @@ -175,6 +177,8 @@ func parseOsRelease(osRelease string) *DistroInfo { result.Distribution = Solus case "endeavouros": result.Distribution = EndeavourOS + case "crux": + result.Distribution = Crux default: result.Distribution = Unknown } @@ -255,6 +259,17 @@ func RpmInstalled(packageName string) (bool, error) { return exitCode == 0, nil } +// PrtGetInstalled uses prt-get to see if a package is installed +func PrtGetInstalled(packageName string) (bool, error) { + program := NewProgramHelper() + prtget := program.FindProgram("prt-get") + if prtget == nil { + return false, fmt.Errorf("cannot check dependencies: prt-get not found") + } + _, _, exitCode, _ := prtget.Run("isinst", packageName) + return exitCode == 0, nil +} + // RequestSupportForDistribution promts the user to submit a request to support their // currently unsupported distribution func RequestSupportForDistribution(distroInfo *DistroInfo) error { diff --git a/cmd/linuxdb.yaml b/cmd/linuxdb.yaml index 616ccd0f..13920279 100644 --- a/cmd/linuxdb.yaml +++ b/cmd/linuxdb.yaml @@ -307,3 +307,22 @@ distributions: gccversioncommand: *gccdumpfullversion programs: *opensusedefaultprograms libraries: *opensusedefaultlibraries + crux: + id: crux + releases: + default: + version: default + name: Crux Linux + gccversioncommand: *gccdumpversion + programs: + - name: gcc + help: Please install with `sudo prt-get depinst gcc-c++ make` and try again + - name: pkg-config + help: Please install with `sudo prt-get depinst pkg-config` and try again + - name: npm + help: Please install with `sudo prt-get depinst nodejs` and try again + libraries: + - name: gtk3 + help: Please install with `sudo prt-get depinst gtk3` and try again + - name: webkitgtk + help: Please install with `sudo prt-get depinst webkitgtk` and try again diff --git a/cmd/system.go b/cmd/system.go index ab3c9e5d..ddf8ffdb 100644 --- a/cmd/system.go +++ b/cmd/system.go @@ -99,11 +99,16 @@ func (s *SystemHelper) setup() error { if config.Name != "" { systemConfig["name"] = PromptRequired("What is your name", config.Name) + } else if n, err := getGitConfigValue("user.name"); err == nil && n != "" { + systemConfig["name"] = PromptRequired("What is your name", n) } else { systemConfig["name"] = PromptRequired("What is your name") } + if config.Email != "" { systemConfig["email"] = PromptRequired("What is your email address", config.Email) + } else if e, err := getGitConfigValue("user.email"); err == nil && e != "" { + systemConfig["email"] = PromptRequired("What is your email address", e) } else { systemConfig["email"] = PromptRequired("What is your email address") } @@ -180,7 +185,7 @@ func (s *SystemHelper) Initialise() error { return s.setup() } -// SystemConfig - Defines system wode configuration data +// SystemConfig - Defines system wide configuration data type SystemConfig struct { Name string `json:"name"` Email string `json:"email"` @@ -286,6 +291,8 @@ func CheckDependencies(logger *Logger) (bool, error) { libraryChecker = XbpsInstalled case Solus: libraryChecker = EOpkgInstalled + case Crux: + libraryChecker = PrtGetInstalled default: return false, RequestSupportForDistribution(distroInfo) } diff --git a/cmd/templates/angular-template/frontend/package.json.template b/cmd/templates/angular-template/frontend/package.json.template index 7b2ae827..ee5c0d05 100644 --- a/cmd/templates/angular-template/frontend/package.json.template +++ b/cmd/templates/angular-template/frontend/package.json.template @@ -3,7 +3,7 @@ "version": "0.0.0", "scripts": { "ng": "npx ng", - "start": "npx ng serve --poll=2000 --host=0.0.0.0", + "serve": "npx ng serve --poll=2000 --host=0.0.0.0", "build": "npx ng build --single-bundle true --output-hashing none --prod --bundle-styles false", "test": "npx ng test", "lint": "npx ng lint", diff --git a/cmd/templates/angular-template/template.json b/cmd/templates/angular-template/template.json index 89ac169e..c2b25832 100644 --- a/cmd/templates/angular-template/template.json +++ b/cmd/templates/angular-template/template.json @@ -14,7 +14,7 @@ "author": "bh90210 ", "created": "2019-06-15 18:23:48.666414555 +0300 EEST m=+223.934866008", "frontenddir": "frontend", - "serve": "npx ng serve --poll=2000", + "serve": "npm run serve", "bridge": "src", "wailsdir": "" } \ No newline at end of file diff --git a/cmd/templates/create-react-app/frontend/package.json.template b/cmd/templates/create-react-app/frontend/package.json.template index 8cd6ded3..a940d3d1 100644 --- a/cmd/templates/create-react-app/frontend/package.json.template +++ b/cmd/templates/create-react-app/frontend/package.json.template @@ -12,7 +12,7 @@ "@wailsapp/runtime": "^1.0.10" }, "scripts": { - "start": "react-scripts start", + "serve": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" diff --git a/cmd/templates/create-react-app/template.json b/cmd/templates/create-react-app/template.json index 57ef5d90..ea6acbed 100755 --- a/cmd/templates/create-react-app/template.json +++ b/cmd/templates/create-react-app/template.json @@ -8,7 +8,7 @@ "author": "bh90210 ", "created": "2019-06-07 18:23:48.666414555 +0300 EEST m=+223.934866008", "frontenddir": "frontend", - "serve": "npm run start", + "serve": "npm run serve", "bridge": "src", "wailsdir": "" } diff --git a/cmd/templates/svelte/frontend/package.json.template b/cmd/templates/svelte/frontend/package.json.template index 167ed910..d833ead1 100644 --- a/cmd/templates/svelte/frontend/package.json.template +++ b/cmd/templates/svelte/frontend/package.json.template @@ -3,7 +3,7 @@ "author": "{{.Author.Name}}<{{.Author.Email}}>", "scripts": { "build": "rollup -c", - "dev": "rollup -c -w", + "serve": "rollup -c -w", "start": "sirv public" }, "devDependencies": { diff --git a/cmd/templates/svelte/frontend/rollup.config.js b/cmd/templates/svelte/frontend/rollup.config.js index c6b831f2..ac3a0a76 100644 --- a/cmd/templates/svelte/frontend/rollup.config.js +++ b/cmd/templates/svelte/frontend/rollup.config.js @@ -80,7 +80,6 @@ export default { { targets: '> 0.25%, not dead, IE 11', modules: false, - spec: true, useBuiltIns: 'usage', forceAllTransforms: true, corejs: 3, diff --git a/cmd/templates/svelte/template.json b/cmd/templates/svelte/template.json index 0b1c0ba3..dea6ed19 100755 --- a/cmd/templates/svelte/template.json +++ b/cmd/templates/svelte/template.json @@ -8,7 +8,7 @@ "author": "Tim Kipp ", "created": "2020-09-06 13:06:10.469848 -0700 PDT m=+213.578828559", "frontenddir": "frontend", - "serve": "npm run dev", + "serve": "npm run serve", "bridge": "src", "wailsdir": "" } diff --git a/cmd/version.go b/cmd/version.go index 0477f008..3b428d1a 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -1,4 +1,4 @@ package cmd // Version - Wails version -const Version = "v1.11.0" \ No newline at end of file +const Version = "v1.12.1" diff --git a/lib/event/manager.go b/lib/event/manager.go index 6020fd34..23e4f31c 100644 --- a/lib/event/manager.go +++ b/lib/event/manager.go @@ -18,6 +18,7 @@ type Manager struct { log *logger.CustomLogger renderer interfaces.Renderer // Messages will be dispatched to the frontend wg sync.WaitGroup + mu sync.Mutex } // NewManager creates a new event manager with a 100 event buffer @@ -42,12 +43,12 @@ func (e *Manager) PushEvent(eventData *messages.EventData) { // means it does not expire (default). type eventListener struct { callback func(...interface{}) // Function to call with emitted event data - counter int // Expire after counter callbacks. 0 = infinite + counter uint // Expire after counter callbacks. 0 = infinite expired bool // Indicates if the listener has expired } // Creates a new event listener from the given callback function -func (e *Manager) addEventListener(eventName string, callback func(...interface{}), counter int) error { +func (e *Manager) addEventListener(eventName string, callback func(...interface{}), counter uint) error { // Sanity check inputs if callback == nil { @@ -75,7 +76,30 @@ func (e *Manager) addEventListener(eventName string, callback func(...interface{ // On adds a listener for the given event func (e *Manager) On(eventName string, callback func(...interface{})) { // Add a persistent eventListener (counter = 0) - e.addEventListener(eventName, callback, 0) + err := e.addEventListener(eventName, callback, 0) + if err != nil { + e.log.Error(err.Error()) + } +} + +// Once adds a listener for the given event that will auto remove +// after one callback +func (e *Manager) Once(eventName string, callback func(...interface{})) { + // Add a persistent eventListener (counter = 0) + err := e.addEventListener(eventName, callback, 1) + if err != nil { + e.log.Error(err.Error()) + } +} + +// OnMultiple adds a listener for the given event that will trigger +// at most times. +func (e *Manager) OnMultiple(eventName string, callback func(...interface{}), counter uint) { + // Add a persistent eventListener (counter = 0) + err := e.addEventListener(eventName, callback, counter) + if err != nil { + e.log.Error(err.Error()) + } } // Emit broadcasts the given event to the subscribed listeners @@ -108,20 +132,24 @@ func (e *Manager) Start(renderer interfaces.Renderer) { }) // Notify renderer - e.renderer.NotifyEvent(event) + err := e.renderer.NotifyEvent(event) + if err != nil { + e.log.Error(err.Error()) + } - // Notify Go listeners - var listenersToRemove []*eventListener + e.mu.Lock() // Iterate listeners for _, listener := range e.listeners[event.Name] { - // Call listener, perhaps with data - if event.Data == nil { - go listener.callback() - } else { - unpacked := event.Data.([]interface{}) - go listener.callback(unpacked...) + if !listener.expired { + // Call listener, perhaps with data + if event.Data == nil { + go listener.callback() + } else { + unpacked := event.Data.([]interface{}) + go listener.callback(unpacked...) + } } // Update listen counter @@ -133,15 +161,8 @@ func (e *Manager) Start(renderer interfaces.Renderer) { } } - // Remove expired listeners in place - if len(listenersToRemove) > 0 { - listeners := e.listeners[event.Name][:0] - for _, listener := range listeners { - if !listener.expired { - listeners = append(listeners, listener) - } - } - } + e.mu.Unlock() + case <-e.quitChannel: e.running = false } diff --git a/lib/interfaces/eventmanager.go b/lib/interfaces/eventmanager.go index c4f4e51f..4805ee2b 100644 --- a/lib/interfaces/eventmanager.go +++ b/lib/interfaces/eventmanager.go @@ -6,6 +6,8 @@ import "github.com/wailsapp/wails/lib/messages" type EventManager interface { PushEvent(*messages.EventData) Emit(eventName string, optionalData ...interface{}) + OnMultiple(eventName string, callback func(...interface{}), counter uint) + Once(eventName string, callback func(...interface{})) On(eventName string, callback func(...interface{})) Start(Renderer) Shutdown() diff --git a/lib/renderer/webview.go b/lib/renderer/webview.go index c51e76bc..1c0ff73a 100644 --- a/lib/renderer/webview.go +++ b/lib/renderer/webview.go @@ -256,6 +256,9 @@ func (w *WebView) SelectFile(title string, filter string) string { wg.Done() }) }() + + defer w.focus() // Ensure the main window is put back into focus afterwards + wg.Wait() return result } @@ -274,6 +277,9 @@ func (w *WebView) SelectDirectory() string { wg.Done() }) }() + + defer w.focus() // Ensure the main window is put back into focus afterwards + wg.Wait() return result } @@ -292,10 +298,20 @@ func (w *WebView) SelectSaveFile(title string, filter string) string { wg.Done() }) }() + + defer w.focus() // Ensure the main window is put back into focus afterwards + wg.Wait() return result } +// focus puts the main window into focus +func (w *WebView) focus() { + w.window.Dispatch(func() { + w.window.Focus() + }) +} + // callback sends a callback to the frontend func (w *WebView) callback(data string) error { callbackCMD := fmt.Sprintf("window.wails._.Callback('%s');", data) diff --git a/lib/renderer/webview/webview.go b/lib/renderer/webview/webview.go index f8ac2b70..0e5da75c 100755 --- a/lib/renderer/webview/webview.go +++ b/lib/renderer/webview/webview.go @@ -65,6 +65,10 @@ static inline void CgoWebViewSetTitle(void *w, char *title) { webview_set_title((struct webview *)w, title); } +static inline void CgoWebViewFocus(void *w) { + webview_focus((struct webview *)w); +} + static inline void CgoWebViewSetFullscreen(void *w, int fullscreen) { webview_set_fullscreen((struct webview *)w, fullscreen); } @@ -170,6 +174,10 @@ type WebView interface { // SetTitle() changes window title. This method must be called from the main // thread only. See Dispatch() for more details. SetTitle(title string) + + // Focus() puts the main window into focus + Focus() + // SetFullscreen() controls window full-screen mode. This method must be // called from the main thread only. See Dispatch() for more details. SetFullscreen(fullscreen bool) @@ -307,6 +315,10 @@ func (w *webview) SetColor(r, g, b, a uint8) { C.CgoWebViewSetColor(w.w, C.uint8_t(r), C.uint8_t(g), C.uint8_t(b), C.uint8_t(a)) } +func (w *webview) Focus() { + C.CgoWebViewFocus(w.w) +} + func (w *webview) SetFullscreen(fullscreen bool) { C.CgoWebViewSetFullscreen(w.w, C.int(boolToInt(fullscreen))) } @@ -353,7 +365,9 @@ func _webviewDispatchGoCallback(index unsafe.Pointer) { f = fns[uintptr(index)] delete(fns, uintptr(index)) m.Unlock() - f() + if f != nil { + f() + } } //export _webviewExternalInvokeCallback @@ -369,5 +383,7 @@ func _webviewExternalInvokeCallback(w unsafe.Pointer, data unsafe.Pointer) { } } m.Unlock() - cb(wv, C.GoString((*C.char)(data))) + if cb != nil { + cb(wv, C.GoString((*C.char)(data))) + } } diff --git a/lib/renderer/webview/webview.h b/lib/renderer/webview/webview.h index c08cb479..f1327b59 100644 --- a/lib/renderer/webview/webview.h +++ b/lib/renderer/webview/webview.h @@ -168,6 +168,7 @@ struct webview_priv WEBVIEW_API int webview_eval(struct webview *w, const char *js); WEBVIEW_API int webview_inject_css(struct webview *w, const char *css); WEBVIEW_API void webview_set_title(struct webview *w, const char *title); + WEBVIEW_API void webview_focus(struct webview *w); WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen); WEBVIEW_API void webview_set_color(struct webview *w, uint8_t r, uint8_t g, uint8_t b, uint8_t a); @@ -396,6 +397,11 @@ struct webview_priv gtk_window_set_title(GTK_WINDOW(w->priv.window), title); } + WEBVIEW_API void webview_focus(struct webview *w) + { + gtk_window_present(GTK_WINDOW(w->priv.window)); + } + WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen) { if (fullscreen) @@ -1641,6 +1647,11 @@ struct webview_priv #endif } + WEBVIEW_API void webview_focus(struct webview *w) + { + SetFocus(w->priv.hwnd); + } + WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen) { if (w->priv.is_fullscreen == !!fullscreen) @@ -2208,6 +2219,11 @@ struct webview_priv [w->priv.window setTitle:nsTitle]; } + WEBVIEW_API void webview_focus(struct webview *w) + { + [w->priv.window makeKeyWindow]; + } + WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen) { int b = ((([w->priv.window styleMask] & NSWindowStyleMaskFullScreen) == diff --git a/runtime/events.go b/runtime/events.go index 70cff403..ffbeaa5a 100644 --- a/runtime/events.go +++ b/runtime/events.go @@ -19,6 +19,16 @@ func (r *Events) On(eventName string, callback func(optionalData ...interface{}) r.eventManager.On(eventName, callback) } +// Once pass through +func (r *Events) Once(eventName string, callback func(optionalData ...interface{})) { + r.eventManager.Once(eventName, callback) +} + +// OnMultiple pass through +func (r *Events) OnMultiple(eventName string, callback func(optionalData ...interface{}), counter uint) { + r.eventManager.OnMultiple(eventName, callback, counter) +} + // Emit pass through func (r *Events) Emit(eventName string, optionalData ...interface{}) { r.eventManager.Emit(eventName, optionalData...) diff --git a/scripts/build.sh b/scripts/build.sh index fc838f2e..0e9d172a 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash echo "**** Checking if Wails passes unit tests ****" -if ! go test ./... +if ! go test ./lib/... ./runtime/... ./cmd/... then echo "" echo "ERROR: Unit tests failed!"