5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-02 06:01:48 +08:00

update wml events to be parseable (#2561)

* update wml events to be parseable

* [v3] Rename `CustomEvent` to `WailsEvent` to prevent clashing with the standard JS `CustomEvent` object

---------

Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
This commit is contained in:
Travis McLane 2023-04-11 03:28:06 -05:00 committed by GitHub
parent 9574bfc054
commit a7bf359930
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 146 additions and 101 deletions

View File

@ -18,15 +18,15 @@ Window events are events that are emitted by a window. These events include nati
### Custom Events
Events that the user defines are called `CustomEvents`. This is to differentiate them from the `Event` object that is used to communicate with the browser. CustomEvents are now objects that encapsulate all the details of an event. This includes the event name, the data, and the source of the event.
Events that the user defines are called `WailsEvents`. This is to differentiate them from the `Event` object that is used to communicate with the browser. WailsEvents are now objects that encapsulate all the details of an event. This includes the event name, the data, and the source of the event.
The data associated with a CustomEvent is now a single value. If multiple values are required, then a struct can be used.
The data associated with a WailsEvent is now a single value. If multiple values are required, then a struct can be used.
### Event callbacks and `Emit` function signature
The signatures events callbacks (as used by `On`, `Once` & `OnMultiple`) have changed. In v2, the callback function received optional data. In v3, the callback function receives a `CustomEvent` object that contains all data related to the event.
The signatures events callbacks (as used by `On`, `Once` & `OnMultiple`) have changed. In v2, the callback function received optional data. In v3, the callback function receives a `WailsEvent` object that contains all data related to the event.
Similarly, the `Emit` function has changed. Instead of taking a name and optional data, it now takes a single `CustomEvent` object that it will emit.
Similarly, the `Emit` function has changed. Instead of taking a name and optional data, it now takes a single `WailsEvent` object that it will emit.
### `Off` and `OffAll`

View File

@ -37,7 +37,7 @@ func main() {
window.On(events.FilesDropped, func(ctx *application.WindowEventContext) {
files := ctx.DroppedFiles()
app.Events.Emit(&application.CustomEvent{
app.Events.Emit(&application.WailsEvent{
Name: "files",
Data: files,
})

View File

@ -26,14 +26,14 @@ func main() {
},
})
app.Events.On("myevent", func(e *application.CustomEvent) {
log.Printf("[Go] CustomEvent received: %+v\n", e)
app.Events.On("myevent", func(e *application.WailsEvent) {
log.Printf("[Go] WailsEvent received: %+v\n", e)
})
app.On(events.Mac.ApplicationDidFinishLaunching, func() {
for {
log.Println("Sending event")
app.Events.Emit(&application.CustomEvent{
app.Events.Emit(&application.WailsEvent{
Name: "myevent",
Data: "hello",
})

View File

@ -34,7 +34,7 @@ func main() {
URL: "/",
})
app.Events.On("clicked", func(_ *application.CustomEvent) {
app.Events.On("clicked", func(_ *application.WailsEvent) {
println("clicked")
})

View File

@ -35,10 +35,10 @@ func main() {
},
})
app.Events.On("button-pressed", func(_ *application.CustomEvent) {
app.Events.On("button-pressed", func(_ *application.WailsEvent) {
println("Button Pressed!")
})
app.Events.On("hover", func(_ *application.CustomEvent) {
app.Events.On("hover", func(_ *application.WailsEvent) {
println("Hover time!")
})

View File

@ -0,0 +1,3 @@
# Runtime
To rebuild the runtime run `task build-runtime` or if you have Wails v3 CLI, you can use `wails task build-runtime`.

View File

@ -344,7 +344,7 @@ export interface Rect {
Height: number;
}
export interface CustomEvent {
export interface WailsEvent {
// The name of the event
Name: string;
// The data associated with the event

View File

@ -107,7 +107,7 @@ export interface Rect {
Height: number;
}
export interface CustomEvent {
export interface WailsEvent {
// The name of the event
Name: string;
// The data associated with the event

View File

@ -11,7 +11,7 @@ The electron alternative for Go
/* jshint esversion: 9 */
/**
* @typedef {import("./api/types").CustomEvent} CustomEvent
* @typedef {import("./api/types").WailsEvent} WailsEvent
*/
import {newRuntimeCaller} from "./runtime";
@ -52,18 +52,20 @@ class Listener {
/**
* CustomEvent defines a custom event. It is passed to event listeners.
* WailsEvent defines a custom event. It is passed to event listeners.
*
* @class CustomEvent
* @class WailsEvent
* @property {string} name - Name of the event
* @property {any} data - Data associated with the event
*/
export class CustomEvent {
export class WailsEvent {
/**
* Creates an instance of CustomEvent.
* Creates an instance of WailsEvent.
* @param {string} name - Name of the event
* @param {any} data - Data associated with the event
* @memberof CustomEvent
* @param {any=null} data - Data associated with the event
* @memberof WailsEvent
*/
constructor(name, data) {
constructor(name, data = null) {
this.name = name;
this.data = data;
}
@ -76,7 +78,7 @@ export const eventListeners = new Map();
*
* @export
* @param {string} eventName
* @param {function(CustomEvent): void} callback
* @param {function(WailsEvent): void} callback
* @param {number} maxCallbacks
* @returns {function} A function to cancel the listener
*/
@ -93,7 +95,7 @@ export function OnMultiple(eventName, callback, maxCallbacks) {
*
* @export
* @param {string} eventName
* @param {function(CustomEvent): void} callback
* @param {function(WailsEvent): void} callback
* @returns {function} A function to cancel the listener
*/
export function On(eventName, callback) {
@ -105,7 +107,7 @@ export function On(eventName, callback) {
*
* @export
* @param {string} eventName
* @param {function(CustomEvent): void} callback
* @param {function(WailsEvent): void} callback
@returns {function} A function to cancel the listener
*/
export function Once(eventName, callback) {
@ -132,9 +134,9 @@ function listenerOff(listener) {
* dispatches an event to all listeners
*
* @export
* @param {CustomEvent} event
* @param {WailsEvent} event
*/
export function dispatchCustomEvent(event) {
export function dispatchWailsEvent(event) {
console.log("dispatching event: ", {event});
let listeners = eventListeners.get(event.name);
if (listeners) {
@ -185,7 +187,7 @@ export function OffAll() {
/**
* Emit an event
* @param {CustomEvent} event The event to emit
* @param {WailsEvent} event The event to emit
*/
export function Emit(event) {
void call("Emit", event);

View File

@ -1,34 +1,34 @@
import { On, Off, OffAll, OnMultiple, CustomEvent, dispatchCustomEvent, eventListeners, Once } from './events'
import { expect, describe, it, vi, afterEach, beforeEach } from 'vitest'
import { On, Off, OffAll, OnMultiple, WailsEvent, dispatchWailsEvent, eventListeners, Once } from './events';
import { expect, describe, it, vi, afterEach, beforeEach } from 'vitest';
afterEach(() => {
OffAll();
vi.resetAllMocks()
})
vi.resetAllMocks();
});
describe('OnMultiple', () => {
let testEvent = new CustomEvent('a', {})
let testEvent = new WailsEvent('a', {});
it('should stop after a specified number of times', () => {
const cb = vi.fn()
OnMultiple('a', cb, 5)
dispatchCustomEvent(testEvent)
dispatchCustomEvent(testEvent)
dispatchCustomEvent(testEvent)
dispatchCustomEvent(testEvent)
dispatchCustomEvent(testEvent)
dispatchCustomEvent(testEvent)
const cb = vi.fn();
OnMultiple('a', cb, 5);
dispatchWailsEvent(testEvent);
dispatchWailsEvent(testEvent);
dispatchWailsEvent(testEvent);
dispatchWailsEvent(testEvent);
dispatchWailsEvent(testEvent);
dispatchWailsEvent(testEvent);
expect(cb).toBeCalledTimes(5);
})
});
it('should return a cancel fn', () => {
const cb = vi.fn()
const cancel = OnMultiple('a', cb, 5)
dispatchCustomEvent(testEvent)
dispatchCustomEvent(testEvent)
dispatchWailsEvent(testEvent)
dispatchWailsEvent(testEvent)
cancel()
dispatchCustomEvent(testEvent)
dispatchCustomEvent(testEvent)
dispatchWailsEvent(testEvent)
dispatchWailsEvent(testEvent)
expect(cb).toBeCalledTimes(2)
})
})

View File

@ -16,7 +16,7 @@ import * as Log from './log';
import * as Screens from './screens';
import {Plugin, Call, callErrorCallback, callCallback} from "./calls";
import {newWindow} from "./window";
import {dispatchCustomEvent, Emit, Off, OffAll, On, Once, OnMultiple} from "./events";
import {dispatchWailsEvent, Emit, Off, OffAll, On, Once, OnMultiple} from "./events";
import {dialogCallback, dialogErrorCallback, Error, Info, OpenFile, Question, SaveFile, Warning,} from "./dialogs";
import {enableContextMenus} from "./contextmenu";
import {reloadWML} from "./wml";
@ -29,7 +29,7 @@ window.wails = {
window._wails = {
dialogCallback,
dialogErrorCallback,
dispatchCustomEvent,
dispatchWailsEvent,
callCallback,
callErrorCallback,
};

View File

@ -1,8 +1,9 @@
import {Emit} from "./events";
import {Emit, WailsEvent} from "./events";
import {Question} from "./dialogs";
function sendEvent(event) {
function sendEvent(eventName, data=null) {
let event = new WailsEvent(eventName, data);
Emit(event);
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -45,7 +45,7 @@ func New(appOptions Options) *App {
result.log.AddOutput(&logger.Console{})
}
result.Events = NewCustomEventProcessor(result.dispatchEventToWindows)
result.Events = NewWailsEventProcessor(result.dispatchEventToWindows)
opts := assetserveroptions.Options{
Assets: appOptions.Assets.FS,
@ -547,9 +547,9 @@ func (a *App) SaveFileDialogWithOptions(s *SaveFileDialogOptions) *SaveFileDialo
return result
}
func (a *App) dispatchEventToWindows(event *CustomEvent) {
func (a *App) dispatchEventToWindows(event *WailsEvent) {
for _, window := range a.windows {
window.dispatchCustomEvent(event)
window.dispatchWailsEvent(event)
}
}

View File

@ -18,13 +18,13 @@ var windowEvents = make(chan *WindowEvent)
var menuItemClicked = make(chan uint)
type CustomEvent struct {
type WailsEvent struct {
Name string `json:"name"`
Data any `json:"data"`
Sender string `json:"sender"`
}
func (e CustomEvent) ToJSON() string {
func (e WailsEvent) ToJSON() string {
marshal, err := json.Marshal(&e)
if err != nil {
// TODO: Fatal error? log?
@ -38,9 +38,9 @@ func (e CustomEvent) ToJSON() string {
// how the total number of events it is interested in. A value of zero
// means it does not expire (default).
type eventListener struct {
callback func(*CustomEvent) // Function to call with emitted event data
counter int // The number of times this callback may be called. -1 = infinite
delete bool // Flag to indicate that this listener should be deleted
callback func(*WailsEvent) // Function to call with emitted event data
counter int // The number of times this callback may be called. -1 = infinite
delete bool // Flag to indicate that this listener should be deleted
}
// EventProcessor handles custom events
@ -48,10 +48,10 @@ type EventProcessor struct {
// Go event listeners
listeners map[string][]*eventListener
notifyLock sync.RWMutex
dispatchEventToWindows func(*CustomEvent)
dispatchEventToWindows func(*WailsEvent)
}
func NewCustomEventProcessor(dispatchEventToWindows func(*CustomEvent)) *EventProcessor {
func NewWailsEventProcessor(dispatchEventToWindows func(*WailsEvent)) *EventProcessor {
return &EventProcessor{
listeners: make(map[string][]*eventListener),
dispatchEventToWindows: dispatchEventToWindows,
@ -59,22 +59,22 @@ func NewCustomEventProcessor(dispatchEventToWindows func(*CustomEvent)) *EventPr
}
// On is the equivalent of Javascript's `addEventListener`
func (e *EventProcessor) On(eventName string, callback func(event *CustomEvent)) func() {
func (e *EventProcessor) On(eventName string, callback func(event *WailsEvent)) func() {
return e.registerListener(eventName, callback, -1)
}
// OnMultiple is the same as `On` but will unregister after `count` events
func (e *EventProcessor) OnMultiple(eventName string, callback func(event *CustomEvent), counter int) func() {
func (e *EventProcessor) OnMultiple(eventName string, callback func(event *WailsEvent), counter int) func() {
return e.registerListener(eventName, callback, counter)
}
// Once is the same as `On` but will unregister after the first event
func (e *EventProcessor) Once(eventName string, callback func(event *CustomEvent)) func() {
func (e *EventProcessor) Once(eventName string, callback func(event *WailsEvent)) func() {
return e.registerListener(eventName, callback, 1)
}
// Emit sends an event to all listeners
func (e *EventProcessor) Emit(thisEvent *CustomEvent) {
func (e *EventProcessor) Emit(thisEvent *WailsEvent) {
if thisEvent == nil {
return
}
@ -93,7 +93,7 @@ func (e *EventProcessor) OffAll() {
}
// registerListener provides a means of subscribing to events of type "eventName"
func (e *EventProcessor) registerListener(eventName string, callback func(*CustomEvent), counter int) func() {
func (e *EventProcessor) registerListener(eventName string, callback func(*WailsEvent), counter int) func() {
// Create new eventListener
thisListener := &eventListener{
callback: callback,
@ -125,7 +125,7 @@ func (e *EventProcessor) unRegisterListener(eventName string) {
}
// dispatchEventToListeners calls all registered listeners event name
func (e *EventProcessor) dispatchEventToListeners(event *CustomEvent) {
func (e *EventProcessor) dispatchEventToListeners(event *WailsEvent) {
e.notifyLock.Lock()
defer e.notifyLock.Unlock()

View File

@ -10,33 +10,33 @@ import (
)
type mockNotifier struct {
Events []*application.CustomEvent
Events []*application.WailsEvent
}
func (m *mockNotifier) dispatchEventToWindows(event *application.CustomEvent) {
func (m *mockNotifier) dispatchEventToWindows(event *application.WailsEvent) {
m.Events = append(m.Events, event)
}
func (m *mockNotifier) Reset() {
m.Events = []*application.CustomEvent{}
m.Events = []*application.WailsEvent{}
}
func Test_EventsOn(t *testing.T) {
i := is.New(t)
notifier := &mockNotifier{}
eventProcessor := application.NewCustomEventProcessor(notifier.dispatchEventToWindows)
eventProcessor := application.NewWailsEventProcessor(notifier.dispatchEventToWindows)
// Test On
eventName := "test"
counter := 0
var wg sync.WaitGroup
wg.Add(1)
unregisterFn := eventProcessor.On(eventName, func(event *application.CustomEvent) {
unregisterFn := eventProcessor.On(eventName, func(event *application.WailsEvent) {
// This is called in a goroutine
counter++
wg.Done()
})
eventProcessor.Emit(&application.CustomEvent{
eventProcessor.Emit(&application.WailsEvent{
Name: "test",
Data: "test payload",
})
@ -47,7 +47,7 @@ func Test_EventsOn(t *testing.T) {
notifier.Reset()
unregisterFn()
counter = 0
eventProcessor.Emit(&application.CustomEvent{
eventProcessor.Emit(&application.WailsEvent{
Name: "test",
Data: "test payload",
})
@ -58,23 +58,23 @@ func Test_EventsOn(t *testing.T) {
func Test_EventsOnce(t *testing.T) {
i := is.New(t)
notifier := &mockNotifier{}
eventProcessor := application.NewCustomEventProcessor(notifier.dispatchEventToWindows)
eventProcessor := application.NewWailsEventProcessor(notifier.dispatchEventToWindows)
// Test On
eventName := "test"
counter := 0
var wg sync.WaitGroup
wg.Add(1)
unregisterFn := eventProcessor.Once(eventName, func(event *application.CustomEvent) {
unregisterFn := eventProcessor.Once(eventName, func(event *application.WailsEvent) {
// This is called in a goroutine
counter++
wg.Done()
})
eventProcessor.Emit(&application.CustomEvent{
eventProcessor.Emit(&application.WailsEvent{
Name: "test",
Data: "test payload",
})
eventProcessor.Emit(&application.CustomEvent{
eventProcessor.Emit(&application.WailsEvent{
Name: "test",
Data: "test payload",
})
@ -85,7 +85,7 @@ func Test_EventsOnce(t *testing.T) {
notifier.Reset()
unregisterFn()
counter = 0
eventProcessor.Emit(&application.CustomEvent{
eventProcessor.Emit(&application.WailsEvent{
Name: "test",
Data: "test payload",
})
@ -95,27 +95,27 @@ func Test_EventsOnce(t *testing.T) {
func Test_EventsOnMultiple(t *testing.T) {
i := is.New(t)
notifier := &mockNotifier{}
eventProcessor := application.NewCustomEventProcessor(notifier.dispatchEventToWindows)
eventProcessor := application.NewWailsEventProcessor(notifier.dispatchEventToWindows)
// Test On
eventName := "test"
counter := 0
var wg sync.WaitGroup
wg.Add(2)
unregisterFn := eventProcessor.OnMultiple(eventName, func(event *application.CustomEvent) {
unregisterFn := eventProcessor.OnMultiple(eventName, func(event *application.WailsEvent) {
// This is called in a goroutine
counter++
wg.Done()
}, 2)
eventProcessor.Emit(&application.CustomEvent{
eventProcessor.Emit(&application.WailsEvent{
Name: "test",
Data: "test payload",
})
eventProcessor.Emit(&application.CustomEvent{
eventProcessor.Emit(&application.WailsEvent{
Name: "test",
Data: "test payload",
})
eventProcessor.Emit(&application.CustomEvent{
eventProcessor.Emit(&application.WailsEvent{
Name: "test",
Data: "test payload",
})
@ -126,7 +126,7 @@ func Test_EventsOnMultiple(t *testing.T) {
notifier.Reset()
unregisterFn()
counter = 0
eventProcessor.Emit(&application.CustomEvent{
eventProcessor.Emit(&application.WailsEvent{
Name: "test",
Data: "test payload",
})

View File

@ -8,7 +8,7 @@ func (m *MessageProcessor) processEventsMethod(method string, rw http.ResponseWr
switch method {
case "Emit":
var event CustomEvent
var event WailsEvent
err := params.ToStruct(&event)
if err != nil {
m.httpError(rw, "Error parsing event: %s", err)

View File

@ -602,8 +602,8 @@ func (w *WebviewWindow) SetFrameless(frameless bool) *WebviewWindow {
return w
}
func (w *WebviewWindow) dispatchCustomEvent(event *CustomEvent) {
msg := fmt.Sprintf("_wails.dispatchCustomEvent(%s);", event.ToJSON())
func (w *WebviewWindow) dispatchWailsEvent(event *WailsEvent) {
msg := fmt.Sprintf("_wails.dispatchWailsEvent(%s);", event.ToJSON())
w.ExecJS(msg)
}