mirror of
https://github.com/wailsapp/wails.git
synced 2026-03-14 14:45:49 +01:00
Support Emit & Once. Improved On.
This commit is contained in:
parent
78f99c2697
commit
aeb7d857ee
18 changed files with 329 additions and 41 deletions
|
|
@ -16,8 +16,8 @@ func (e *Events) WailsInit(runtime *wails.Runtime) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Subscribe will subscribe
|
||||
func (e *Events) Subscribe(eventName string) {
|
||||
// On will subscribe to the given event name
|
||||
func (e *Events) On(eventName string) {
|
||||
e.runtime.Events.On(eventName, func(args ...interface{}) {
|
||||
type callbackData struct {
|
||||
Name string
|
||||
|
|
@ -27,3 +27,20 @@ func (e *Events) Subscribe(eventName string) {
|
|||
e.runtime.Events.Emit("event fired by go subscriber", result)
|
||||
})
|
||||
}
|
||||
|
||||
// Once will subscribe to the given event name
|
||||
func (e *Events) Once(eventName string) {
|
||||
e.runtime.Events.Once(eventName, func(args ...interface{}) {
|
||||
type callbackData struct {
|
||||
Name string
|
||||
Data []interface{}
|
||||
}
|
||||
result := callbackData{Name: eventName, Data: args}
|
||||
e.runtime.Events.Emit("once event fired by go subscriber", result)
|
||||
})
|
||||
}
|
||||
|
||||
// Emit will emit
|
||||
func (e *Events) Emit(eventName string, data []interface{}) {
|
||||
e.runtime.Events.Emit(eventName, data...)
|
||||
}
|
||||
|
|
|
|||
12
v2/test/kitchensink/frontend/package-lock.json
generated
12
v2/test/kitchensink/frontend/package-lock.json
generated
|
|
@ -135,9 +135,9 @@
|
|||
}
|
||||
},
|
||||
"@wails/runtime": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@wails/runtime/-/runtime-1.0.4.tgz",
|
||||
"integrity": "sha512-x7marEg5nU//qUVRJAF9Hp0oyW75bevHv6jWAzoU977KQPoWtuCkxWm8B5X1u40rq1O0DHWy58R4CujwpewUTw==",
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@wails/runtime/-/runtime-1.0.5.tgz",
|
||||
"integrity": "sha512-B7nX207vC4ykXCdNEX7e54U4DhBPoPMuoVs3hhJuhRGFXGeUCaItWy0FjUW2YO2NGaR+NjluX19jAsfnHjTk4A==",
|
||||
"dev": true
|
||||
},
|
||||
"alphanum-sort": {
|
||||
|
|
@ -2976,9 +2976,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"rollup": {
|
||||
"version": "2.29.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.29.0.tgz",
|
||||
"integrity": "sha512-gtU0sjxMpsVlpuAf4QXienPmUAhd6Kc7owQ4f5lypoxBW18fw2UNYZ4NssLGsri6WhUZkE/Ts3EMRebN+gNLiQ==",
|
||||
"version": "2.32.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.32.0.tgz",
|
||||
"integrity": "sha512-0FIG1jY88uhCP2yP4CfvtKEqPDRmsUwfY1kEOOM+DH/KOGATgaIFd/is1+fQOxsvh62ELzcFfKonwKWnHhrqmw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fsevents": "~2.1.2"
|
||||
|
|
|
|||
|
|
@ -11,12 +11,12 @@
|
|||
"@rollup/plugin-commonjs": "^11.0.0",
|
||||
"@rollup/plugin-node-resolve": "^7.0.0",
|
||||
"@rollup/plugin-url": "^5.0.1",
|
||||
"@wails/runtime": "^1.0.4",
|
||||
"@wails/runtime": "^1.0.5",
|
||||
"focus-visible": "^5.2.0",
|
||||
"halfmoon": "^1.1.1",
|
||||
"postcss": "^8.1.1",
|
||||
"postcss-import": "^12.0.1",
|
||||
"rollup": "^2.29.0",
|
||||
"rollup": "^2.32.0",
|
||||
"rollup-plugin-livereload": "^1.0.0",
|
||||
"rollup-plugin-postcss": "^3.1.8",
|
||||
"rollup-plugin-string": "^3.0.0",
|
||||
|
|
|
|||
|
|
@ -56,10 +56,10 @@
|
|||
|
||||
.inner-content {
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
bottom: 40px;
|
||||
top: 20px;
|
||||
bottom: 20px;
|
||||
width: 99%;
|
||||
overflow-y: auto;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
|
|
@ -106,14 +106,19 @@
|
|||
}
|
||||
|
||||
.list {
|
||||
margin-top: 2rem;
|
||||
margin-left: 2rem;
|
||||
margin-top: 1.5rem;
|
||||
margin-left: 1.5rem;
|
||||
}
|
||||
|
||||
.list li {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
position: fixed;
|
||||
top: 50px;
|
||||
}
|
||||
|
||||
/* * {
|
||||
font-family: 'Roboto';
|
||||
} */
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
</script>
|
||||
|
||||
<h4 class="title">{$selectedPage || "" }</h4>
|
||||
<div class="mainpage">
|
||||
{#if $selectedPage == undefined} <TitlePage></TitlePage> {/if}
|
||||
{#if $selectedPage == "Logging"} <Logging></Logging> {/if}
|
||||
|
|
@ -14,10 +15,19 @@
|
|||
</div>
|
||||
|
||||
<style>
|
||||
.title {
|
||||
position: fixed;
|
||||
top: 50px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
.mainpage {
|
||||
margin-left: 45px;
|
||||
margin-right: 45px;
|
||||
position: absolute;
|
||||
top: 70px;
|
||||
margin-left: 20px;
|
||||
padding-right: 10px;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
overflow-y: auto;
|
||||
height: calc(100% - 100px);
|
||||
width: calc(100% - 20px);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -29,7 +29,7 @@
|
|||
export let id = "toggle-" + Date.now().toString() + Math.random().toString();
|
||||
|
||||
// Handle hiding example
|
||||
let showRun = true;
|
||||
let showRun = false;
|
||||
|
||||
function toggleRun() {
|
||||
showRun = !showRun;
|
||||
|
|
@ -150,7 +150,7 @@
|
|||
}
|
||||
|
||||
.codeblock {
|
||||
background-color: #3F3F4B;
|
||||
/* background-color: #3F3F4B; */
|
||||
border-radius: 5px;
|
||||
border: 1px solid #555;
|
||||
padding: 5px;
|
||||
|
|
@ -159,7 +159,7 @@
|
|||
}
|
||||
|
||||
.codeblock-light {
|
||||
background-color: #e5e5e5;
|
||||
/* background-color: #e5e5e5; */
|
||||
border-radius: 5px;
|
||||
border: 1px solid #ccc;
|
||||
padding: 5px;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
<script>
|
||||
import { Events } from '@wails/runtime';
|
||||
import CodeBlock from '../../../components/CodeBlock.svelte';
|
||||
import CodeSnippet from '../../../components/CodeSnippet.svelte';
|
||||
import FakeTerm from '../../../components/FakeTerm.svelte';
|
||||
import description from './description.txt';
|
||||
import { UniqueID } from '../../../utils/utils';
|
||||
import jsCode from './code.jsx';
|
||||
import goCode from './code.go';
|
||||
import { loggingOutput } from '../On/store';
|
||||
|
||||
|
||||
let isJs = false;
|
||||
$: lang = isJs ? 'Javascript' : 'Go';
|
||||
|
||||
let id = UniqueID('events');
|
||||
|
||||
let eventName = "";
|
||||
|
||||
let dataText = "";
|
||||
let placeholder = `123, "hello", true`;
|
||||
let formattedData = "";
|
||||
|
||||
function emitEvent() {
|
||||
let data = JSON.parse("["+formattedData+"]");
|
||||
if( isJs ) {
|
||||
Events.Emit(eventName.trim(), ...data);
|
||||
} else {
|
||||
backend.main.Events.Emit(eventName, data);
|
||||
}
|
||||
}
|
||||
|
||||
let dataValid = true;
|
||||
|
||||
$: {
|
||||
console.log("REactive function triggered!");
|
||||
|
||||
if ( dataText.length === 0 ) {
|
||||
dataValid = true;
|
||||
formattedData = "";
|
||||
} else {
|
||||
try {
|
||||
formattedData = JSON.stringify(JSON.parse("["+dataText+"]")).slice(1,-1);
|
||||
dataValid = true;
|
||||
} catch(e) {
|
||||
formattedData = "";
|
||||
dataValid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$: emitCodeJs = `import { Events } from '@wails/runtime';\n\nEvents.Emit("` + eventName + `"` + (formattedData.length > 0 ? ',' + formattedData : '') + `);`;
|
||||
$: emitCodeGo = `Events.Emit("` + eventName + `"` + (formattedData.length > 0 ? ',' + formattedData : '') + `);`;
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<CodeBlock bind:isJs={isJs} {jsCode} {goCode} {id} title="Events.Emit(eventName [, data])" {description}>
|
||||
<div class="logging-form">
|
||||
<form data-wails-no-drag class="mw-full">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="{id}-eventName" class="required">Event Name to Emit</label>
|
||||
<input type="text" class="form-control" id="{id}-eventName" placeholder="MyEventName" bind:value="{eventName}" required="required">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="{id}-data">Optional data:</label>
|
||||
<input type="text" class="form-control" style="{ dataValid ? '' : 'border: 1px solid red;' }" id="{id}-data" {placeholder} bind:value="{dataText}">
|
||||
</div>
|
||||
|
||||
<input class="btn btn-primary" type="button" on:click="{emitEvent}" disabled="{!dataValid || eventName.trim().length == 0}" value="Emit using {lang} runtime">
|
||||
|
||||
<CodeSnippet bind:isJs={isJs} jsCode={emitCodeJs} goCode={emitCodeGo}></CodeSnippet>
|
||||
|
||||
Listener output:
|
||||
<FakeTerm text={$loggingOutput} style="height: 300px; overflow: scroll"></FakeTerm>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</CodeBlock>
|
||||
26
v2/test/kitchensink/frontend/src/pages/events/Emit/code.go
Normal file
26
v2/test/kitchensink/frontend/src/pages/events/Emit/code.go
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
|
||||
wails "github.com/wailsapp/wails/v2"
|
||||
)
|
||||
|
||||
type MyStruct struct {
|
||||
runtime *wails.Runtime
|
||||
}
|
||||
|
||||
func (m *MyStruct) WailsInit(runtime *wails.Runtime) error {
|
||||
|
||||
// Load notes
|
||||
data, err := ioutil.ReadFile("notes.txt")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Emit an event with the loaded data
|
||||
runtime.Events.Emit("notes loaded", string(data))
|
||||
|
||||
m.runtime = runtime
|
||||
return nil
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
import { Events } from '@wails/runtime';
|
||||
|
||||
function processButtonPress(name, address) {
|
||||
Events.Emit("new user", name, address);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<code>Events.Emit()</code> is used to emit application-wide events. Data may be passed with the event.
|
||||
Any subscribers listening for events using <code>Events.On</code> will be called, passing the optional data.
|
||||
|
|
@ -1,11 +1,10 @@
|
|||
<script>
|
||||
import On from './On/On.svelte';
|
||||
import Emit from './Emit/Emit.svelte';
|
||||
import Once from './Once/Once.svelte';
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<h4>Events</h4>
|
||||
|
||||
Wails includes a unified events system which allows you to send events in either Go or Javascript and receive them in either Go or Javascript. The events methods may be accessed through the <code>runtime.Events</code> object. Available methods are:
|
||||
|
||||
<ul class="list">
|
||||
|
|
@ -20,6 +19,8 @@
|
|||
<div style="padding: 15px"></div>
|
||||
|
||||
<On></On>
|
||||
<br/>
|
||||
<Once></Once>
|
||||
<br/>
|
||||
<Emit></Emit>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,11 +2,13 @@
|
|||
import { Events } from '@wails/runtime';
|
||||
import { writable } from 'svelte/store';
|
||||
import CodeBlock from '../../../components/CodeBlock.svelte';
|
||||
import CodeSnippet from '../../../components/CodeSnippet.svelte';
|
||||
import description from './description.txt';
|
||||
import { UniqueID } from '../../../utils/utils';
|
||||
import FakeTerm from '../../../components/FakeTerm.svelte';
|
||||
import jsCode from './code.jsx';
|
||||
import goCode from './code.go';
|
||||
import { loggingOutput } from './store';
|
||||
|
||||
let isJs = false;
|
||||
$: lang = isJs ? 'Javascript' : 'Go';
|
||||
|
|
@ -16,8 +18,6 @@
|
|||
let id = UniqueID('events');
|
||||
|
||||
let eventName = "";
|
||||
let loggingOutput = writable("");
|
||||
|
||||
|
||||
function updateLog(eventName, data, source) {
|
||||
loggingOutput.update( (log) => {
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
return
|
||||
}
|
||||
|
||||
let name = eventName + " (" + (isJs ? 'JS' : 'Go') + ")"
|
||||
let name = '"' + eventName + '" (' + (isJs ? 'JS' : 'Go') + ")"
|
||||
if( $listeners.includes(name) ) {
|
||||
return
|
||||
}
|
||||
|
|
@ -54,33 +54,37 @@
|
|||
} else {
|
||||
// We call a function in Go to register a subscriber
|
||||
// for us
|
||||
backend.main.Events.Subscribe(eventName);
|
||||
backend.main.Events.On(eventName);
|
||||
}
|
||||
}
|
||||
|
||||
$: testcodeJs = "import { Events } from '@wails/runtime';\nEvents.On('" + eventName + "', callback);";
|
||||
$: testcodeGo = '// runtime is given through WailsInit()\nruntime.Events.On("' + eventName + '", func(optionalData ...interface{} {\n // Process data\n}))';
|
||||
|
||||
</script>
|
||||
|
||||
<CodeBlock bind:isJs={isJs} {jsCode} {goCode} {id} title="Events.On(eventName, callback)" {description}>
|
||||
<div class="logging-form">
|
||||
<form data-wails-no-drag class="mw-full">
|
||||
{#if $listeners.length > 0 }
|
||||
Subscribed to:
|
||||
<div class="form-group">
|
||||
<ul class="list">
|
||||
{#each $listeners as listener}
|
||||
<li>"{listener}"</li>
|
||||
{/each}
|
||||
</div>
|
||||
Now use <code>Events.Emit</code> to trigger the subscribers!<br/>
|
||||
{/if}
|
||||
<div class="form-group">
|
||||
<label for="{id}-eventName" class="required">Event Name to subscribe to</label>
|
||||
<input type="text" class="form-control" id="{id}-eventName" placeholder="MyEventName" bind:value="{eventName}" required="required">
|
||||
</div>
|
||||
|
||||
<input class="btn btn-primary" type="button" on:click="{subscribe}" value="Subscribe using {lang} runtime">
|
||||
|
||||
<CodeSnippet bind:isJs={isJs} jsCode={testcodeJs} goCode={testcodeGo}></CodeSnippet>
|
||||
{#if $listeners.length > 0 }
|
||||
<div class="form-group" style="margin-top:10px">
|
||||
Subscribed to:
|
||||
<ul class="list">
|
||||
{#each $listeners as listener}
|
||||
<li>{listener}</li>
|
||||
{/each}
|
||||
</div>
|
||||
Now use <code>Events.Emit</code> to trigger the subscribers!<br/>
|
||||
<div style="margin-top: 10px">Subscriber output will be printed below:</div>
|
||||
<FakeTerm text={$loggingOutput} style="height: 300px; overflow: scroll"></FakeTerm>
|
||||
{/if}
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
import { writable } from 'svelte/store';
|
||||
|
||||
export let loggingOutput = writable("");
|
||||
106
v2/test/kitchensink/frontend/src/pages/events/Once/Once.svelte
Normal file
106
v2/test/kitchensink/frontend/src/pages/events/Once/Once.svelte
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
<script>
|
||||
import { Events } from '@wails/runtime';
|
||||
import { writable } from 'svelte/store';
|
||||
import CodeBlock from '../../../components/CodeBlock.svelte';
|
||||
import CodeSnippet from '../../../components/CodeSnippet.svelte';
|
||||
import description from './description.txt';
|
||||
import { UniqueID } from '../../../utils/utils';
|
||||
import FakeTerm from '../../../components/FakeTerm.svelte';
|
||||
import jsCode from './code.jsx';
|
||||
import goCode from './code.go';
|
||||
import { loggingOutput } from '../On/store';
|
||||
|
||||
let isJs = false;
|
||||
$: lang = isJs ? 'Javascript' : 'Go';
|
||||
|
||||
// Listeners
|
||||
let listeners = writable([]);
|
||||
let id = UniqueID('events');
|
||||
|
||||
let eventName = "";
|
||||
|
||||
function removeSubscriber(eventName, source) {
|
||||
listeners.update( (current) => {
|
||||
let name = '"' + eventName + '" (' + source + ')';
|
||||
console.log(name);
|
||||
const index = current.indexOf(name);
|
||||
console.log("index = ", index);
|
||||
if (index > -1) {
|
||||
current.splice(index, 1);
|
||||
}
|
||||
console.log(current);
|
||||
return current;
|
||||
});
|
||||
}
|
||||
|
||||
function updateLog(eventName, data, source) {
|
||||
removeSubscriber(eventName, source);
|
||||
loggingOutput.update( (log) => {
|
||||
let datatext = (data ? JSON.stringify(data) : "(No data given)");
|
||||
return log + "[" + eventName + " (" + source + ")] data: " + datatext + " (Listener now destroyed)\n";
|
||||
});
|
||||
}
|
||||
|
||||
// Subscribe to the Go event calls
|
||||
Events.On("once event fired by go subscriber", (input) => {
|
||||
// Format the data for printing
|
||||
updateLog(input.Name, input.Data, "Go");
|
||||
});
|
||||
|
||||
function subscribe() {
|
||||
if (eventName.length == 0) {
|
||||
return
|
||||
}
|
||||
|
||||
let name = '"' + eventName + '" (' + (isJs ? 'JS' : 'Go') + ")"
|
||||
if( $listeners.includes(name) ) {
|
||||
return
|
||||
}
|
||||
|
||||
// Add eventName to listeners list
|
||||
listeners.update( (current) => {
|
||||
return current.concat(name);
|
||||
});
|
||||
|
||||
if( isJs ) {
|
||||
Events.Once(eventName, (...data) => {
|
||||
updateLog(eventName, data, "JS");
|
||||
})
|
||||
} else {
|
||||
// We call a function in Go to register a subscriber
|
||||
// for us
|
||||
backend.main.Events.Once(eventName);
|
||||
}
|
||||
}
|
||||
|
||||
$: testcodeJs = "import { Events } from '@wails/runtime';\nEvents.Once('" + eventName + "', callback);";
|
||||
$: testcodeGo = '// runtime is given through WailsInit()\nruntime.Events.Once("' + eventName + '", func(optionalData ...interface{} {\n // Process data\n}))';
|
||||
|
||||
</script>
|
||||
|
||||
<CodeBlock bind:isJs={isJs} {jsCode} {goCode} {id} title="Events.Once(eventName, callback)" {description}>
|
||||
<div class="logging-form">
|
||||
<form data-wails-no-drag class="mw-full">
|
||||
<div class="form-group">
|
||||
<label for="{id}-eventName" class="required">Event Name to subscribe to</label>
|
||||
<input type="text" class="form-control" id="{id}-eventName" placeholder="MyEventName" bind:value="{eventName}" required="required">
|
||||
</div>
|
||||
|
||||
<input class="btn btn-primary" type="button" on:click="{subscribe}" value="Subscribe using {lang} runtime">
|
||||
<CodeSnippet bind:isJs={isJs} jsCode={testcodeJs} goCode={testcodeGo}></CodeSnippet>
|
||||
{#if $listeners.length > 0 }
|
||||
<div class="form-group" style="margin-top:10px">
|
||||
Subscribed to:
|
||||
<ul class="list">
|
||||
{#each $listeners as listener}
|
||||
<li>{listener}</li>
|
||||
{/each}
|
||||
</div>
|
||||
Now use <code>Events.Emit</code> to trigger the subscribers!<br/>
|
||||
<div style="margin-top: 10px">Subscriber output will be printed below:</div>
|
||||
<FakeTerm text={$loggingOutput} style="height: 300px; overflow: scroll"></FakeTerm>
|
||||
{/if}
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</CodeBlock>
|
||||
19
v2/test/kitchensink/frontend/src/pages/events/Once/code.go
Normal file
19
v2/test/kitchensink/frontend/src/pages/events/Once/code.go
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
package main
|
||||
|
||||
import wails "github.com/wailsapp/wails/v2"
|
||||
|
||||
type MyStruct struct {
|
||||
runtime *wails.Runtime
|
||||
}
|
||||
|
||||
func (m *MyStruct) WailsInit(runtime *wails.Runtime) error {
|
||||
|
||||
runtime.Events.On("notes updated", func(optionalData ...interface{}) {
|
||||
// Get notes
|
||||
notes := optionalData[0].(*Notes)
|
||||
// Save the notes to disk
|
||||
})
|
||||
|
||||
m.runtime = runtime
|
||||
return nil
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import { Events } from '@wails/runtime';
|
||||
|
||||
let notes = [];
|
||||
|
||||
// Do some things
|
||||
Events.On("notes loaded", (newNotes) => {
|
||||
notes = newNotes;
|
||||
});
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<code>Events.Once()</code> is used to subscribe to events.
|
||||
The given callback will be called when an event matching the given event name is received, but only once.
|
||||
|
|
@ -8,8 +8,6 @@
|
|||
|
||||
</script>
|
||||
<div>
|
||||
<h4>Logging</h4>
|
||||
|
||||
Logging is part of the Wails Runtime and is accessed through the <code>runtime.Log</code> object.
|
||||
|
||||
There are {loglevels.length} methods available:
|
||||
|
|
@ -44,5 +42,5 @@ I am a Print message
|
|||
<Log></Log>
|
||||
<br/>
|
||||
<SetLogLevel></SetLogLevel>
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue