mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-07 00:02:39 +08:00
[v3] Update application.On
and window.On
to return functions that unregister the listener. WebviewWindow.onApplicationEvent
is a helper which will manage the unregistering for you on window destroy.
This commit is contained in:
parent
178ea9c8c5
commit
f08ae2fc62
@ -1,6 +1,7 @@
|
||||
package application
|
||||
|
||||
import (
|
||||
"github.com/samber/lo"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
@ -23,6 +24,10 @@ func init() {
|
||||
runtime.LockOSThread()
|
||||
}
|
||||
|
||||
type EventListener struct {
|
||||
callback func()
|
||||
}
|
||||
|
||||
func New(appOptions Options) *App {
|
||||
if globalApplication != nil {
|
||||
return globalApplication
|
||||
@ -32,7 +37,7 @@ func New(appOptions Options) *App {
|
||||
|
||||
result := &App{
|
||||
options: appOptions,
|
||||
applicationEventListeners: make(map[uint][]func()),
|
||||
applicationEventListeners: make(map[uint][]*EventListener),
|
||||
systemTrays: make(map[uint]*SystemTray),
|
||||
log: logger.New(appOptions.Logger.CustomLoggers...),
|
||||
contextMenus: make(map[string]*Menu),
|
||||
@ -155,7 +160,7 @@ var webviewRequests = make(chan *webViewAssetRequest)
|
||||
|
||||
type App struct {
|
||||
options Options
|
||||
applicationEventListeners map[uint][]func()
|
||||
applicationEventListeners map[uint][]*EventListener
|
||||
applicationEventListenersLock sync.RWMutex
|
||||
|
||||
// Windows
|
||||
@ -216,14 +221,25 @@ func (a *App) deleteWindowByID(id uint) {
|
||||
delete(a.windows, id)
|
||||
}
|
||||
|
||||
func (a *App) On(eventType events.ApplicationEventType, callback func()) {
|
||||
func (a *App) On(eventType events.ApplicationEventType, callback func()) func() {
|
||||
eventID := uint(eventType)
|
||||
a.applicationEventListenersLock.Lock()
|
||||
defer a.applicationEventListenersLock.Unlock()
|
||||
a.applicationEventListeners[eventID] = append(a.applicationEventListeners[eventID], callback)
|
||||
listener := &EventListener{
|
||||
callback: callback,
|
||||
}
|
||||
a.applicationEventListeners[eventID] = append(a.applicationEventListeners[eventID], listener)
|
||||
if a.impl != nil {
|
||||
go a.impl.on(eventID)
|
||||
}
|
||||
|
||||
return func() {
|
||||
// lock the map
|
||||
a.applicationEventListenersLock.Lock()
|
||||
defer a.applicationEventListenersLock.Unlock()
|
||||
// Remove listener
|
||||
a.applicationEventListeners[eventID] = lo.Without(a.applicationEventListeners[eventID], listener)
|
||||
}
|
||||
}
|
||||
func (a *App) NewWebviewWindow() *WebviewWindow {
|
||||
return a.NewWebviewWindowWithOptions(&WebviewWindowOptions{})
|
||||
@ -383,7 +399,7 @@ func (a *App) handleApplicationEvent(event uint) {
|
||||
return
|
||||
}
|
||||
for _, listener := range listeners {
|
||||
go listener()
|
||||
go listener.callback()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ package application
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/samber/lo"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -61,17 +62,25 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
type WindowEventListener struct {
|
||||
callback func(ctx *WindowEventContext)
|
||||
}
|
||||
|
||||
type WebviewWindow struct {
|
||||
options *WebviewWindowOptions
|
||||
impl webviewWindowImpl
|
||||
implLock sync.RWMutex
|
||||
id uint
|
||||
|
||||
eventListeners map[uint][]func(ctx *WindowEventContext)
|
||||
eventListeners map[uint][]*WindowEventListener
|
||||
eventListenersLock sync.RWMutex
|
||||
|
||||
contextMenus map[string]*Menu
|
||||
contextMenusLock sync.RWMutex
|
||||
|
||||
// A map of listener cancellation functions
|
||||
cancellersLock sync.RWMutex
|
||||
cancellers []func()
|
||||
}
|
||||
|
||||
var windowID uint
|
||||
@ -84,6 +93,13 @@ func getWindowID() uint {
|
||||
return windowID
|
||||
}
|
||||
|
||||
// Use onApplicationEvent to register a callback for an application event from a window.
|
||||
// This will handle tidying up the callback when the window is destroyed
|
||||
func (w *WebviewWindow) onApplicationEvent(eventType events.ApplicationEventType, callback func()) {
|
||||
cancelFn := globalApplication.On(eventType, callback)
|
||||
w.addCancellationFunction(cancelFn)
|
||||
}
|
||||
|
||||
func NewWindow(options *WebviewWindowOptions) *WebviewWindow {
|
||||
if options.Width == 0 {
|
||||
options.Width = 800
|
||||
@ -98,13 +114,19 @@ func NewWindow(options *WebviewWindowOptions) *WebviewWindow {
|
||||
result := &WebviewWindow{
|
||||
id: getWindowID(),
|
||||
options: options,
|
||||
eventListeners: make(map[uint][]func(ctx *WindowEventContext)),
|
||||
eventListeners: make(map[uint][]*WindowEventListener),
|
||||
contextMenus: make(map[string]*Menu),
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (w *WebviewWindow) addCancellationFunction(canceller func()) {
|
||||
w.cancellersLock.Lock()
|
||||
defer w.cancellersLock.Unlock()
|
||||
w.cancellers = append(w.cancellers, canceller)
|
||||
}
|
||||
|
||||
func (w *WebviewWindow) SetTitle(title string) *WebviewWindow {
|
||||
w.implLock.RLock()
|
||||
defer w.implLock.RUnlock()
|
||||
@ -371,20 +393,30 @@ func (w *WebviewWindow) Center() {
|
||||
w.impl.center()
|
||||
}
|
||||
|
||||
func (w *WebviewWindow) On(eventType events.WindowEventType, callback func(ctx *WindowEventContext)) {
|
||||
func (w *WebviewWindow) On(eventType events.WindowEventType, callback func(ctx *WindowEventContext)) func() {
|
||||
eventID := uint(eventType)
|
||||
w.eventListenersLock.Lock()
|
||||
defer w.eventListenersLock.Unlock()
|
||||
w.eventListeners[eventID] = append(w.eventListeners[eventID], callback)
|
||||
windowEventListener := &WindowEventListener{
|
||||
callback: callback,
|
||||
}
|
||||
w.eventListeners[eventID] = append(w.eventListeners[eventID], windowEventListener)
|
||||
if w.impl != nil {
|
||||
w.impl.on(eventID)
|
||||
}
|
||||
|
||||
return func() {
|
||||
w.eventListenersLock.Lock()
|
||||
defer w.eventListenersLock.Unlock()
|
||||
w.eventListeners[eventID] = lo.Without(w.eventListeners[eventID], windowEventListener)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (w *WebviewWindow) handleWindowEvent(id uint) {
|
||||
w.eventListenersLock.RLock()
|
||||
for _, callback := range w.eventListeners[id] {
|
||||
go callback(blankWindowEventContext)
|
||||
for _, listener := range w.eventListeners[id] {
|
||||
go listener.callback(blankWindowEventContext)
|
||||
}
|
||||
w.eventListenersLock.RUnlock()
|
||||
}
|
||||
@ -416,6 +448,10 @@ func (w *WebviewWindow) Destroy() {
|
||||
if w.impl == nil {
|
||||
return
|
||||
}
|
||||
// Cancel the callbacks
|
||||
for _, cancelFunc := range w.cancellers {
|
||||
cancelFunc()
|
||||
}
|
||||
w.impl.destroy()
|
||||
}
|
||||
|
||||
@ -631,7 +667,7 @@ func (w *WebviewWindow) handleDragAndDropMessage(event *dragAndDropMessage) {
|
||||
ctx := newWindowEventContext()
|
||||
ctx.setDroppedFiles(event.filenames)
|
||||
for _, listener := range w.eventListeners[uint(events.FilesDropped)] {
|
||||
listener(ctx)
|
||||
listener.callback(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,7 +140,8 @@ func (w *windowsWebviewWindow) _run() {
|
||||
switch options.Windows.Theme {
|
||||
case SystemDefault:
|
||||
w.updateTheme(w32.IsCurrentlyDarkMode())
|
||||
globalApplication.On(events.Windows.SystemThemeChanged, func() {
|
||||
// Setup a listener to respond to theme changes
|
||||
w.parent.onApplicationEvent(events.Windows.SystemThemeChanged, func() {
|
||||
w.updateTheme(w32.IsCurrentlyDarkMode())
|
||||
})
|
||||
case Light:
|
||||
|
Loading…
Reference in New Issue
Block a user