mirror of
https://github.com/wavetermdev/wails.git
synced 2026-08-05 13:53:43 -07:00
Feature: AssetServer Runtime (#2335)
* Tidy up runtime JS * Initial implementation of runtime over http * Update runtime deps. Fix test task. * Support Clipboard. Message Processor refactor. * Add `Window.Screen()` Clipboard `GetText` -> `Text` * Support most dialogs Better JS->Go object mapping Implement Go->JS callback mechanism Rename `window.runtime` -> `window.wails` to better reflect the Go API * Support SaveFile dialog * Remove go.work * Tidy up * Event->CustomEvent to prevent potential clash with native JS Event object Support Eventing * Support application calls * Support logging * Support named windows Remove debug info * Update v3 changes
This commit is contained in:
@@ -6,16 +6,19 @@ github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keL
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
|
||||
github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg=
|
||||
github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc=
|
||||
github.com/klauspost/cpuid/v2 v2.2.0/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/sftp v1.10.1 h1:VasscCm72135zRysgrJDKsntdmPN+OuU3+nnHYA9wyc=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
|
||||
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
const (
|
||||
runtimeJSPath = "/wails/runtime.js"
|
||||
ipcJSPath = "/wails/ipc.js"
|
||||
runtimePath = "/wails/runtime"
|
||||
)
|
||||
|
||||
type RuntimeAssets interface {
|
||||
@@ -22,6 +23,10 @@ type RuntimeAssets interface {
|
||||
RuntimeDesktopJS() []byte
|
||||
}
|
||||
|
||||
type RuntimeHandler interface {
|
||||
HandleRuntimeCall(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
|
||||
type AssetServer struct {
|
||||
handler http.Handler
|
||||
wsHandler http.Handler
|
||||
@@ -34,6 +39,9 @@ type AssetServer struct {
|
||||
servingFromDisk bool
|
||||
appendSpinnerToBody bool
|
||||
|
||||
// Use http based runtime
|
||||
runtimeHandler RuntimeHandler
|
||||
|
||||
assetServerWebView
|
||||
}
|
||||
|
||||
@@ -77,6 +85,10 @@ func NewAssetServerWithHandler(handler http.Handler, bindingsJSON string, servin
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (d *AssetServer) UseRuntimeHandler(handler RuntimeHandler) {
|
||||
d.runtimeHandler = handler
|
||||
}
|
||||
|
||||
func (d *AssetServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
if isWebSocket(req) {
|
||||
// Forward WebSockets to the distinct websocket handler if it exists
|
||||
@@ -122,6 +134,13 @@ func (d *AssetServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
case runtimeJSPath:
|
||||
d.writeBlob(rw, path, d.runtimeJS)
|
||||
|
||||
case runtimePath:
|
||||
if d.runtimeHandler != nil {
|
||||
d.runtimeHandler.HandleRuntimeCall(rw, req)
|
||||
} else {
|
||||
d.handler.ServeHTTP(rw, req)
|
||||
}
|
||||
|
||||
case ipcJSPath:
|
||||
content := d.runtime.DesktopIPC()
|
||||
if d.ipcJS != nil {
|
||||
|
||||
+14
-4
@@ -19,10 +19,20 @@ Informal and incomplete list of things needed in v3.
|
||||
- [ ] Implement alias for `window` in JS
|
||||
- [ ] Implement runtime dispatcher
|
||||
- [ ] Log
|
||||
- [ ] Same Window
|
||||
- [ ] Other Window
|
||||
- [ ] Dialogs
|
||||
- [ ] Events
|
||||
- [x] Same Window
|
||||
- [x] Other Window
|
||||
- [x] Dialogs
|
||||
- [x] Info
|
||||
- [x] Warning
|
||||
- [x] Error
|
||||
- [x] Question
|
||||
- [x] OpenFile
|
||||
- [x] SaveFile
|
||||
- [x] Events
|
||||
- [ ] Screens
|
||||
- [x] Clipboard
|
||||
- [ ] Application
|
||||
- [ ] Create `.d.ts` file
|
||||
|
||||
## Templates
|
||||
|
||||
|
||||
+8
-26
@@ -87,32 +87,15 @@ tasks:
|
||||
cmds:
|
||||
- npm install
|
||||
|
||||
build-runtime-dev:
|
||||
dir: internal/runtime/dev
|
||||
deps:
|
||||
- install-runtime-dev-deps
|
||||
sources:
|
||||
- ./*.js
|
||||
generates:
|
||||
- ../ipc_websocket.js
|
||||
cmds:
|
||||
- node build.js
|
||||
|
||||
build-runtime-ipc:
|
||||
dir: internal/runtime
|
||||
deps:
|
||||
- install-runtime-dev-deps
|
||||
sources:
|
||||
- ./desktop/ipc.js
|
||||
generates:
|
||||
- ipc.js
|
||||
cmds:
|
||||
- npx esbuild desktop/ipc.js --bundle --minify --outfile=ipc.js
|
||||
|
||||
test-runtime:
|
||||
dir: internal/runtime
|
||||
cmds:
|
||||
- npx vitest
|
||||
- npx vitest run
|
||||
|
||||
update-runtime:
|
||||
dir: internal/runtime
|
||||
cmds:
|
||||
- npx npm-check-updates -u
|
||||
|
||||
build-runtime-all:
|
||||
dir: internal/runtime
|
||||
@@ -123,10 +106,9 @@ tasks:
|
||||
- build-runtime-debug-darwin
|
||||
- build-runtime-debug-windows
|
||||
- build-runtime-debug-linux
|
||||
- build-runtime-dev
|
||||
- build-runtime-ipc
|
||||
|
||||
cmds:
|
||||
- task: test-runtime
|
||||
- cmd: echo "build complete"
|
||||
|
||||
build-runtime:
|
||||
dir: internal/runtime
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
# Changes for v3
|
||||
|
||||
## Events
|
||||
|
||||
In v3, there are 3 types of events:
|
||||
|
||||
- Application Events
|
||||
- Window Events
|
||||
- Custom Events
|
||||
|
||||
### Application Events
|
||||
|
||||
Application events are events that are emitted by the application. These events include native events such as `ApplicationDidFinishLaunching` on macOS.
|
||||
|
||||
### Window Events
|
||||
|
||||
Window events are events that are emitted by a window. These events include native events such as `WindowDidBecomeMain` on macOS.
|
||||
|
||||
### 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.
|
||||
|
||||
The data associated with a CustomEvent 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.
|
||||
|
||||
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.
|
||||
|
||||
### `Off` and `OffAll`
|
||||
|
||||
In v2, `Off` and `OffAll` calls would remove events in both JS and Go. Due to the multi-window nature of v3, this has been changed so that these methods only apply to the context they are called in. For example, if you call `Off` in a window, it will only remove events for that window. If you use `Off` in Go, it will only remove events for Go.
|
||||
|
||||
### Logging
|
||||
|
||||
There was a lot of requests for different types of logging in v2 so for v3 we have simplified things to make it as customisable as you want. There is now a single call `Log` that takes a LogMessage object. This object contains the message, the level, and the source, the log message and any data to be printed out. The default logger is the Console logger, however any number of outputs to log to can be added. Simply add custom loggers to the `options.Application.Logger.CustomLoggers` slice. The default logger does not have log level filtering, however custom loggers can be added that do.
|
||||
|
||||
### Developer notes
|
||||
|
||||
When emitting an event in Go, it will dispatch the event to local Go listeners and also each window in the application.
|
||||
When emitting an event in JS, it now sends the event to the application. This will be processed as if it was emitted in Go, however the sender ID will be that of the window.
|
||||
|
||||
## Window
|
||||
|
||||
The Window API has largely remained the same, however there are a few changes to note.
|
||||
|
||||
- Windows now have a Name that identifies them. This is used to identify the window when emitting events.
|
||||
|
||||
## ClipBoard
|
||||
|
||||
The clipboard API has been simplified. There is now a single `Clipboard` object that can be used to read and write to the clipboard. The `Clipboard` object is available in both Go and JS. `SetText()` to set the text and `Text()` to get the text.
|
||||
|
||||
## Bindings
|
||||
|
||||
TBD
|
||||
|
||||
## Dialogs
|
||||
|
||||
Dialogs are now available in JavaScript!
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
<style>body{ text-align: center; color: white; background-color: rgba(0,0,0,0); user-select: none; -ms-user-select: none; -webkit-user-select: none; }</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Events Demo</h1>
|
||||
<br/>
|
||||
<div id="results"></div>
|
||||
</body>
|
||||
|
||||
<script>
|
||||
wails.Events.On("myevent", function(data) {
|
||||
let currentHTML = document.getElementById("results").innerHTML;
|
||||
document.getElementById("results").innerHTML = currentHTML + "<br/>" + JSON.stringify(data);;
|
||||
})
|
||||
</script>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,72 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"embed"
|
||||
_ "embed"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/wailsapp/wails/v3/pkg/events"
|
||||
|
||||
"github.com/wailsapp/wails/v3/pkg/options"
|
||||
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
)
|
||||
|
||||
//go:embed assets
|
||||
var assets embed.FS
|
||||
|
||||
func main() {
|
||||
|
||||
app := application.New(options.Application{
|
||||
Name: "Events Demo",
|
||||
Description: "A demo of the Events API",
|
||||
Mac: options.Mac{
|
||||
ApplicationShouldTerminateAfterLastWindowClosed: true,
|
||||
},
|
||||
})
|
||||
|
||||
app.Events.On("myevent", func(e *application.CustomEvent) {
|
||||
log.Printf("[Go] CustomEvent received: %+v\n", e)
|
||||
})
|
||||
|
||||
app.On(events.Mac.ApplicationDidFinishLaunching, func() {
|
||||
for {
|
||||
log.Println("Sending event")
|
||||
app.Events.Emit(&application.CustomEvent{
|
||||
Name: "myevent",
|
||||
Data: "hello",
|
||||
})
|
||||
time.Sleep(10 * time.Second)
|
||||
}
|
||||
})
|
||||
|
||||
app.NewWebviewWindowWithOptions(&options.WebviewWindow{
|
||||
Title: "Events Demo",
|
||||
Assets: options.Assets{
|
||||
FS: assets,
|
||||
},
|
||||
Mac: options.MacWindow{
|
||||
Backdrop: options.MacBackdropTranslucent,
|
||||
TitleBar: options.TitleBarHiddenInsetUnified,
|
||||
InvisibleTitleBarHeight: 50,
|
||||
},
|
||||
})
|
||||
app.NewWebviewWindowWithOptions(&options.WebviewWindow{
|
||||
Title: "Events Demo",
|
||||
Assets: options.Assets{
|
||||
FS: assets,
|
||||
},
|
||||
Mac: options.MacWindow{
|
||||
Backdrop: options.MacBackdropTranslucent,
|
||||
TitleBar: options.TitleBarHiddenInsetUnified,
|
||||
InvisibleTitleBarHeight: 50,
|
||||
},
|
||||
})
|
||||
|
||||
err := app.Run()
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,11 @@ go 1.19
|
||||
require (
|
||||
github.com/go-task/task/v3 v3.20.0
|
||||
github.com/jackmordaunt/icns/v2 v2.2.1
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/leaanthony/clir v1.6.0
|
||||
github.com/leaanthony/gosod v1.0.3
|
||||
github.com/leaanthony/winicon v1.0.0
|
||||
github.com/matryer/is v1.4.0
|
||||
github.com/pterm/pterm v0.12.51
|
||||
github.com/samber/lo v1.37.0
|
||||
github.com/stretchr/testify v1.8.1
|
||||
@@ -33,6 +35,8 @@ require (
|
||||
github.com/mattn/go-runewidth v0.0.14 // indirect
|
||||
github.com/mattn/go-zglob v0.0.4 // indirect
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
@@ -53,3 +57,5 @@ require (
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
mvdan.cc/sh/v3 v3.6.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/wailsapp/wails/v2 => ../v2
|
||||
|
||||
@@ -26,6 +26,7 @@ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg78
|
||||
github.com/go-task/task/v3 v3.20.0 h1:pTavuhP+AiEpKLzh5I6Lja9Ux7ypYO5QMsEPTbhYEDc=
|
||||
github.com/go-task/task/v3 v3.20.0/go.mod h1:y7rWakbLR5gFElGgo6rA2dyr6vU/zNIDVfn3S4Of6OI=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
|
||||
github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo=
|
||||
github.com/gookit/color v1.5.2 h1:uLnfXcaFjlrDnQDT+NCBcfhrXqYTx/rcCa6xn01Y8yI=
|
||||
@@ -36,6 +37,8 @@ github.com/jackmordaunt/icns/v2 v2.2.1 h1:MGklwYP2yohKn2Bw7XxlF69LZe98S1vUfl5OvA
|
||||
github.com/jackmordaunt/icns/v2 v2.2.1/go.mod h1:6aYIB9eSzyfHHMKqDf17Xrs1zetQPReAkiUSHzdw4cI=
|
||||
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
|
||||
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
@@ -74,6 +77,10 @@ github.com/mattn/go-zglob v0.0.4 h1:LQi2iOm0/fGgu80AioIJ/1j9w9Oh+9DZ39J4VAGzHQM=
|
||||
github.com/mattn/go-zglob v0.0.4/go.mod h1:MxxjyoXXnMxfIpxTK2GAkw1w8glPsQILx3N5wrKakiY=
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
@@ -107,6 +114,7 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
@@ -119,8 +127,6 @@ github.com/tc-hib/winres v0.1.6 h1:qgsYHze+BxQPEYilxIz/KCQGaClvI2+yLBAZs+3+0B8=
|
||||
github.com/tc-hib/winres v0.1.6/go.mod h1:pe6dOR40VOrGz8PkzreVKNvEKnlE8t4yR8A8naL+t7A=
|
||||
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
|
||||
github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
|
||||
github.com/wailsapp/wails/v2 v2.3.2-0.20230117193915-45c3a501d9e6 h1:Wn+nhnS+VytzE0PegUzSh4T3hXJCtggKGD/4U5H9+wQ=
|
||||
github.com/wailsapp/wails/v2 v2.3.2-0.20230117193915-45c3a501d9e6/go.mod h1:zlNLI0E2c2qA6miiuAHtp0Bac8FaGH0tlhA19OssR/8=
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
|
||||
@@ -37,6 +37,6 @@ func GenerateBindings(options *GenerateBindingsOptions) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("error writing models file: %v", err)
|
||||
}
|
||||
|
||||
println("Generated models file '" + options.ModelsFilename + "'")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,22 +3,19 @@
|
||||
package runtime
|
||||
|
||||
var RuntimeAssetsBundle = &RuntimeAssets{
|
||||
desktopIPC: DesktopIPC,
|
||||
runtimeDesktopJS: DesktopRuntime,
|
||||
}
|
||||
|
||||
type RuntimeAssets struct {
|
||||
desktopIPC []byte
|
||||
websocketIPC []byte
|
||||
runtimeDesktopJS []byte
|
||||
}
|
||||
|
||||
func (r *RuntimeAssets) DesktopIPC() []byte {
|
||||
return r.desktopIPC
|
||||
return []byte("")
|
||||
}
|
||||
|
||||
func (r *RuntimeAssets) WebsocketIPC() []byte {
|
||||
return r.websocketIPC
|
||||
return []byte("")
|
||||
}
|
||||
|
||||
func (r *RuntimeAssets) RuntimeDesktopJS() []byte {
|
||||
|
||||
@@ -3,23 +3,19 @@
|
||||
package runtime
|
||||
|
||||
var RuntimeAssetsBundle = &RuntimeAssets{
|
||||
desktopIPC: DesktopIPC,
|
||||
websocketIPC: WebsocketIPC,
|
||||
runtimeDesktopJS: DesktopRuntime,
|
||||
}
|
||||
|
||||
type RuntimeAssets struct {
|
||||
desktopIPC []byte
|
||||
websocketIPC []byte
|
||||
runtimeDesktopJS []byte
|
||||
}
|
||||
|
||||
func (r *RuntimeAssets) DesktopIPC() []byte {
|
||||
return r.desktopIPC
|
||||
return []byte("")
|
||||
}
|
||||
|
||||
func (r *RuntimeAssets) WebsocketIPC() []byte {
|
||||
return r.websocketIPC
|
||||
return []byte("")
|
||||
}
|
||||
|
||||
func (r *RuntimeAssets) RuntimeDesktopJS() []byte {
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# README
|
||||
|
||||
After updating any files in this directory, you must run `wails task build-runtime` to regenerate the compiled JS.
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
_ __ _ __
|
||||
| | / /___ _(_) /____
|
||||
| | /| / / __ `/ / / ___/
|
||||
| |/ |/ / /_/ / / (__ )
|
||||
|__/|__/\__,_/_/_/____/
|
||||
The electron alternative for Go
|
||||
(c) Lea Anthony 2019-present
|
||||
*/
|
||||
|
||||
/* jshint esversion: 9 */
|
||||
|
||||
import {newRuntimeCaller} from "./runtime";
|
||||
|
||||
let call = newRuntimeCaller("application");
|
||||
|
||||
export function Hide() {
|
||||
return call("Hide");
|
||||
}
|
||||
|
||||
export function Show() {
|
||||
return call("Show");
|
||||
}
|
||||
|
||||
export function Quit() {
|
||||
return call("Quit");
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
_ __ _ __
|
||||
| | / /___ _(_) /____
|
||||
| | /| / / __ `/ / / ___/
|
||||
| |/ |/ / /_/ / / (__ )
|
||||
|__/|__/\__,_/_/_/____/
|
||||
The electron alternative for Go
|
||||
(c) Lea Anthony 2019-present
|
||||
*/
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
import {Call} from './calls';
|
||||
|
||||
// This is where we bind go method wrappers
|
||||
window.go = {};
|
||||
|
||||
export function SetBindings(bindingsMap) {
|
||||
try {
|
||||
bindingsMap = JSON.parse(bindingsMap);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
// Initialise the bindings map
|
||||
window.go = window.go || {};
|
||||
|
||||
// Iterate package names
|
||||
Object.keys(bindingsMap).forEach((packageName) => {
|
||||
|
||||
// Create inner map if it doesn't exist
|
||||
window.go[packageName] = window.go[packageName] || {};
|
||||
|
||||
// Iterate struct names
|
||||
Object.keys(bindingsMap[packageName]).forEach((structName) => {
|
||||
|
||||
// Create inner map if it doesn't exist
|
||||
window.go[packageName][structName] = window.go[packageName][structName] || {};
|
||||
|
||||
Object.keys(bindingsMap[packageName][structName]).forEach((methodName) => {
|
||||
|
||||
window.go[packageName][structName][methodName] = function () {
|
||||
|
||||
// No timeout by default
|
||||
let timeout = 0;
|
||||
|
||||
// Actual function
|
||||
function dynamic() {
|
||||
const args = [].slice.call(arguments);
|
||||
return Call([packageName, structName, methodName].join('.'), args, timeout);
|
||||
}
|
||||
|
||||
// Allow setting timeout to function
|
||||
dynamic.setTimeout = function (newTimeout) {
|
||||
timeout = newTimeout;
|
||||
};
|
||||
|
||||
// Allow getting timeout to function
|
||||
dynamic.getTimeout = function () {
|
||||
return timeout;
|
||||
};
|
||||
|
||||
return dynamic;
|
||||
}();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
/**
|
||||
* @description: Use the system default browser to open the url
|
||||
* @param {string} url
|
||||
* @return {void}
|
||||
*/
|
||||
export function BrowserOpenURL(url) {
|
||||
window.WailsInvoke('BO:' + url);
|
||||
}
|
||||
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
_ __ _ __
|
||||
| | / /___ _(_) /____
|
||||
| | /| / / __ `/ / / ___/
|
||||
| |/ |/ / /_/ / / (__ )
|
||||
|__/|__/\__,_/_/_/____/
|
||||
The electron alternative for Go
|
||||
(c) Lea Anthony 2019-present
|
||||
*/
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
export const callbacks = {};
|
||||
|
||||
/**
|
||||
* Returns a number from the native browser random function
|
||||
*
|
||||
* @returns number
|
||||
*/
|
||||
function cryptoRandom() {
|
||||
var array = new Uint32Array(1);
|
||||
return window.crypto.getRandomValues(array)[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a number using da old-skool Math.Random
|
||||
* I likes to call it LOLRandom
|
||||
*
|
||||
* @returns number
|
||||
*/
|
||||
function basicRandom() {
|
||||
return Math.random() * 9007199254740991;
|
||||
}
|
||||
|
||||
// Pick a random number function based on browser capability
|
||||
var randomFunc;
|
||||
if (window.crypto) {
|
||||
randomFunc = cryptoRandom;
|
||||
} else {
|
||||
randomFunc = basicRandom;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call sends a message to the backend to call the binding with the
|
||||
* given data. A promise is returned and will be completed when the
|
||||
* backend responds. This will be resolved when the call was successful
|
||||
* or rejected if an error is passed back.
|
||||
* There is a timeout mechanism. If the call doesn't respond in the given
|
||||
* time (in milliseconds) then the promise is rejected.
|
||||
*
|
||||
* @export
|
||||
* @param {string} name
|
||||
* @param {any=} args
|
||||
* @param {number=} timeout
|
||||
* @returns
|
||||
*/
|
||||
export function Call(name, args, timeout) {
|
||||
|
||||
// Timeout infinite by default
|
||||
if (timeout == null) {
|
||||
timeout = 0;
|
||||
}
|
||||
|
||||
let windowID = window.wails.window.ID();
|
||||
|
||||
// Create a promise
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
// Create a unique callbackID
|
||||
var callbackID;
|
||||
do {
|
||||
callbackID = name + '-' + randomFunc();
|
||||
} while (callbacks[callbackID]);
|
||||
|
||||
var timeoutHandle;
|
||||
// Set timeout
|
||||
if (timeout > 0) {
|
||||
timeoutHandle = setTimeout(function () {
|
||||
reject(Error('Call to ' + name + ' timed out. Request ID: ' + callbackID));
|
||||
}, timeout);
|
||||
}
|
||||
|
||||
// Store callback
|
||||
callbacks[callbackID] = {
|
||||
timeoutHandle: timeoutHandle,
|
||||
reject: reject,
|
||||
resolve: resolve
|
||||
};
|
||||
|
||||
try {
|
||||
const payload = {
|
||||
name,
|
||||
args,
|
||||
callbackID,
|
||||
windowID,
|
||||
};
|
||||
|
||||
// Make the call
|
||||
window.WailsInvoke('C' + JSON.stringify(payload));
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line
|
||||
console.error(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
window.ObfuscatedCall = (id, args, timeout) => {
|
||||
|
||||
// Timeout infinite by default
|
||||
if (timeout == null) {
|
||||
timeout = 0;
|
||||
}
|
||||
|
||||
// Create a promise
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
// Create a unique callbackID
|
||||
var callbackID;
|
||||
do {
|
||||
callbackID = id + '-' + randomFunc();
|
||||
} while (callbacks[callbackID]);
|
||||
|
||||
var timeoutHandle;
|
||||
// Set timeout
|
||||
if (timeout > 0) {
|
||||
timeoutHandle = setTimeout(function () {
|
||||
reject(Error('Call to method ' + id + ' timed out. Request ID: ' + callbackID));
|
||||
}, timeout);
|
||||
}
|
||||
|
||||
// Store callback
|
||||
callbacks[callbackID] = {
|
||||
timeoutHandle: timeoutHandle,
|
||||
reject: reject,
|
||||
resolve: resolve
|
||||
};
|
||||
|
||||
try {
|
||||
const payload = {
|
||||
id,
|
||||
args,
|
||||
callbackID,
|
||||
windowID: window.wails.window.ID(),
|
||||
};
|
||||
|
||||
// Make the call
|
||||
window.WailsInvoke('c' + JSON.stringify(payload));
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line
|
||||
console.error(e);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Called by the backend to return data to a previously called
|
||||
* binding invocation
|
||||
*
|
||||
* @export
|
||||
* @param {string} incomingMessage
|
||||
*/
|
||||
export function Callback(incomingMessage) {
|
||||
// Parse the message
|
||||
let message;
|
||||
try {
|
||||
message = JSON.parse(incomingMessage);
|
||||
} catch (e) {
|
||||
const error = `Invalid JSON passed to callback: ${e.message}. Message: ${incomingMessage}`;
|
||||
runtime.LogDebug(error);
|
||||
throw new Error(error);
|
||||
}
|
||||
let callbackID = message.callbackid;
|
||||
let callbackData = callbacks[callbackID];
|
||||
if (!callbackData) {
|
||||
const error = `Callback '${callbackID}' not registered!!!`;
|
||||
console.error(error); // eslint-disable-line
|
||||
throw new Error(error);
|
||||
}
|
||||
clearTimeout(callbackData.timeoutHandle);
|
||||
|
||||
delete callbacks[callbackID];
|
||||
|
||||
if (message.error) {
|
||||
callbackData.reject(message.error);
|
||||
} else {
|
||||
callbackData.resolve(message.result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
_ __ _ __
|
||||
| | / /___ _(_) /____
|
||||
| | /| / / __ `/ / / ___/
|
||||
| |/ |/ / /_/ / / (__ )
|
||||
|__/|__/\__,_/_/_/____/
|
||||
The electron alternative for Go
|
||||
(c) Lea Anthony 2019-present
|
||||
*/
|
||||
|
||||
/* jshint esversion: 9 */
|
||||
|
||||
import {newRuntimeCaller} from "./runtime";
|
||||
|
||||
let call = newRuntimeCaller("clipboard");
|
||||
|
||||
export function SetText(text) {
|
||||
return call("SetText", {text});
|
||||
}
|
||||
|
||||
export function Text() {
|
||||
return call("Text");
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
_ __ _ __
|
||||
| | / /___ _(_) /____
|
||||
| | /| / / __ `/ / / ___/
|
||||
| |/ |/ / /_/ / / (__ )
|
||||
|__/|__/\__,_/_/_/____/
|
||||
The electron alternative for Go
|
||||
(c) Lea Anthony 2019-present
|
||||
*/
|
||||
|
||||
/* jshint esversion: 9 */
|
||||
|
||||
import {newRuntimeCaller} from "./runtime";
|
||||
|
||||
import { nanoid } from 'nanoid/non-secure'
|
||||
|
||||
let call = newRuntimeCaller("dialog");
|
||||
|
||||
let dialogResponses = new Map();
|
||||
|
||||
function generateID() {
|
||||
let result;
|
||||
do {
|
||||
result = nanoid();
|
||||
} while (dialogResponses.has(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
export function dialogCallback(id, data, isJSON) {
|
||||
let p = dialogResponses.get(id);
|
||||
if (p) {
|
||||
if (isJSON) {
|
||||
p.resolve(JSON.parse(data));
|
||||
} else {
|
||||
p.resolve(data);
|
||||
}
|
||||
dialogResponses.delete(id);
|
||||
}
|
||||
}
|
||||
export function dialogErrorCallback(id, message) {
|
||||
let p = dialogResponses.get(id);
|
||||
if (p) {
|
||||
p.reject(message);
|
||||
dialogResponses.delete(id);
|
||||
}
|
||||
}
|
||||
|
||||
function dialog(type, options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let id = generateID();
|
||||
options = options || {};
|
||||
options["dialog-id"] = id;
|
||||
dialogResponses.set(id, {resolve, reject});
|
||||
call(type, options).catch((error) => {
|
||||
reject(error);
|
||||
dialogResponses.delete(id);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export function Info(options) {
|
||||
return dialog("Info", options);
|
||||
}
|
||||
|
||||
export function Warning(options) {
|
||||
return dialog("Warning", options);
|
||||
}
|
||||
|
||||
export function Error(options) {
|
||||
return dialog("Error", options);
|
||||
}
|
||||
|
||||
export function Question(options) {
|
||||
return dialog("Question", options);
|
||||
}
|
||||
|
||||
export function OpenFile(options) {
|
||||
return dialog("OpenFile", options);
|
||||
}
|
||||
|
||||
export function SaveFile(options) {
|
||||
return dialog("SaveFile", options);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
/*
|
||||
_ __ _ __
|
||||
| | / /___ _(_) /____
|
||||
_ __ _ __
|
||||
| | / /___ _(_) /____
|
||||
| | /| / / __ `/ / / ___/
|
||||
| |/ |/ / /_/ / / (__ )
|
||||
|__/|__/\__,_/_/_/____/
|
||||
The electron alternative for Go
|
||||
(c) Lea Anthony 2019-present
|
||||
*/
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
// Defines a single listener with a maximum number of times to callback
|
||||
/* jshint esversion: 9 */
|
||||
|
||||
import {newRuntimeCaller} from "./runtime";
|
||||
|
||||
let call = newRuntimeCaller("events");
|
||||
|
||||
/**
|
||||
* The Listener class defines a listener! :-)
|
||||
@@ -31,7 +34,7 @@ class Listener {
|
||||
// Callback invokes the callback with the given data
|
||||
// Returns true if this listener should be destroyed
|
||||
this.Callback = (data) => {
|
||||
callback.apply(null, data);
|
||||
callback(data);
|
||||
// If maxCallbacks is infinite, return false (do not destroy)
|
||||
if (this.maxCallbacks === -1) {
|
||||
return false;
|
||||
@@ -43,21 +46,41 @@ class Listener {
|
||||
}
|
||||
}
|
||||
|
||||
export const eventListeners = {};
|
||||
|
||||
/**
|
||||
* CustomEvent defines a custom event. It is passed to event listeners.
|
||||
*
|
||||
* @class CustomEvent
|
||||
*/
|
||||
export class CustomEvent {
|
||||
/**
|
||||
* Creates an instance of CustomEvent.
|
||||
* @param {string} name - Name of the event
|
||||
* @param {any} data - Data associated with the event
|
||||
* @memberof CustomEvent
|
||||
*/
|
||||
constructor(name, data) {
|
||||
this.name = name;
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
|
||||
export const eventListeners = new Map();
|
||||
|
||||
/**
|
||||
* Registers an event listener that will be invoked `maxCallbacks` times before being destroyed
|
||||
*
|
||||
* @export
|
||||
* @param {string} eventName
|
||||
* @param {function} callback
|
||||
* @param {function(CustomEvent): void} callback
|
||||
* @param {number} maxCallbacks
|
||||
* @returns {function} A function to cancel the listener
|
||||
*/
|
||||
export function EventsOnMultiple(eventName, callback, maxCallbacks) {
|
||||
eventListeners[eventName] = eventListeners[eventName] || [];
|
||||
export function OnMultiple(eventName, callback, maxCallbacks) {
|
||||
let listeners = eventListeners.get(eventName) || [];
|
||||
const thisListener = new Listener(eventName, callback, maxCallbacks);
|
||||
eventListeners[eventName].push(thisListener);
|
||||
listeners.push(thisListener);
|
||||
eventListeners.set(eventName, listeners);
|
||||
return () => listenerOff(thisListener);
|
||||
}
|
||||
|
||||
@@ -66,11 +89,11 @@ export function EventsOnMultiple(eventName, callback, maxCallbacks) {
|
||||
*
|
||||
* @export
|
||||
* @param {string} eventName
|
||||
* @param {function} callback
|
||||
* @param {function(CustomEvent): void} callback
|
||||
* @returns {function} A function to cancel the listener
|
||||
*/
|
||||
export function EventsOn(eventName, callback) {
|
||||
return EventsOnMultiple(eventName, callback, -1);
|
||||
export function On(eventName, callback) {
|
||||
return OnMultiple(eventName, callback, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,135 +101,87 @@ export function EventsOn(eventName, callback) {
|
||||
*
|
||||
* @export
|
||||
* @param {string} eventName
|
||||
* @param {function} callback
|
||||
* @param {function(CustomEvent): void} callback
|
||||
* @returns {function} A function to cancel the listener
|
||||
*/
|
||||
export function EventsOnce(eventName, callback) {
|
||||
return EventsOnMultiple(eventName, callback, 1);
|
||||
export function Once(eventName, callback) {
|
||||
return OnMultiple(eventName, callback, 1);
|
||||
}
|
||||
|
||||
function notifyListeners(eventData) {
|
||||
/**
|
||||
* listenerOff unregisters a listener previously registered with On
|
||||
*
|
||||
* @param {Listener} listener
|
||||
*/
|
||||
function listenerOff(listener) {
|
||||
const eventName = listener.eventName;
|
||||
// Remove local listener
|
||||
let listeners = eventListeners.get(eventName).filter(l => l !== listener);
|
||||
if (listeners.length === 0) {
|
||||
eventListeners.delete(eventName);
|
||||
} else {
|
||||
eventListeners.set(eventName, listeners);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the event name
|
||||
let eventName = eventData.name;
|
||||
|
||||
// Check if we have any listeners for this event
|
||||
if (eventListeners[eventName]) {
|
||||
|
||||
// Keep a list of listener indexes to destroy
|
||||
const newEventListenerList = eventListeners[eventName].slice();
|
||||
|
||||
// Iterate listeners
|
||||
for (let count = 0; count < eventListeners[eventName].length; count += 1) {
|
||||
|
||||
// Get next listener
|
||||
const listener = eventListeners[eventName][count];
|
||||
|
||||
let data = eventData.data;
|
||||
|
||||
// Do the callback
|
||||
const destroy = listener.Callback(data);
|
||||
if (destroy) {
|
||||
// if the listener indicated to destroy itself, add it to the destroy list
|
||||
newEventListenerList.splice(count, 1);
|
||||
/**
|
||||
* dispatches an event to all listeners
|
||||
*
|
||||
* @export
|
||||
* @param {CustomEvent} event
|
||||
*/
|
||||
export function dispatchCustomEvent(event) {
|
||||
console.log("dispatching event: ", {event});
|
||||
let listeners = eventListeners.get(event.name);
|
||||
if (listeners) {
|
||||
// iterate listeners and call callback. If callback returns true, remove listener
|
||||
let toRemove = [];
|
||||
listeners.forEach(listener => {
|
||||
let remove = listener.Callback(event)
|
||||
if (remove) {
|
||||
toRemove.push(listener);
|
||||
}
|
||||
});
|
||||
// remove listeners
|
||||
if (toRemove.length > 0) {
|
||||
listeners = listeners.filter(l => !toRemove.includes(l));
|
||||
if (listeners.length === 0) {
|
||||
eventListeners.delete(event.name);
|
||||
} else {
|
||||
eventListeners.set(event.name, listeners);
|
||||
}
|
||||
}
|
||||
|
||||
// Update callbacks with new list of listeners
|
||||
if (newEventListenerList.length === 0) {
|
||||
removeListener(eventName);
|
||||
} else {
|
||||
eventListeners[eventName] = newEventListenerList;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify informs frontend listeners that an event was emitted with the given data
|
||||
*
|
||||
* @export
|
||||
* @param {string} notifyMessage - encoded notification message
|
||||
|
||||
*/
|
||||
export function EventsNotify(notifyMessage) {
|
||||
// Parse the message
|
||||
let message;
|
||||
try {
|
||||
message = JSON.parse(notifyMessage);
|
||||
} catch (e) {
|
||||
const error = 'Invalid JSON passed to Notify: ' + notifyMessage;
|
||||
throw new Error(error);
|
||||
}
|
||||
notifyListeners(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit an event with the given name and data
|
||||
*
|
||||
* @export
|
||||
* @param {string} eventName
|
||||
*/
|
||||
export function EventsEmit(eventName) {
|
||||
|
||||
const payload = {
|
||||
name: eventName,
|
||||
data: [].slice.apply(arguments).slice(1),
|
||||
};
|
||||
|
||||
// Notify JS listeners
|
||||
notifyListeners(payload);
|
||||
|
||||
// Notify Go listeners
|
||||
window.WailsInvoke('EE' + JSON.stringify(payload));
|
||||
}
|
||||
|
||||
function removeListener(eventName) {
|
||||
// Remove local listeners
|
||||
delete eventListeners[eventName];
|
||||
|
||||
// Notify Go listeners
|
||||
window.WailsInvoke('EX' + eventName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Off unregisters a listener previously registered with On,
|
||||
* optionally multiple listeneres can be unregistered via `additionalEventNames`
|
||||
* optionally multiple listeners can be unregistered via `additionalEventNames`
|
||||
*
|
||||
[v3 CHANGE] Off only unregisters listeners within the current window
|
||||
*
|
||||
* @param {string} eventName
|
||||
* @param {...string} additionalEventNames
|
||||
*/
|
||||
export function EventsOff(eventName, ...additionalEventNames) {
|
||||
removeListener(eventName)
|
||||
|
||||
if (additionalEventNames.length > 0) {
|
||||
additionalEventNames.forEach(eventName => {
|
||||
removeListener(eventName)
|
||||
})
|
||||
}
|
||||
export function Off(eventName, ...additionalEventNames) {
|
||||
let eventsToRemove = [eventName, ...additionalEventNames];
|
||||
eventsToRemove.forEach(eventName => {
|
||||
eventListeners.delete(eventName);
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* OffAll unregisters all listeners
|
||||
* [v3 CHANGE] OffAll only unregisters listeners within the current window
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
export function OffAll() {
|
||||
eventListeners.clear();
|
||||
}
|
||||
|
||||
/*
|
||||
Emit emits an event to all listeners
|
||||
*/
|
||||
export function Emit(event) {
|
||||
return call("Emit", event);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user