mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-03 01:43:15 +08:00
Add single listener deregistration (#1969)
* Add single listener deregistration * Return function to stop listening, updates types * Add missing returns, improve documentation * Duplicate interface in go * Define eventName * Use lo instead for filtering * Move logger to Interface. Add sample test. * Add vite test for events * Add js test workflow * Add corresponding go method to remove all events * Update documentation Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
This commit is contained in:
parent
4bff4af2b0
commit
9f751d66e0
32
.github/workflows/test_js.yml
vendored
Normal file
32
.github/workflows/test_js.yml
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
name: Test JS
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ release/*, master ]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: Run JS Tests
|
||||||
|
if: github.repository == 'wailsapp/wails'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [16.x]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm install
|
||||||
|
working-directory: v2/internal/frontend/runtime
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: npm test
|
||||||
|
working-directory: v2/internal/frontend/runtime
|
@ -1,10 +1,11 @@
|
|||||||
package frontend
|
package frontend
|
||||||
|
|
||||||
type Events interface {
|
type Events interface {
|
||||||
On(eventName string, callback func(...interface{}))
|
On(eventName string, callback func(...interface{})) func()
|
||||||
OnMultiple(eventName string, callback func(...interface{}), counter int)
|
OnMultiple(eventName string, callback func(...interface{}), counter int) func()
|
||||||
Once(eventName string, callback func(...interface{}))
|
Once(eventName string, callback func(...interface{})) func()
|
||||||
Emit(eventName string, data ...interface{})
|
Emit(eventName string, data ...interface{})
|
||||||
Off(eventName string)
|
Off(eventName string)
|
||||||
|
OffAll()
|
||||||
Notify(sender Frontend, name string, data ...interface{})
|
Notify(sender Frontend, name string, data ...interface{})
|
||||||
}
|
}
|
||||||
|
@ -19,24 +19,26 @@ The electron alternative for Go
|
|||||||
class Listener {
|
class Listener {
|
||||||
/**
|
/**
|
||||||
* Creates an instance of Listener.
|
* Creates an instance of Listener.
|
||||||
|
* @param {string} eventName
|
||||||
* @param {function} callback
|
* @param {function} callback
|
||||||
* @param {number} maxCallbacks
|
* @param {number} maxCallbacks
|
||||||
* @memberof Listener
|
* @memberof Listener
|
||||||
*/
|
*/
|
||||||
constructor(callback, maxCallbacks) {
|
constructor(eventName, callback, maxCallbacks) {
|
||||||
|
this.eventName = eventName;
|
||||||
// Default of -1 means infinite
|
// Default of -1 means infinite
|
||||||
maxCallbacks = maxCallbacks || -1;
|
this.maxCallbacks = maxCallbacks || -1;
|
||||||
// Callback invokes the callback with the given data
|
// Callback invokes the callback with the given data
|
||||||
// Returns true if this listener should be destroyed
|
// Returns true if this listener should be destroyed
|
||||||
this.Callback = (data) => {
|
this.Callback = (data) => {
|
||||||
callback.apply(null, data);
|
callback.apply(null, data);
|
||||||
// If maxCallbacks is infinite, return false (do not destroy)
|
// If maxCallbacks is infinite, return false (do not destroy)
|
||||||
if (maxCallbacks === -1) {
|
if (this.maxCallbacks === -1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Decrement maxCallbacks. Return true if now 0, otherwise false
|
// Decrement maxCallbacks. Return true if now 0, otherwise false
|
||||||
maxCallbacks -= 1;
|
this.maxCallbacks -= 1;
|
||||||
return maxCallbacks === 0;
|
return this.maxCallbacks === 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,11 +52,13 @@ export const eventListeners = {};
|
|||||||
* @param {string} eventName
|
* @param {string} eventName
|
||||||
* @param {function} callback
|
* @param {function} callback
|
||||||
* @param {number} maxCallbacks
|
* @param {number} maxCallbacks
|
||||||
|
* @returns {function} A function to cancel the listener
|
||||||
*/
|
*/
|
||||||
export function EventsOnMultiple(eventName, callback, maxCallbacks) {
|
export function EventsOnMultiple(eventName, callback, maxCallbacks) {
|
||||||
eventListeners[eventName] = eventListeners[eventName] || [];
|
eventListeners[eventName] = eventListeners[eventName] || [];
|
||||||
const thisListener = new Listener(callback, maxCallbacks);
|
const thisListener = new Listener(eventName, callback, maxCallbacks);
|
||||||
eventListeners[eventName].push(thisListener);
|
eventListeners[eventName].push(thisListener);
|
||||||
|
return () => listenerOff(thisListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,9 +67,10 @@ export function EventsOnMultiple(eventName, callback, maxCallbacks) {
|
|||||||
* @export
|
* @export
|
||||||
* @param {string} eventName
|
* @param {string} eventName
|
||||||
* @param {function} callback
|
* @param {function} callback
|
||||||
|
* @returns {function} A function to cancel the listener
|
||||||
*/
|
*/
|
||||||
export function EventsOn(eventName, callback) {
|
export function EventsOn(eventName, callback) {
|
||||||
EventsOnMultiple(eventName, callback, -1);
|
return EventsOnMultiple(eventName, callback, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -74,9 +79,10 @@ export function EventsOn(eventName, callback) {
|
|||||||
* @export
|
* @export
|
||||||
* @param {string} eventName
|
* @param {string} eventName
|
||||||
* @param {function} callback
|
* @param {function} callback
|
||||||
|
* @returns {function} A function to cancel the listener
|
||||||
*/
|
*/
|
||||||
export function EventsOnce(eventName, callback) {
|
export function EventsOnce(eventName, callback) {
|
||||||
EventsOnMultiple(eventName, callback, 1);
|
return EventsOnMultiple(eventName, callback, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function notifyListeners(eventData) {
|
function notifyListeners(eventData) {
|
||||||
@ -107,9 +113,13 @@ function notifyListeners(eventData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update callbacks with new list of listeners
|
// Update callbacks with new list of listeners
|
||||||
|
if (newEventListenerList.length === 0) {
|
||||||
|
removeListener(eventName);
|
||||||
|
} else {
|
||||||
eventListeners[eventName] = newEventListenerList;
|
eventListeners[eventName] = newEventListenerList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify informs frontend listeners that an event was emitted with the given data
|
* Notify informs frontend listeners that an event was emitted with the given data
|
||||||
@ -174,3 +184,29 @@ export function EventsOff(eventName, ...additionalEventNames) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
132
v2/internal/frontend/runtime/desktop/events.test.js
Normal file
132
v2/internal/frontend/runtime/desktop/events.test.js
Normal file
@ -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']]);
|
||||||
|
})
|
||||||
|
})
|
@ -1,11 +1,16 @@
|
|||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/wailsapp/wails/v2/internal/frontend"
|
|
||||||
"github.com/wailsapp/wails/v2/internal/logger"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/samber/lo"
|
||||||
|
"github.com/wailsapp/wails/v2/internal/frontend"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Logger interface {
|
||||||
|
Trace(format string, v ...interface{})
|
||||||
|
}
|
||||||
|
|
||||||
// eventListener holds a callback function which is invoked when
|
// eventListener holds a callback function which is invoked when
|
||||||
// the event listened for is emitted. It has a counter which indicates
|
// the event listened for is emitted. It has a counter which indicates
|
||||||
// how the total number of events it is interested in. A value of zero
|
// how the total number of events it is interested in. A value of zero
|
||||||
@ -18,7 +23,7 @@ type eventListener struct {
|
|||||||
|
|
||||||
// Events handles eventing
|
// Events handles eventing
|
||||||
type Events struct {
|
type Events struct {
|
||||||
log *logger.Logger
|
log Logger
|
||||||
frontend []frontend.Frontend
|
frontend []frontend.Frontend
|
||||||
|
|
||||||
// Go event listeners
|
// Go event listeners
|
||||||
@ -36,16 +41,16 @@ func (e *Events) Notify(sender frontend.Frontend, name string, data ...interface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Events) On(eventName string, callback func(...interface{})) {
|
func (e *Events) On(eventName string, callback func(...interface{})) func() {
|
||||||
e.registerListener(eventName, callback, -1)
|
return e.registerListener(eventName, callback, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Events) OnMultiple(eventName string, callback func(...interface{}), counter int) {
|
func (e *Events) OnMultiple(eventName string, callback func(...interface{}), counter int) func() {
|
||||||
e.registerListener(eventName, callback, counter)
|
return e.registerListener(eventName, callback, counter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Events) Once(eventName string, callback func(...interface{})) {
|
func (e *Events) Once(eventName string, callback func(...interface{})) func() {
|
||||||
e.registerListener(eventName, callback, 1)
|
return e.registerListener(eventName, callback, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Events) Emit(eventName string, data ...interface{}) {
|
func (e *Events) Emit(eventName string, data ...interface{}) {
|
||||||
@ -59,8 +64,15 @@ func (e *Events) Off(eventName string) {
|
|||||||
e.unRegisterListener(eventName)
|
e.unRegisterListener(eventName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Events) OffAll() {
|
||||||
|
e.notifyLock.Lock()
|
||||||
|
for eventName := range e.listeners {
|
||||||
|
delete(e.listeners, eventName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewEvents creates a new log subsystem
|
// NewEvents creates a new log subsystem
|
||||||
func NewEvents(log *logger.Logger) *Events {
|
func NewEvents(log Logger) *Events {
|
||||||
result := &Events{
|
result := &Events{
|
||||||
log: log,
|
log: log,
|
||||||
listeners: make(map[string][]*eventListener),
|
listeners: make(map[string][]*eventListener),
|
||||||
@ -69,7 +81,7 @@ func NewEvents(log *logger.Logger) *Events {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// registerListener provides a means of subscribing to events of type "eventName"
|
// registerListener provides a means of subscribing to events of type "eventName"
|
||||||
func (e *Events) registerListener(eventName string, callback func(...interface{}), counter int) {
|
func (e *Events) registerListener(eventName string, callback func(...interface{}), counter int) func() {
|
||||||
// Create new eventListener
|
// Create new eventListener
|
||||||
thisListener := &eventListener{
|
thisListener := &eventListener{
|
||||||
callback: callback,
|
callback: callback,
|
||||||
@ -80,6 +92,17 @@ func (e *Events) registerListener(eventName string, callback func(...interface{}
|
|||||||
// Append the new listener to the listeners slice
|
// Append the new listener to the listeners slice
|
||||||
e.listeners[eventName] = append(e.listeners[eventName], thisListener)
|
e.listeners[eventName] = append(e.listeners[eventName], thisListener)
|
||||||
e.notifyLock.Unlock()
|
e.notifyLock.Unlock()
|
||||||
|
return func() {
|
||||||
|
e.notifyLock.Lock()
|
||||||
|
defer e.notifyLock.Unlock()
|
||||||
|
|
||||||
|
if _, ok := e.listeners[eventName]; !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.listeners[eventName] = lo.Filter(e.listeners[eventName], func(l *eventListener, i int) bool {
|
||||||
|
return l != thisListener
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unRegisterListener provides a means of unsubscribing to events of type "eventName"
|
// unRegisterListener provides a means of unsubscribing to events of type "eventName"
|
||||||
|
38
v2/internal/frontend/runtime/events_test.go
Normal file
38
v2/internal/frontend/runtime/events_test.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package runtime_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
import "github.com/matryer/is"
|
||||||
|
|
||||||
|
type mockLogger struct {
|
||||||
|
Log string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *mockLogger) Trace(format string, args ...interface{}) {
|
||||||
|
t.Log = fmt.Sprintf(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_EventsOn(t *testing.T) {
|
||||||
|
i := is.New(t)
|
||||||
|
l := &mockLogger{}
|
||||||
|
manager := runtime.NewEvents(l)
|
||||||
|
|
||||||
|
// Test On
|
||||||
|
eventName := "test"
|
||||||
|
counter := 0
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
|
manager.On(eventName, func(args ...interface{}) {
|
||||||
|
// This is called in a goroutine
|
||||||
|
counter++
|
||||||
|
wg.Done()
|
||||||
|
})
|
||||||
|
manager.Emit(eventName, "test payload")
|
||||||
|
wg.Wait()
|
||||||
|
i.Equal(1, counter)
|
||||||
|
|
||||||
|
}
|
1808
v2/internal/frontend/runtime/package-lock.json
generated
1808
v2/internal/frontend/runtime/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -9,13 +9,15 @@
|
|||||||
"build:ipc-dev": "cd dev && npm install && npm run build",
|
"build:ipc-dev": "cd dev && npm install && npm run build",
|
||||||
"build:runtime-desktop-prod": "npx esbuild desktop/main.js --bundle --minify --outfile=runtime_prod_desktop.js --define:ENV=1",
|
"build:runtime-desktop-prod": "npx esbuild desktop/main.js --bundle --minify --outfile=runtime_prod_desktop.js --define:ENV=1",
|
||||||
"build:runtime-desktop-dev": "npx esbuild desktop/main.js --bundle --sourcemap=inline --outfile=runtime_dev_desktop.js --define:ENV=0",
|
"build:runtime-desktop-dev": "npx esbuild desktop/main.js --bundle --sourcemap=inline --outfile=runtime_dev_desktop.js --define:ENV=0",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "vitest"
|
||||||
},
|
},
|
||||||
"author": "Lea Anthony <lea.anthony@gmail.com>",
|
"author": "Lea Anthony <lea.anthony@gmail.com>",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"esbuild": "^0.15.6",
|
"esbuild": "^0.15.6",
|
||||||
|
"happy-dom": "^7.6.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"svelte": "^3.49.0"
|
"svelte": "^3.49.0",
|
||||||
|
"vitest": "^0.24.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
7
v2/internal/frontend/runtime/vite.config.ts
Normal file
7
v2/internal/frontend/runtime/vite.config.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { defineConfig } from 'vitest/config'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
test: {
|
||||||
|
environment: 'happy-dom',
|
||||||
|
},
|
||||||
|
})
|
@ -38,20 +38,24 @@ export interface EnvironmentInfo {
|
|||||||
export function EventsEmit(eventName: string, ...data: any): void;
|
export function EventsEmit(eventName: string, ...data: any): void;
|
||||||
|
|
||||||
// [EventsOn](https://wails.io/docs/reference/runtime/events#eventson) sets up a listener for the given event name.
|
// [EventsOn](https://wails.io/docs/reference/runtime/events#eventson) sets up a listener for the given event name.
|
||||||
export function EventsOn(eventName: string, callback: (...data: any) => void): void;
|
export function EventsOn(eventName: string, callback: (...data: any) => void): () => void;
|
||||||
|
|
||||||
// [EventsOnMultiple](https://wails.io/docs/reference/runtime/events#eventsonmultiple)
|
// [EventsOnMultiple](https://wails.io/docs/reference/runtime/events#eventsonmultiple)
|
||||||
// sets up a listener for the given event name, but will only trigger a given number times.
|
// sets up a listener for the given event name, but will only trigger a given number times.
|
||||||
export function EventsOnMultiple(eventName: string, callback: (...data: any) => void, maxCallbacks: number): void;
|
export function EventsOnMultiple(eventName: string, callback: (...data: any) => void, maxCallbacks: number): () => void;
|
||||||
|
|
||||||
// [EventsOnce](https://wails.io/docs/reference/runtime/events#eventsonce)
|
// [EventsOnce](https://wails.io/docs/reference/runtime/events#eventsonce)
|
||||||
// sets up a listener for the given event name, but will only trigger once.
|
// sets up a listener for the given event name, but will only trigger once.
|
||||||
export function EventsOnce(eventName: string, callback: (...data: any) => void): void;
|
export function EventsOnce(eventName: string, callback: (...data: any) => void): () => void;
|
||||||
|
|
||||||
// [EventsOff](https://wails.io/docs/reference/runtime/events#eventsff)
|
// [EventsOff](https://wails.io/docs/reference/runtime/events#eventsoff)
|
||||||
// unregisters the listener for the given event name.
|
// unregisters the listener for the given event name.
|
||||||
export function EventsOff(eventName: string, ...additionalEventNames: string[]): void;
|
export function EventsOff(eventName: string, ...additionalEventNames: string[]): void;
|
||||||
|
|
||||||
|
// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall)
|
||||||
|
// unregisters all listeners.
|
||||||
|
export function EventsOffAll(): void;
|
||||||
|
|
||||||
// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint)
|
// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint)
|
||||||
// logs the given message as a raw message
|
// logs the given message as a raw message
|
||||||
export function LogPrint(message: string): void;
|
export function LogPrint(message: string): void;
|
||||||
|
@ -4,10 +4,10 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EventsOn registers a listener for the given event name
|
// EventsOn registers a listener for the given event name. It returns a function to cancel the listener
|
||||||
func EventsOn(ctx context.Context, eventName string, callback func(optionalData ...interface{})) {
|
func EventsOn(ctx context.Context, eventName string, callback func(optionalData ...interface{})) func() {
|
||||||
events := getEvents(ctx)
|
events := getEvents(ctx)
|
||||||
events.On(eventName, callback)
|
return events.On(eventName, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EventsOff unregisters a listener for the given event name, optionally multiple listeneres can be unregistered via `additionalEventNames`
|
// EventsOff unregisters a listener for the given event name, optionally multiple listeneres can be unregistered via `additionalEventNames`
|
||||||
@ -22,17 +22,24 @@ func EventsOff(ctx context.Context, eventName string, additionalEventNames ...st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EventsOnce registers a listener for the given event name. After the first callback, the
|
// EventsOff unregisters a listener for the given event name, optionally multiple listeneres can be unregistered via `additionalEventNames`
|
||||||
// listener is deleted.
|
func EventsOffAll(ctx context.Context) {
|
||||||
func EventsOnce(ctx context.Context, eventName string, callback func(optionalData ...interface{})) {
|
|
||||||
events := getEvents(ctx)
|
events := getEvents(ctx)
|
||||||
events.Once(eventName, callback)
|
events.OffAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
// EventsOnMultiple registers a listener for the given event name, that may be called a maximum of 'counter' times
|
// EventsOnce registers a listener for the given event name. After the first callback, the
|
||||||
func EventsOnMultiple(ctx context.Context, eventName string, callback func(optionalData ...interface{}), counter int) {
|
// listener is deleted. It returns a function to cancel the listener
|
||||||
|
func EventsOnce(ctx context.Context, eventName string, callback func(optionalData ...interface{})) func() {
|
||||||
events := getEvents(ctx)
|
events := getEvents(ctx)
|
||||||
events.OnMultiple(eventName, callback, counter)
|
return events.Once(eventName, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventsOnMultiple registers a listener for the given event name, that may be called a maximum of 'counter' times. It returns a function
|
||||||
|
// to cancel the listener
|
||||||
|
func EventsOnMultiple(ctx context.Context, eventName string, callback func(optionalData ...interface{}), counter int) func() {
|
||||||
|
events := getEvents(ctx)
|
||||||
|
return events.OnMultiple(eventName, callback, counter)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EventsEmit pass through
|
// EventsEmit pass through
|
||||||
|
@ -10,10 +10,11 @@ Optionally, data may be passed with the events. Listeners will receive the data
|
|||||||
### EventsOn
|
### EventsOn
|
||||||
|
|
||||||
This method sets up a listener for the given event name. When an event of type `eventName` is [emitted](#EventsEmit),
|
This method sets up a listener for the given event name. When an event of type `eventName` is [emitted](#EventsEmit),
|
||||||
the callback is triggered. Any additional data sent with the emitted event will be passed to the callback.
|
the callback is triggered. Any additional data sent with the emitted event will be passed to the callback. It returns
|
||||||
|
a function to cancel the listener.
|
||||||
|
|
||||||
Go: `EventsOn(ctx context.Context, eventName string, callback func(optionalData ...interface{}))`<br/>
|
Go: `EventsOn(ctx context.Context, eventName string, callback func(optionalData ...interface{})) func()`<br/>
|
||||||
JS: `EventsOn(eventName string, callback function(optionalData?: any))`
|
JS: `EventsOn(eventName string, callback function(optionalData?: any)): () => void`
|
||||||
|
|
||||||
### EventsOff
|
### EventsOff
|
||||||
|
|
||||||
@ -24,17 +25,19 @@ JS: `EventsOff(eventName string, ...additionalEventNames)`
|
|||||||
|
|
||||||
### EventsOnce
|
### EventsOnce
|
||||||
|
|
||||||
This method sets up a listener for the given event name, but will only trigger once.
|
This method sets up a listener for the given event name, but will only trigger once. It returns a function to cancel
|
||||||
|
the listener.
|
||||||
|
|
||||||
Go: `EventsOnce(ctx context.Context, eventName string, callback func(optionalData ...interface{}))`<br/>
|
Go: `EventsOnce(ctx context.Context, eventName string, callback func(optionalData ...interface{})) func()`<br/>
|
||||||
JS: `EventsOnce(eventName string, callback function(optionalData?: any))`
|
JS: `EventsOnce(eventName string, callback function(optionalData?: any)): () => void`
|
||||||
|
|
||||||
### EventsOnMultiple
|
### EventsOnMultiple
|
||||||
|
|
||||||
This method sets up a listener for the given event name, but will only trigger a maximum of `counter` times.
|
This method sets up a listener for the given event name, but will only trigger a maximum of `counter` times. It returns
|
||||||
|
a function to cancel the listener.
|
||||||
|
|
||||||
Go: `EventsOnMultiple(ctx context.Context, eventName string, callback func(optionalData ...interface{}), counter int)`<br/>
|
Go: `EventsOnMultiple(ctx context.Context, eventName string, callback func(optionalData ...interface{}), counter int) func()`<br/>
|
||||||
JS: `EventsOnMultiple(eventName string, callback function(optionalData?: any), counter int)`
|
JS: `EventsOnMultiple(eventName string, callback function(optionalData?: any), counter int): () => void`
|
||||||
|
|
||||||
### EventsEmit
|
### EventsEmit
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user