mirror of
https://github.com/taigrr/wails.git
synced 2026-04-03 13:48:55 -07:00
Compare commits
1 Commits
bugfix/syn
...
generate-s
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f382f45f94 |
@@ -32,4 +32,3 @@ Wails is what it is because of the time and effort given by these great people.
|
||||
* [Zámbó, Levente](https://github.com/Lyimmi)
|
||||
* [artem](https://github.com/Unix4ever)
|
||||
* [Tim Kipp](https://github.com/timkippdev)
|
||||
* [Dmitry Gomzyakov](https://github.com/kyoto44)
|
||||
|
||||
@@ -57,7 +57,7 @@ _Ubuntu: 16.04, 18.04, 19.04_
|
||||
|
||||
_Also succesfully tested on: Zorin 15, Parrot 4.7, Linuxmint 19, Elementary 5, Kali, Neon_, Pop!_OS
|
||||
|
||||
#### Arch Linux / ArchLabs / Ctlos Linux
|
||||
#### Arch Linux / ArchLabs
|
||||
|
||||
`sudo pacman -S webkit2gtk gtk3`
|
||||
|
||||
|
||||
13
app.go
13
app.go
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/wailsapp/wails/lib/ipc"
|
||||
"github.com/wailsapp/wails/lib/logger"
|
||||
"github.com/wailsapp/wails/lib/renderer"
|
||||
wailsruntime "github.com/wailsapp/wails/runtime"
|
||||
)
|
||||
|
||||
// -------------------------------- Compile time Flags ------------------------------
|
||||
@@ -21,16 +20,6 @@ import (
|
||||
// BuildMode indicates what mode we are in
|
||||
var BuildMode = cmd.BuildModeProd
|
||||
|
||||
// Runtime is the Go Runtime struct
|
||||
type Runtime = wailsruntime.Runtime
|
||||
|
||||
// Store is a state store used for syncing with
|
||||
// the front end
|
||||
type Store = wailsruntime.Store
|
||||
|
||||
// CustomLogger is a specialised logger
|
||||
type CustomLogger = logger.CustomLogger
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
// App defines the main application struct
|
||||
@@ -136,7 +125,7 @@ func (a *App) start() error {
|
||||
a.ipc.Start(a.eventManager, a.bindingManager)
|
||||
|
||||
// Create the runtime
|
||||
a.runtime = wailsruntime.NewRuntime(a.eventManager, a.renderer)
|
||||
a.runtime = NewRuntime(a.eventManager, a.renderer)
|
||||
|
||||
// Start binding manager and give it our renderer
|
||||
err = a.bindingManager.Start(a.renderer, a.runtime)
|
||||
|
||||
@@ -63,8 +63,6 @@ const (
|
||||
PopOS
|
||||
// Solus distribution
|
||||
Solus
|
||||
// Ctlos Linux distribution
|
||||
Ctlos
|
||||
)
|
||||
|
||||
// DistroInfo contains all the information relating to a linux distribution
|
||||
@@ -131,8 +129,6 @@ func parseOsRelease(osRelease string) *DistroInfo {
|
||||
result.Distribution = Arch
|
||||
case "archlabs":
|
||||
result.Distribution = ArchLabs
|
||||
case "ctlos":
|
||||
result.Distribution = Ctlos
|
||||
case "debian":
|
||||
result.Distribution = Debian
|
||||
case "ubuntu":
|
||||
|
||||
@@ -193,16 +193,7 @@ distributions:
|
||||
name: ArchLabs
|
||||
gccversioncommand: *gccdumpversion
|
||||
programs: *archdefaultprograms
|
||||
libraries: *archdefaultlibraries
|
||||
ctlos:
|
||||
id: ctlos
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: Ctlos Linux
|
||||
gccversioncommand: *gccdumpversion
|
||||
programs: *archdefaultprograms
|
||||
libraries: *archdefaultlibraries
|
||||
libraries: *archdefaultlibraries
|
||||
manjaro:
|
||||
id: manjaro
|
||||
releases:
|
||||
|
||||
@@ -276,7 +276,7 @@ func CheckDependencies(logger *Logger) (bool, error) {
|
||||
switch distroInfo.Distribution {
|
||||
case Ubuntu, Debian, Zorin, Parrot, Linuxmint, Elementary, Kali, Neon, Deepin, Raspbian, PopOS:
|
||||
libraryChecker = DpkgInstalled
|
||||
case Arch, ArcoLinux, ArchLabs, Ctlos, Manjaro, ManjaroARM:
|
||||
case Arch, ArcoLinux, ArchLabs, Manjaro, ManjaroARM:
|
||||
libraryChecker = PacmanInstalled
|
||||
case CentOS, Fedora, Tumbleweed, Leap:
|
||||
libraryChecker = RpmInstalled
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
|
||||
"github.com/wailsapp/wails"
|
||||
)
|
||||
|
||||
// Counter is what we use for counting
|
||||
type Counter struct {
|
||||
r *wails.Runtime
|
||||
store *wails.Store
|
||||
}
|
||||
|
||||
// WailsInit is called when the component is being initialised
|
||||
func (c *Counter) WailsInit(runtime *wails.Runtime) error {
|
||||
c.r = runtime
|
||||
c.store = runtime.Store.New("Counter", 0)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RandomValue sets the counter to a random value
|
||||
func (c *Counter) RandomValue() {
|
||||
c.store.Set(rand.Intn(1000))
|
||||
}
|
||||
|
||||
// Increment will increment the counter
|
||||
func (c *Counter) Increment() {
|
||||
|
||||
increment := func(data int) int {
|
||||
return data + 1
|
||||
}
|
||||
|
||||
// Update the store using the increment function
|
||||
c.store.Update(increment)
|
||||
}
|
||||
|
||||
// Decrement will decrement the counter
|
||||
func (c *Counter) Decrement() {
|
||||
|
||||
decrement := func(data int) int {
|
||||
return data - 1
|
||||
}
|
||||
// Update the store using the decrement function
|
||||
c.store.Update(decrement)
|
||||
}
|
||||
@@ -2,9 +2,8 @@
|
||||
html,
|
||||
body {
|
||||
background-color: white;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
width: 1024px;
|
||||
height: 768px;
|
||||
}
|
||||
|
||||
.container {
|
||||
@@ -19,16 +18,6 @@ button {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
#newCounter {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.result {
|
||||
margin-top: 3rem;
|
||||
text-align: center;
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
|
||||
@@ -4,8 +4,6 @@ const runtime = require('@wailsapp/runtime');
|
||||
// Main entry point
|
||||
function start() {
|
||||
|
||||
var mystore = wails.Store.New('Counter');
|
||||
|
||||
// Ensure the default app div is 100% wide/high
|
||||
var app = document.getElementById('app');
|
||||
app.style.width = '100%';
|
||||
@@ -15,33 +13,18 @@ function start() {
|
||||
app.innerHTML = `
|
||||
<div class='logo'></div>
|
||||
<div class='container'>
|
||||
<button onClick='window.backend.Counter.Increment()'>
|
||||
Increment Counter
|
||||
</button>
|
||||
<button onClick='window.backend.Counter.Decrement()'>
|
||||
Decrement Counter
|
||||
</button>
|
||||
</div>
|
||||
<div class='result'>Counter: <span id='counter'></span></div>
|
||||
<div class='container'>
|
||||
<input id='newCounter' type="number" value="0"/>
|
||||
<button id='setvalue'>Set Counter Value</button>
|
||||
<button onclick='window.backend.Counter.RandomValue()'>Set to Random Value</button>
|
||||
<button id='button'>Click Me!</button>
|
||||
<div id='result'/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Connect counter value button to Go method
|
||||
document.getElementById('setvalue').onclick = function() {
|
||||
let newValue = parseInt(document.getElementById('newCounter').value,10);
|
||||
mystore.set(newValue);
|
||||
// Connect button to Go method
|
||||
document.getElementById('button').onclick = function() {
|
||||
window.backend.basic().then( function(result) {
|
||||
document.getElementById('result').innerText = result;
|
||||
});
|
||||
};
|
||||
|
||||
mystore.subscribe( (state) => {
|
||||
document.getElementById('counter').innerText = state;
|
||||
});
|
||||
|
||||
mystore.set(0);
|
||||
};
|
||||
|
||||
// We provide our entrypoint as a callback for runtime.Init
|
||||
runtime.Init(start);
|
||||
runtime.Init(start);
|
||||
@@ -5,6 +5,10 @@ import (
|
||||
"github.com/wailsapp/wails"
|
||||
)
|
||||
|
||||
func basic() string {
|
||||
return "Hello World!"
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
js := mewn.String("./frontend/build/main.js")
|
||||
@@ -18,6 +22,6 @@ func main() {
|
||||
CSS: css,
|
||||
Colour: "#131313",
|
||||
})
|
||||
app.Bind(&Counter{})
|
||||
app.Bind(basic)
|
||||
app.Run()
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package cmd
|
||||
|
||||
// Version - Wails version
|
||||
const Version = "v1.7.2-pre5"
|
||||
const Version = "v1.7.2-pre3"
|
||||
|
||||
37
cmd/wails/3_generate.go
Normal file
37
cmd/wails/3_generate.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/leaanthony/spinner"
|
||||
"github.com/wailsapp/wails/lib/stores"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
var generateStores = false
|
||||
|
||||
buildSpinner := spinner.NewSpinner()
|
||||
buildSpinner.SetSpinSpeed(50)
|
||||
|
||||
commandDescription := `This command will generate components`
|
||||
generateCommand := app.Command("generate", "Generate components").
|
||||
LongDescription(commandDescription).
|
||||
BoolFlag("s", "Generate Stores", &generateStores)
|
||||
|
||||
generateCommand.Action(func() error {
|
||||
|
||||
logger.PrintSmallBanner("Generating")
|
||||
fmt.Println()
|
||||
|
||||
if generateStores {
|
||||
err := stores.Generate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
})
|
||||
}
|
||||
2
go.mod
2
go.mod
@@ -21,9 +21,9 @@ require (
|
||||
github.com/stretchr/testify v1.3.0 // indirect
|
||||
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba
|
||||
golang.org/x/image v0.0.0-20200430140353-33d19683fad8
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344 // indirect
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd
|
||||
golang.org/x/text v0.3.0
|
||||
golang.org/x/tools v0.0.0-20200902012652-d1954cc86c82
|
||||
gopkg.in/AlecAivazis/survey.v1 v1.8.4
|
||||
gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22
|
||||
)
|
||||
|
||||
18
go.sum
18
go.sum
@@ -64,15 +64,22 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba h1:2DHfQOxcpWdGf5q5IzCUFPNvRX9Icf+09RvQK2VnJq0=
|
||||
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba/go.mod h1:iLnlXG2Pakcii2CU0cbY07DRCSvpWNa7nFxtevhOChk=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw=
|
||||
golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -83,6 +90,13 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20u
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200902012652-d1954cc86c82 h1:shxDsb9Dz27xzk3A0DxP0JuJnZMpKrdg8+E14eiUAX4=
|
||||
golang.org/x/tools v0.0.0-20200902012652-d1954cc86c82/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/AlecAivazis/survey.v1 v1.8.4 h1:10xXXN3wgIhPheb5NI58zFgZv32Ana7P3Tl4shW+0Qc=
|
||||
gopkg.in/AlecAivazis/survey.v1 v1.8.4/go.mod h1:iBNOmqKz/NUbZx3bA+4hAGLRC7fSK7tgtVDT4tB22XA=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
|
||||
@@ -196,7 +196,7 @@ func (b *boundMethod) processWailsInit() error {
|
||||
// It must be *wails.Runtime
|
||||
inputName := b.inputs[0].String()
|
||||
b.log.Debugf("WailsInit input type: %s", inputName)
|
||||
if inputName != "*runtime.Runtime" {
|
||||
if inputName != "*wails.Runtime" {
|
||||
return fmt.Errorf("Invalid WailsInit() definition. Expected input to be wails.Runtime, but got %s", inputName)
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ func (b *boundMethod) processWailsInit() error {
|
||||
}
|
||||
|
||||
func (b *boundMethod) processWailsShutdown() error {
|
||||
// We must not have any inputs
|
||||
// We must have only 1 input, it must be *wails.Runtime
|
||||
if len(b.inputs) != 0 {
|
||||
return fmt.Errorf("Invalid WailsShutdown() definition. Expected 0 inputs, but got %d", len(b.inputs))
|
||||
}
|
||||
|
||||
@@ -5,5 +5,5 @@ package renderer
|
||||
import "github.com/leaanthony/mewn"
|
||||
|
||||
func init() {
|
||||
mewn.AddAsset(".", "../../runtime/assets/wails.js", "1f8b08000000000000ff94587f6f1b37d2fe2a2be27d5532a6b752ae875e56dd06a9eba23e38761127d73f744241ed8e24262b52478eac0812bffb61f6b76cb9770704b1440ec9e13ccfcc3cd460b135196a6bb8118747e5224c0f61d20c46c09d38e805c7a99b0907b87526a2cf317cdd58877e424b6c4a43e941274e16c9602cebc9e410c2a45e646851a68a82db66adb4b2fb0c42dab84807a36e2c40bc4e8d84384b51429ca79dab12a51307882d7d14c7e3fdfc336418e7b0d0067e7376030ef7a5d901cc760d4ecd0b480623b9044c5c104142ecd2fed5d9d654ab73364871bf01bb881ef6ebb92d86c3ea6f8cf6019d36cb8f6a391cbe74e2735b797854c51612f6dee6db025810f2a5c5ec8f3fc0d766cdb2c1a872174fae5f82321ee270c84d0adc0821ff36c4062133d10bfe1dcd325b1ec5d2e64e6638a47f717752b788b07469ed5ce6402170b32d0a41db41ecb87bc97527590e0bb52d903d8d78750b13847c5d3ae4cbb874413662611d2f69146913190171ce9db4b2bd2e8a434b229c8578ae4d5efa25ad100dbf1cc5c8a4cfd9fce4b66f5b8b6ed7b8f63d2467265b06935f2899621285443ace3e81a436ac43b471162d5d325e297fbf334db0aa2ca005b4c726654c0287d8a72311f8f484e340bcf41051cc326413c20085ac3db9311a99e4cf7dfe1a84a8c13c84490d5c1556f633ccb7cbb3ab8a205aab1bb3b0678d7ccfe877e50c4179ce6ed1b3bb76cebab35679cfea1785aa386bb56bae639bebd86a9595ec7e03e6d387dbb3ebf6cdeeb5dd2f9ad2ea8ce1bc39403707e86aa196ec0e7667d75c356b543a9d75f5326b70abc34ff8274612e473957db9f93901b951fbc2aa3cc13039a9be7ac177dae47617ef942efcdce97c096f9f0fc53b987b9b7d018c3d502a88a43682af08cea822d6e6d17ea1b220555c8059e2eac7519b67988e26f8433331c18b0ba1a638e34604fef787fbbbb84a51bdd873274468efb6ad589e7156d8259387021ea1488c5c83f76a0909869e714137da7296577c33bd295f4fe99264fd99453db36b98d59fcceb49a8e8d49fdad5538b8a434604bae7463e9ef4b265834d93dadba218a4301cd61f8e470ee9484803bbe83767d7da03ef9077d256a8ea496e0f3a3517ec925d6cb808bb952e803f4ef5ac2a943f8e44450c0ff851afc16e91f719647999119c5da9a288d046ecc25cb008f51af2c86e318e3ec0bfb6e031baf93989d88516220809624247a407acb6fc5599bc80444907546e122b1d785b3c42e2c204dd9e7022da3179a082a9cdf24ead898bb942953cc1996a9116215398ad28969935de161097b12662843e115627e56ec959c5ce985d9455adb5dbd356b5d58ab39f9cdd7970719bb37d08e72fdb56796b44d8a435cf33b7dfa0ed97720ab84909b94fdae05f5ebf734eedf9b86d0f270be325e0076572bbfe073527e2e374343b57fddf8c46df8fdfbc79fdd7efbeff6ef4e6cdf8d57b85abd8956bb908650158b75d2032bce4d7e059a71e701369e351998c7a1e0a812b67771139fc71bf819610c6588c08b6484559a1bc8f948f54d46cc844e0b8d25e1a2181187b3996f43dbeaa0bcc49036cf45aac369b625fb54c23e4e5789012ed47699a72b84cc72204797d922af74daa5c4fcd2ca5ff8ec7e9acee29e4f4babce98466e2cdd6afb8eb61f9d075df273c9bce625fe80c6a8f945b6ed760d08b6a988fa962a707d3632a8649c6193c824126a1caecbb1367bfd071c4f826af6117fdd28481913dbb30420e461dbf2bcbc138744e5f5560913948975254299b07fdfa5ba356a3f53b0d45da478499361ab52ab4879c35dd6a3a6be85762e4b7739f393d8713906c153f234285a4879ed24371801465df87f89a42e1e3ebb546aa94baf089df9b2cf1681d24db4dae10f2f97ee1ac4130794259f9040610a4b617d65dab6cd5ab4d461c0c0741c95e3953ed764e5571101347ce96b5e39c83f7e6cfdc23b236de9d3a507166a39c2f1b18a4e63ff92a84c4e1b0891e2924fadc41fbb94d68feb991b7ca7bbd34c7637fbfae418ea94136e4ec37ca8a1f693b37c5d9a459e648bf82f8afe41f482748bbd3bb09e86d155abd29eae428f3bccb9050c7b80e5c7a388d7adaff723c76b39d7dc9ca9bf47007bb9faa8e903c07763a8b336b3285dcc47e5310c76226ca8f6d7e9eee4c59828dca18b72ac3a5a389fba199b81c4fdc453aae4ea9de8b65767de156885eded6a9c51a27ac644d86a9e851153a8f3eab474579b4c148e760502f34b898093181a99d51139fda597a0865859cda59a8941dc61bbbe1a23e55ffe9a9fa7f3b55cfd227ad882456ef0dddd0a62d7f25073a6c276d2b3512a885b64f8e4e429c2421a6861e0fcb33b35dd90f1202174136bde139da1393e690d91c3e7db8b9b2eb8d35600878079b4265c0bffda7bff876291913ddd07474f9465d2e6687d781a6feffff8614042abf789ab975b56d6a6aca6e4c154ab28a36ca7bc849fd34da3889daf8635c6b4ac9e2e87d2d2f23265a6a8a4955890b0e955eab10acdb834b316e76d5b9b4e96343b746c2a5ac094af44d7baa93ec9b1273074bed11f2c160c09a934e1591ee9f4ac2a900e51aad67e3138926640e052044e485c46a87b736ae741baf07444223a580e31853e71341de59d48b7df24c4e50dbedca15940dbaeea0425689570ed585ab9f79344e7e68ea4e94b982a0d37de8b0075dce4f6123c7220f06093953ba174765c18fa8694769d96b836d0509d7623884a67e383916a1d41410827c97e70f654a3db96175a9dc66657ad4bf445c1740df38abb2908909c4085f3135b2b59cdb7c4fd5134c7eb5d2454eecc0e1f0a1ec513786e27df5f070a6eabd7816ee0b200e5022be43747abe45e08cea3a938cceff36f39e09897169fbb002c0b7fd2f71e6fdc7d2cf044f7c7b7226d9dcd9bcfa2da79b5c81ca8fc7f6eb12b076ceffb4ffa84a4dcf191931d2b0e2e484ead61a93af14ea9bdfae6e89d606dc4904542b4082bc4d0fb776993859ebefc4caaa9b27877bf304a5fbfa378c7bf37e5ba0de1490dc4b5225c983fc1594c339a85364bb773149d1c91df1a057b7ca24ba3108ee5115e54f1654bd1c3da3dad1fe3b8a646610a50fefb22fc6ee0ac897903c79520fe8989edcce5b99adba45d1d6d06713ad1ac77b75c148f60dd538da8853941e4a29a3e51fc94d4f867ead2489089f4f9ef1f25634add89a32d54f7fc70459be2c4f14d4ad5dc6754f7af5ead5abe84a6d972b8c3e99555951f2aaf04434c7847c6969573849febe64f5e9c32d59e0cb16b7da407467c90a5eb6bab2c5766d6a3bf7b25d1902b2b122c88746221656e5a49cc34c4cfe1d0000ffff6a61b37f93160000")
|
||||
mewn.AddAsset(".", "../../runtime/assets/wails.js", "1f8b08000000000000ff94586d8f1bb711fe2b2ba255481f8f91dc14a977c318cee582a838df053ebbfda00a01b53b92e85b915b2e758a20f1bf17b3efba97a2050c7bc519728633cf3c33f468b533a9d7d650c38e8fca45208f216917234f1d3bea1585b95b30077ee74c84df02fe28acf365825bacc42579d4b1e3793c9af246181f43489a4d0637a52acfa96df772cbfb6fcfb815b91c4dfab5e0c5561aee452a817b91c9de550edcb1a317163fd9e974b7fc0aa91719acb481df9c2dc0f943a57604b3db8253cb1ce2d184afc1c72eb0c0bd70727875b233f5ee8c8ca43f146057d1fd61bbb4f9785cff2bbcbdf74e9bf567b51e8f5fb3f85c971f1f55be83987cb4d92e0712187f6d33f9fd77281bb576db6852bbebcfae5f25653a86f1981ae9a9618cff6d0c6d864ca257f43b94125b9922b2bd93198ff18fe82df59b30974e36cea50e94076a7679cef0382f1c75afb9ee38c960a576b9274f235edfc204c6df560e95555cfa201bb6b28e56308ab4890cf322a38e5bde5d17d8b103112c82586a93557e71cb588b2f873132f2399a9fdcf67da7d19f2a1adf43fc82b04330fa059c28c281714073f6494a1ac5264485b3dee225c54695777bd306abae02dc8067149210eea917a59cb040e76718f788cb12228c59ea49823900c61b4f66467bc2e9739f6781b12699c7903489abc34a7e86e56efde2ae5d609dd6ccacec8b4af940e99fca194ce54b7aab81deb573d6bda8950db47e515ee52f6a95ed756c7b1d5befb29cdc1560be7cba7971dfa13dbdd1fb456359bda0b86c0d68395ff4dca7da1c34a1c45cc68663fa962a7d98fd1c7b5ea8436e55164348ce9854afe85e9bcceec55ee9bc5c3a9dade1fdf325b1876569d307f0a20484358b1b25f8c383332a17da3cda07a086712d72306bbff971d2d50cc849023fb482042e2e989ec3821a16e8dfefef6e455d6e7a75a08eb1d0dd2dad11ab28c9ed9af0630e8f90c7866fa12cd51a620803e51dde28a524abb16306a2bc11e90a3043c9aa91ec5b940c855923841a1a4351d98856351e0c0b78cf3d2fcefad2639b9bb64c77793e927e3c6e3e4e27eae5847103fbe83767b7ba04da67de715b675527993d6a692ec825b9d85316f61b9d032de67a5193de8f13867aa92cc17fd65bb03b4f8708b2b4423725572acf236f2372612e48e4f516b2c8eebc883ec1bf7750fa68f6731c910bcd5860dcb3044dc8a3af8ffc55992c8738e50e903a62cb1d94367f84d885c4bb03e6096147f811c94f9bf5adda221633e555fc24cfc82b9a8554f97453c5d29ad2e620aa582330c21008eb33ea7aa4a446a720171543757a073caad15a53f293b3fb129ce8ea6f98c2e5ebba750d1a16f6b2c179ea0e85b7435ac6801b8999fba28dffcbdb0fcea9039d76547fb651acc17f5226b3db7f60a341f4cc278b9798fcdd64f2fdf4ddbbb77ffdeefbef26efde4ddf7c547e235cb597b25011c0b663f4c8d00a5fa3675d77444da44de99549b17f01637ee3ec3e42873f1f0ae800618cf511a62d52519aabb28c5419a9a83d90b040fd4697dc30ee11b197538ebfc555433067cdac9dbd842a8afc50b73fc3f8e5742411f6132925f59772ca42e09bb352b96b4b6533370b897f9d4ef345d31fd0e96d75d30425a2d8951bea06b9bcee3be9139ccd17a2cc75da7aa4dc7ab705e34b562fd329b2af3c9a015221248a127804e309f77565df9f39fb80e610f16d5dc33efaa50d03417d7261181f4d7a7cd79aa369e89dbeeab24eafda794695a55e9bd36918d49e45a709fcd0dd60c8a6d5ddbdec64735824ed3687038b67ff53bff7dc311cd67050f6384c876ec0604d042b30f4610c0dce110a6032790c7cd83fe4f0c7e9d44b7bfd2ac75fe5f116f63fd5b4113f9f8fe60b915a932a4f8d288b5c7b4a0461d56797c4f3939118a16d45d3ae15393949dc0fade0729ab80b39adadd40f04dc377aa096b141729b6a21ad139693489711968e8a1e55aeb3e8ab7a5465ea74e1239d81f17aa5c109c258e2e776814c3fb70b790c5519cded22d4ad1c44610bca1aabfabf5ad5ff9f55bd904ff80afbf0e0d1d4c2a6ab910a037d6e938e6f0df7c8b3dd8cd9f799b3f20769705a5cbf20edb921701f280bbc2590e7d94e8ccc20b5197cf934bbb2dbc21a3098780745ae52a0dffeabbcf876cd0961fdd27c72f94e5dae16c7b701457ffed3b80a823b1c1b4a28942b713e694a12dacb9399a943895a51a1ca12326c91ed0015475dfc413483072722fad8cc2011611d34595293ec8efabaa9d7196c38c4c93ac278aaceb895450bb7b6cf4bd20625faa6b3ea38f9a6cab983b52e3d64a3d188b496cedba61e5ac5ee9a8372ed4060c5591f673c831c3c44e8056f4e786f45dddc69b3c0625ca9ba3c0581f4c802bfb55eaf0ef1b39e83dcdcd395af58bca159c6ebc2ab961ae21a561eaea31fd56c8b95cb30757a983a18a42ea3e76943c7a2128cc7cc99ca3d115d238347c8ec91ac0839d8ae6b51cdc663dff287e35316aac6e343e01fb2ecbe2aa92737ac2f95d9b42a8fe6e9799d03fea2a4ae424c8cf0f0879786779a4b9b1d903dc164571b9d67880e188fafab21686630de57f7f72fb0deabb6fc2107c212c042fce0bdd3cb9d074a90d7092768ffdbb42c09e3202addfb0d807f3ffc21d2b2fc5cf919c3996f4f6ca2ceadcda07abcf7c20da8ec74ea7eaec137ce953f1d3eab6af0a30495080e3aeccc427d6bede319867af6dbd50dc2da803b8b80aebb3c4e82fc561e6fec3a76bc19d262cbabe496f1f1ce3cc9d25df368bd331f77b9d7450ef11dbfde6a1f5ff35f4139bf04759ed9fef184f34a728f3818f056554433e3c13daabc7aa3227b399cb5bbd5e1b08db34860950f1fd20763f739646b889fbcbb466866309365dd2ca6fa4dd1cee0b78936ade3035e309c7c831c8707518cd2eff1d7c18c32434386b27075f6c6e3b7ac6dc1d654257efe1f569e57cf8ee1167163d7a2e9456fdebc79135da9dd7ae3a32f6653314956134e8432c2f86b5b7bc2c4d9e835ad2f9f6e50035ed7b8d106a25b8b5afe75ad2b9befb6a6d173afeb5521401dcb02bfc687a0cecb185fcb901116162cf94f000000ffff04075a367c140000")
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
14
lib/stores/generate.go
Normal file
14
lib/stores/generate.go
Normal file
@@ -0,0 +1,14 @@
|
||||
// Package stores
|
||||
package stores
|
||||
|
||||
import "os"
|
||||
|
||||
// Generate stores that are found in the project
|
||||
func Generate() error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ParseProject(cwd)
|
||||
return nil
|
||||
}
|
||||
442
lib/stores/parse.go
Normal file
442
lib/stores/parse.go
Normal file
@@ -0,0 +1,442 @@
|
||||
package stores
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/leaanthony/slicer"
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
var internalMethods = slicer.String([]string{"WailsInit", "Wails Shutdown"})
|
||||
|
||||
var structCache = make(map[string]*ParsedStruct)
|
||||
var boundStructs = make(map[string]*ParsedStruct)
|
||||
var boundMethods = []string{}
|
||||
var boundStructPointerLiterals = []string{}
|
||||
var boundStructLiterals = slicer.StringSlicer{}
|
||||
var boundVariables = slicer.StringSlicer{}
|
||||
var app = ""
|
||||
var structPointerFunctionDecls = make(map[string]string)
|
||||
var structFunctionDecls = make(map[string]string)
|
||||
var variableStructDecls = make(map[string]string)
|
||||
var variableFunctionDecls = make(map[string]string)
|
||||
|
||||
type Parameter struct {
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
type ParsedMethod struct {
|
||||
Struct string
|
||||
Name string
|
||||
Comments []string
|
||||
Inputs []*Parameter
|
||||
Returns []*Parameter
|
||||
}
|
||||
|
||||
type ParsedStruct struct {
|
||||
Name string
|
||||
Methods []*ParsedMethod
|
||||
}
|
||||
|
||||
type BoundStructs []*ParsedStruct
|
||||
|
||||
func ParseProject(projectPath string) {
|
||||
|
||||
cfg := &packages.Config{Mode: packages.NeedFiles | packages.NeedSyntax | packages.NeedTypesInfo}
|
||||
pkgs, err := packages.Load(cfg, projectPath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "load: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if packages.PrintErrors(pkgs) > 0 {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Iterate the packages
|
||||
for _, pkg := range pkgs {
|
||||
|
||||
// Iterate the files
|
||||
for _, file := range pkg.Syntax {
|
||||
|
||||
var wailsPkgVar = ""
|
||||
|
||||
ast.Inspect(file, func(n ast.Node) bool {
|
||||
switch x := n.(type) {
|
||||
// Parse import declarations
|
||||
case *ast.ImportSpec:
|
||||
// Determine what wails has been imported as
|
||||
if x.Path.Value == `"github.com/wailsapp/wails/v2"` {
|
||||
wailsPkgVar = x.Name.Name
|
||||
}
|
||||
// Parse calls. We are looking for app.Bind() calls
|
||||
case *ast.CallExpr:
|
||||
f, ok := x.Fun.(*ast.SelectorExpr)
|
||||
if ok {
|
||||
n, ok := f.X.(*ast.Ident)
|
||||
if ok {
|
||||
//Check this is the Bind() call associated with the app variable
|
||||
if n.Name == app && f.Sel.Name == "Bind" {
|
||||
if len(x.Args) == 1 {
|
||||
ce, ok := x.Args[0].(*ast.CallExpr)
|
||||
if ok {
|
||||
n, ok := ce.Fun.(*ast.Ident)
|
||||
if ok {
|
||||
// We found a bind method using a function call
|
||||
// EG: app.Bind( newMyStruct() )
|
||||
boundMethods = append(boundMethods, n.Name)
|
||||
}
|
||||
} else {
|
||||
// We also want to check for Bind( &MyStruct{} )
|
||||
ue, ok := x.Args[0].(*ast.UnaryExpr)
|
||||
if ok {
|
||||
if ue.Op.String() == "&" {
|
||||
cl, ok := ue.X.(*ast.CompositeLit)
|
||||
if ok {
|
||||
t, ok := cl.Type.(*ast.Ident)
|
||||
if ok {
|
||||
// We have found Bind( &MyStruct{} )
|
||||
boundStructPointerLiterals = append(boundStructPointerLiterals, t.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Let's check when the user binds a struct,
|
||||
// rather than a struct pointer: Bind( MyStruct{} )
|
||||
// We do this to provide better hints to the user
|
||||
cl, ok := x.Args[0].(*ast.CompositeLit)
|
||||
if ok {
|
||||
t, ok := cl.Type.(*ast.Ident)
|
||||
if ok {
|
||||
boundStructLiterals.Add(t.Name)
|
||||
}
|
||||
} else {
|
||||
// Also check for when we bind a variable
|
||||
// myVariable := &MyStruct{}
|
||||
// app.Bind( myVariable )
|
||||
i, ok := x.Args[0].(*ast.Ident)
|
||||
if ok {
|
||||
boundVariables.Add(i.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We scan assignments for a number of reasons:
|
||||
// * Determine the variable containing the main application
|
||||
// * Determine the type of variables that get used in Bind()
|
||||
// * Determine the type of variables that get created with var := &MyStruct{}
|
||||
case *ast.AssignStmt:
|
||||
for _, rhs := range x.Rhs {
|
||||
ce, ok := rhs.(*ast.CallExpr)
|
||||
if ok {
|
||||
se, ok := ce.Fun.(*ast.SelectorExpr)
|
||||
if ok {
|
||||
i, ok := se.X.(*ast.Ident)
|
||||
if ok {
|
||||
// Have we found the wails package name?
|
||||
if i.Name == wailsPkgVar {
|
||||
// Check we are calling a function to create the app
|
||||
if se.Sel.Name == "CreateApp" || se.Sel.Name == "CreateAppWithOptions" {
|
||||
if len(x.Lhs) == 1 {
|
||||
i, ok := x.Lhs[0].(*ast.Ident)
|
||||
if ok {
|
||||
// Found the app variable name
|
||||
app = i.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Check for function assignment
|
||||
// a := newMyStruct()
|
||||
fe, ok := ce.Fun.(*ast.Ident)
|
||||
if ok {
|
||||
if len(x.Lhs) == 1 {
|
||||
i, ok := x.Lhs[0].(*ast.Ident)
|
||||
if ok {
|
||||
// Store the variable -> Function mapping
|
||||
// so we can later resolve the type
|
||||
variableFunctionDecls[i.Name] = fe.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Check for literal assignment of struct
|
||||
// EG: myvar := MyStruct{}
|
||||
ue, ok := rhs.(*ast.UnaryExpr)
|
||||
if ok {
|
||||
cl, ok := ue.X.(*ast.CompositeLit)
|
||||
if ok {
|
||||
t, ok := cl.Type.(*ast.Ident)
|
||||
if ok {
|
||||
if len(x.Lhs) == 1 {
|
||||
i, ok := x.Lhs[0].(*ast.Ident)
|
||||
if ok {
|
||||
variableStructDecls[i.Name] = t.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// We scan for functions to build up a list of function names
|
||||
// for a number of reasons:
|
||||
// * Determine which functions are struct methods that are bound
|
||||
// * Determine
|
||||
case *ast.FuncDecl:
|
||||
if x.Recv != nil {
|
||||
// This is a struct method
|
||||
for _, field := range x.Recv.List {
|
||||
se, ok := field.Type.(*ast.StarExpr)
|
||||
if ok {
|
||||
// This is a struct pointer method
|
||||
i, ok := se.X.(*ast.Ident)
|
||||
if ok {
|
||||
// We want to ignore Internal functions
|
||||
if internalMethods.Contains(x.Name.Name) {
|
||||
continue
|
||||
}
|
||||
// If we haven't already found this struct,
|
||||
// Create a placeholder in the cache
|
||||
parsedStruct := structCache[i.Name]
|
||||
if parsedStruct == nil {
|
||||
structCache[i.Name] = &ParsedStruct{
|
||||
Name: i.Name,
|
||||
}
|
||||
parsedStruct = structCache[i.Name]
|
||||
}
|
||||
|
||||
// If this method is Public
|
||||
if string(x.Name.Name[0]) == strings.ToUpper((string(x.Name.Name[0]))) {
|
||||
structMethod := &ParsedMethod{
|
||||
Struct: i.Name,
|
||||
Name: x.Name.Name,
|
||||
}
|
||||
// Check if the method has comments.
|
||||
// If so, save it with the parsed method
|
||||
if x.Doc != nil {
|
||||
for _, comment := range x.Doc.List {
|
||||
stringComment := strings.TrimPrefix(comment.Text, "//")
|
||||
structMethod.Comments = append(structMethod.Comments, strings.TrimSpace(stringComment))
|
||||
}
|
||||
}
|
||||
|
||||
// Save the input parameters
|
||||
if x.Type.Params != nil {
|
||||
for _, inputField := range x.Type.Params.List {
|
||||
t, ok := inputField.Type.(*ast.Ident)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
for _, name := range inputField.Names {
|
||||
structMethod.Inputs = append(structMethod.Inputs, &Parameter{Name: name.Name, Type: t.Name})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save the output parameters
|
||||
if x.Type.Results != nil {
|
||||
for _, outputField := range x.Type.Results.List {
|
||||
t, ok := outputField.Type.(*ast.Ident)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if len(outputField.Names) == 0 {
|
||||
structMethod.Returns = append(structMethod.Returns, &Parameter{Type: t.Name})
|
||||
} else {
|
||||
for _, name := range outputField.Names {
|
||||
structMethod.Returns = append(structMethod.Returns, &Parameter{Name: name.Name, Type: t.Name})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Append this method to the parsed struct
|
||||
parsedStruct.Methods = append(parsedStruct.Methods, structMethod)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// This is a function declaration
|
||||
// We care about its name and return type
|
||||
// This will allow us to resolve types later
|
||||
functionName := x.Name.Name
|
||||
|
||||
// Look for one that returns a single value
|
||||
if x.Type != nil && x.Type.Results != nil && x.Type.Results.List != nil {
|
||||
if len(x.Type.Results.List) == 1 {
|
||||
// Check for *struct
|
||||
t, ok := x.Type.Results.List[0].Type.(*ast.StarExpr)
|
||||
if ok {
|
||||
s, ok := t.X.(*ast.Ident)
|
||||
if ok {
|
||||
// println("*** Function", functionName, "found which returns: *"+s.Name)
|
||||
structPointerFunctionDecls[functionName] = s.Name
|
||||
}
|
||||
} else {
|
||||
// Check for functions that return a struct
|
||||
// This is to help us provide hints if the user binds a struct
|
||||
t, ok := x.Type.Results.List[0].Type.(*ast.Ident)
|
||||
if ok {
|
||||
// println("*** Function", functionName, "found which returns: "+t.Name)
|
||||
structFunctionDecls[functionName] = t.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
// spew.Dump(file)
|
||||
}
|
||||
}
|
||||
|
||||
/***** Update bound structs ******/
|
||||
|
||||
// Resolve bound Methods
|
||||
for _, method := range boundMethods {
|
||||
s, ok := structPointerFunctionDecls[method]
|
||||
if !ok {
|
||||
s, ok = structFunctionDecls[method]
|
||||
if !ok {
|
||||
println("Fatal: Bind statement using", method, "but cannot find", method, "declaration")
|
||||
} else {
|
||||
println("Fatal: Cannot bind struct using method `" + method + "` because it returns a struct (" + s + "). Return a pointer to " + s + " instead.")
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
structDefinition := structCache[s]
|
||||
if structDefinition == nil {
|
||||
println("Fatal: Bind statement using `"+method+"` but cannot find struct", s, "definition")
|
||||
os.Exit(1)
|
||||
}
|
||||
boundStructs[s] = structDefinition
|
||||
}
|
||||
|
||||
// Resolve bound vars
|
||||
for _, structLiteral := range boundStructPointerLiterals {
|
||||
s, ok := structCache[structLiteral]
|
||||
if !ok {
|
||||
println("Fatal: Bind statement using", structLiteral, "but cannot find", structLiteral, "declaration")
|
||||
os.Exit(1)
|
||||
}
|
||||
boundStructs[structLiteral] = s
|
||||
}
|
||||
|
||||
// Resolve bound variables
|
||||
boundVariables.Each(func(variable string) {
|
||||
v, ok := variableStructDecls[variable]
|
||||
if !ok {
|
||||
method, ok := variableFunctionDecls[variable]
|
||||
if !ok {
|
||||
println("Fatal: Bind statement using variable `" + variable + "` which does not resolve to a struct pointer")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Resolve function name
|
||||
v, ok = structPointerFunctionDecls[method]
|
||||
if !ok {
|
||||
v, ok = structFunctionDecls[method]
|
||||
if !ok {
|
||||
println("Fatal: Bind statement using", method, "but cannot find", method, "declaration")
|
||||
} else {
|
||||
println("Fatal: Cannot bind variable `" + variable + "` because it resolves to a struct (" + v + "). Return a pointer to " + v + " instead.")
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
s, ok := structCache[v]
|
||||
if !ok {
|
||||
println("Fatal: Bind statement using variable `" + variable + "` which resolves to a `" + v + "` but cannot find its declaration")
|
||||
os.Exit(1)
|
||||
}
|
||||
boundStructs[v] = s
|
||||
|
||||
})
|
||||
|
||||
// Check for struct literals
|
||||
boundStructLiterals.Each(func(structName string) {
|
||||
println("Fatal: Cannot bind struct using struct literal `" + structName + "{}`. Create a pointer to " + structName + " instead.")
|
||||
os.Exit(1)
|
||||
})
|
||||
|
||||
// Check for bound variables
|
||||
// boundVariables.Each(func(varName string) {
|
||||
// println("Fatal: Cannot bind struct using struct literal `" + structName + "{}`. Create a pointer to " + structName + " instead.")
|
||||
// })
|
||||
|
||||
// spew.Dump(boundStructs)
|
||||
// os.Exit(0)
|
||||
|
||||
// }
|
||||
// Inspect the AST and print all identifiers and literals.
|
||||
|
||||
println("export {")
|
||||
|
||||
noOfStructs := len(boundStructs)
|
||||
structCount := 0
|
||||
for _, s := range boundStructs {
|
||||
structCount++
|
||||
println()
|
||||
println(" " + s.Name + ": {")
|
||||
println()
|
||||
noOfMethods := len(s.Methods)
|
||||
for methodCount, m := range s.Methods {
|
||||
println(" /****************")
|
||||
for _, comment := range m.Comments {
|
||||
println(" *", comment)
|
||||
}
|
||||
if len(m.Comments) > 0 {
|
||||
println(" *")
|
||||
}
|
||||
inputNames := ""
|
||||
for _, input := range m.Inputs {
|
||||
println(" * @param {"+input.Type+"}", input.Name)
|
||||
inputNames += input.Name + ", "
|
||||
}
|
||||
print(" * @return Promise<")
|
||||
for _, output := range m.Returns {
|
||||
print(output.Type + "|")
|
||||
}
|
||||
println("Error>")
|
||||
println(" *")
|
||||
println(" ***/")
|
||||
if len(inputNames) > 2 {
|
||||
inputNames = inputNames[:len(inputNames)-2]
|
||||
}
|
||||
println(" ", m.Name+": function("+inputNames+") {")
|
||||
println(" return window.backend." + s.Name + "." + m.Name + "(" + inputNames + ");")
|
||||
print(" }")
|
||||
if methodCount < noOfMethods-1 {
|
||||
print(",")
|
||||
}
|
||||
println()
|
||||
println()
|
||||
}
|
||||
print(" }")
|
||||
if structCount < noOfStructs-1 {
|
||||
print(",")
|
||||
}
|
||||
println()
|
||||
}
|
||||
println()
|
||||
println("}")
|
||||
println()
|
||||
|
||||
}
|
||||
32
runtime.go
Normal file
32
runtime.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package wails
|
||||
|
||||
import (
|
||||
"github.com/wailsapp/wails/lib/interfaces"
|
||||
"github.com/wailsapp/wails/lib/logger"
|
||||
"github.com/wailsapp/wails/runtime"
|
||||
)
|
||||
|
||||
// CustomLogger type alias
|
||||
type CustomLogger = logger.CustomLogger
|
||||
|
||||
// Runtime is the Wails Runtime Interface, given to a user who has defined the WailsInit method
|
||||
type Runtime struct {
|
||||
Events *runtime.Events
|
||||
Log *runtime.Log
|
||||
Dialog *runtime.Dialog
|
||||
Window *runtime.Window
|
||||
Browser *runtime.Browser
|
||||
FileSystem *runtime.FileSystem
|
||||
}
|
||||
|
||||
// NewRuntime creates a new Runtime struct
|
||||
func NewRuntime(eventManager interfaces.EventManager, renderer interfaces.Renderer) *Runtime {
|
||||
return &Runtime{
|
||||
Events: runtime.NewEvents(eventManager),
|
||||
Log: runtime.NewLog(),
|
||||
Dialog: runtime.NewDialog(renderer),
|
||||
Window: runtime.NewWindow(renderer),
|
||||
Browser: runtime.NewBrowser(),
|
||||
FileSystem: runtime.NewFileSystem(),
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -15,7 +15,6 @@ import { NewBinding } from './bindings';
|
||||
import { Callback } from './calls';
|
||||
import { AddScript, InjectCSS } from './utils';
|
||||
import { AddIPCListener } from './ipc';
|
||||
import * as Store from './store';
|
||||
|
||||
// Initialise global if not already
|
||||
window.wails = window.wails || {};
|
||||
@@ -43,7 +42,6 @@ var runtime = {
|
||||
Heartbeat,
|
||||
Acknowledge,
|
||||
},
|
||||
Store,
|
||||
_: internal,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
_ __ _ __
|
||||
| | / /___ _(_) /____
|
||||
| | /| / / __ `/ / / ___/
|
||||
| |/ |/ / /_/ / / (__ )
|
||||
|__/|__/\__,_/_/_/____/
|
||||
The lightweight framework for web-like apps
|
||||
(c) Lea Anthony 2019-present
|
||||
*/
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
/**
|
||||
* Creates a new sync store with the given name and optional default value
|
||||
*
|
||||
* @export
|
||||
* @param {string} name
|
||||
* @param {*} optionalDefault
|
||||
*/
|
||||
export function New(name, optionalDefault) {
|
||||
|
||||
var data;
|
||||
|
||||
// Check we are initialised
|
||||
if( !window.wails) {
|
||||
throw Error('Wails is not initialised');
|
||||
}
|
||||
|
||||
// Store for the callbacks
|
||||
let callbacks = [];
|
||||
|
||||
// Subscribe to updates by providing a callback
|
||||
this.subscribe = (callback) => {
|
||||
callbacks.push(callback);
|
||||
};
|
||||
|
||||
// sets the store data to the provided `newdata` value
|
||||
this.set = (newdata) => {
|
||||
|
||||
data = newdata;
|
||||
|
||||
// Emit a notification to back end
|
||||
window.wails.Events.Emit('wails:sync:store:updatedbyfrontend:'+name, JSON.stringify(data));
|
||||
|
||||
// Notify callbacks
|
||||
callbacks.forEach( function(callback) {
|
||||
callback(data);
|
||||
});
|
||||
};
|
||||
|
||||
// update mutates the value in the store by calling the
|
||||
// provided method with the current value. The value returned
|
||||
// by the updater function will be set as the new store value
|
||||
this.update = (updater) => {
|
||||
var newValue = updater(data);
|
||||
this.set(newValue);
|
||||
};
|
||||
|
||||
// Setup event callback
|
||||
window.wails.Events.On('wails:sync:store:updatedbybackend:'+name, function(result) {
|
||||
|
||||
// Parse data
|
||||
result = JSON.parse(result);
|
||||
|
||||
// Todo: Potential preprocessing?
|
||||
|
||||
// Save data
|
||||
data = result;
|
||||
|
||||
// Notify callbacks
|
||||
callbacks.forEach( function(callback) {
|
||||
callback(data);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// Set to the optional default if set
|
||||
if( optionalDefault ) {
|
||||
this.set(optionalDefault);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
1103
runtime/js/package-lock.json
generated
1103
runtime/js/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -13,12 +13,10 @@ const Log = require('./log');
|
||||
const Browser = require('./browser');
|
||||
const Events = require('./events');
|
||||
const Init = require('./init');
|
||||
const Store = require('./store');
|
||||
|
||||
module.exports = {
|
||||
Log: Log,
|
||||
Browser: Browser,
|
||||
Events: Events,
|
||||
Init: Init,
|
||||
Store: Store,
|
||||
Init: Init
|
||||
};
|
||||
492
runtime/js/runtime/package-lock.json
generated
492
runtime/js/runtime/package-lock.json
generated
@@ -1,492 +0,0 @@
|
||||
{
|
||||
"name": "@wailsapp/runtime",
|
||||
"version": "1.1.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
||||
"dev": true
|
||||
},
|
||||
"camelcase": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
|
||||
"integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
|
||||
"dev": true
|
||||
},
|
||||
"cliui": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
|
||||
"integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"string-width": "^1.0.1",
|
||||
"strip-ansi": "^3.0.1",
|
||||
"wrap-ansi": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
|
||||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
|
||||
"dev": true
|
||||
},
|
||||
"decamelize": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
||||
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
|
||||
"dev": true
|
||||
},
|
||||
"dts-dom": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/dts-dom/-/dts-dom-3.6.0.tgz",
|
||||
"integrity": "sha512-on5jxTgt+A6r0Zyyz6ZRHXaAO7J1VPnOd6+AmvI1vH440AlAZZNc5rUHzgPuTjGlrVr1rOWQYNl7ZJK6rDohbw==",
|
||||
"dev": true
|
||||
},
|
||||
"dts-gen": {
|
||||
"version": "0.5.8",
|
||||
"resolved": "https://registry.npmjs.org/dts-gen/-/dts-gen-0.5.8.tgz",
|
||||
"integrity": "sha512-kIAV6dlHaF7r5J+tIuOC1BJls2P72YM0cyWQUR88zcJEpX2ccRZe+HmXLfkkvfPwjvSO3FEqUiyC8On/grx5qw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"dts-dom": "^3.6.0",
|
||||
"parse-git-config": "^1.1.1",
|
||||
"typescript": "^3.5.1",
|
||||
"yargs": "^4.8.1"
|
||||
}
|
||||
},
|
||||
"error-ex": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
|
||||
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-arrayish": "^0.2.1"
|
||||
}
|
||||
},
|
||||
"extend-shallow": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
|
||||
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-extendable": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"find-up": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
|
||||
"integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-exists": "^2.0.0",
|
||||
"pinkie-promise": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"fs-exists-sync": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz",
|
||||
"integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=",
|
||||
"dev": true
|
||||
},
|
||||
"get-caller-file": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
|
||||
"integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
|
||||
"dev": true
|
||||
},
|
||||
"git-config-path": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/git-config-path/-/git-config-path-1.0.1.tgz",
|
||||
"integrity": "sha1-bTP37WPbDQ4RgTFQO6s6ykfVRmQ=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"extend-shallow": "^2.0.1",
|
||||
"fs-exists-sync": "^0.1.0",
|
||||
"homedir-polyfill": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
|
||||
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
|
||||
"dev": true
|
||||
},
|
||||
"homedir-polyfill": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
|
||||
"integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"parse-passwd": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"hosted-git-info": {
|
||||
"version": "2.8.8",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
|
||||
"integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
|
||||
"dev": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
|
||||
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
|
||||
"dev": true
|
||||
},
|
||||
"invert-kv": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
|
||||
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
|
||||
"dev": true
|
||||
},
|
||||
"is-arrayish": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
|
||||
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
|
||||
"dev": true
|
||||
},
|
||||
"is-extendable": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
|
||||
"integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
|
||||
"dev": true
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
|
||||
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"is-utf8": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
|
||||
"integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
|
||||
"dev": true
|
||||
},
|
||||
"lcid": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
|
||||
"integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"invert-kv": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"load-json-file": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
|
||||
"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
"parse-json": "^2.2.0",
|
||||
"pify": "^2.0.0",
|
||||
"pinkie-promise": "^2.0.0",
|
||||
"strip-bom": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"lodash.assign": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
|
||||
"integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=",
|
||||
"dev": true
|
||||
},
|
||||
"normalize-package-data": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
|
||||
"integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"hosted-git-info": "^2.1.4",
|
||||
"resolve": "^1.10.0",
|
||||
"semver": "2 || 3 || 4 || 5",
|
||||
"validate-npm-package-license": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
|
||||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
|
||||
"dev": true
|
||||
},
|
||||
"os-locale": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
|
||||
"integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lcid": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"parse-git-config": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-1.1.1.tgz",
|
||||
"integrity": "sha1-06mYQxcTL1c5hxK7pDjhKVkN34w=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"extend-shallow": "^2.0.1",
|
||||
"fs-exists-sync": "^0.1.0",
|
||||
"git-config-path": "^1.0.1",
|
||||
"ini": "^1.3.4"
|
||||
}
|
||||
},
|
||||
"parse-json": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
|
||||
"integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"error-ex": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"parse-passwd": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
|
||||
"integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
|
||||
"dev": true
|
||||
},
|
||||
"path-exists": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
|
||||
"integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"pinkie-promise": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"path-parse": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
|
||||
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
|
||||
"dev": true
|
||||
},
|
||||
"path-type": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
|
||||
"integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
"pify": "^2.0.0",
|
||||
"pinkie-promise": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"pify": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
|
||||
"dev": true
|
||||
},
|
||||
"pinkie": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
|
||||
"integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
|
||||
"dev": true
|
||||
},
|
||||
"pinkie-promise": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
|
||||
"integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"pinkie": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"read-pkg": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
|
||||
"integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"load-json-file": "^1.0.0",
|
||||
"normalize-package-data": "^2.3.2",
|
||||
"path-type": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"read-pkg-up": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
|
||||
"integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"find-up": "^1.0.0",
|
||||
"read-pkg": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"require-directory": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
|
||||
"dev": true
|
||||
},
|
||||
"require-main-filename": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
|
||||
"integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
|
||||
"dev": true
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.17.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
|
||||
"integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-parse": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||
"dev": true
|
||||
},
|
||||
"set-blocking": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
|
||||
"dev": true
|
||||
},
|
||||
"spdx-correct": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
|
||||
"integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"spdx-expression-parse": "^3.0.0",
|
||||
"spdx-license-ids": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"spdx-exceptions": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
|
||||
"integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
|
||||
"dev": true
|
||||
},
|
||||
"spdx-expression-parse": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
|
||||
"integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"spdx-exceptions": "^2.1.0",
|
||||
"spdx-license-ids": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"spdx-license-ids": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
|
||||
"integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
|
||||
"dev": true
|
||||
},
|
||||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
"strip-ansi": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"strip-bom": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
|
||||
"integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-utf8": "^0.2.0"
|
||||
}
|
||||
},
|
||||
"typescript": {
|
||||
"version": "3.9.7",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz",
|
||||
"integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==",
|
||||
"dev": true
|
||||
},
|
||||
"validate-npm-package-license": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
|
||||
"integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"spdx-correct": "^3.0.0",
|
||||
"spdx-expression-parse": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"which-module": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
|
||||
"integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
|
||||
"dev": true
|
||||
},
|
||||
"window-size": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz",
|
||||
"integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=",
|
||||
"dev": true
|
||||
},
|
||||
"wrap-ansi": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
|
||||
"integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"string-width": "^1.0.1",
|
||||
"strip-ansi": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"y18n": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
|
||||
"integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=",
|
||||
"dev": true
|
||||
},
|
||||
"yargs": {
|
||||
"version": "4.8.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz",
|
||||
"integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cliui": "^3.2.0",
|
||||
"decamelize": "^1.1.1",
|
||||
"get-caller-file": "^1.0.1",
|
||||
"lodash.assign": "^4.0.3",
|
||||
"os-locale": "^1.4.0",
|
||||
"read-pkg-up": "^1.0.1",
|
||||
"require-directory": "^2.1.1",
|
||||
"require-main-filename": "^1.0.1",
|
||||
"set-blocking": "^2.0.0",
|
||||
"string-width": "^1.0.1",
|
||||
"which-module": "^1.0.0",
|
||||
"window-size": "^0.2.0",
|
||||
"y18n": "^3.2.1",
|
||||
"yargs-parser": "^2.4.1"
|
||||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz",
|
||||
"integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"camelcase": "^3.0.0",
|
||||
"lodash.assign": "^4.0.6"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@wailsapp/runtime",
|
||||
"version": "1.1.0",
|
||||
"version": "1.0.11",
|
||||
"description": "Wails Javascript runtime library",
|
||||
"main": "main.js",
|
||||
"types": "runtime.d.ts",
|
||||
@@ -25,4 +25,4 @@
|
||||
"devDependencies": {
|
||||
"dts-gen": "^0.5.8"
|
||||
}
|
||||
}
|
||||
}
|
||||
3
runtime/js/runtime/runtime.d.ts
vendored
3
runtime/js/runtime/runtime.d.ts
vendored
@@ -21,9 +21,6 @@ declare const wailsapp__runtime: {
|
||||
Info(message: string): void;
|
||||
Warning(message: string): void;
|
||||
};
|
||||
Store: {
|
||||
New(name: string, optionalDefault?: any): any;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
_ __ _ __
|
||||
| | / /___ _(_) /____
|
||||
| | /| / / __ `/ / / ___/
|
||||
| |/ |/ / /_/ / / (__ )
|
||||
|__/|__/\__,_/_/_/____/
|
||||
The lightweight framework for web-like apps
|
||||
(c) Lea Anthony 2019-present
|
||||
*/
|
||||
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
|
||||
/**
|
||||
* Create a new Store with the given name and optional default value
|
||||
*
|
||||
* @export
|
||||
* @param {string} name
|
||||
* @param {*} optionalDefault
|
||||
*/
|
||||
function New(name, optionalDefault) {
|
||||
return window.wails.Store.New(name, optionalDefault);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
New: New,
|
||||
};
|
||||
@@ -1,29 +0,0 @@
|
||||
package runtime
|
||||
|
||||
import "github.com/wailsapp/wails/lib/interfaces"
|
||||
|
||||
// Runtime is the Wails Runtime Interface, given to a user who has defined the WailsInit method
|
||||
type Runtime struct {
|
||||
Events *Events
|
||||
Log *Log
|
||||
Dialog *Dialog
|
||||
Window *Window
|
||||
Browser *Browser
|
||||
FileSystem *FileSystem
|
||||
Store *StoreProvider
|
||||
}
|
||||
|
||||
// NewRuntime creates a new Runtime struct
|
||||
func NewRuntime(eventManager interfaces.EventManager, renderer interfaces.Renderer) *Runtime {
|
||||
result := &Runtime{
|
||||
Events: NewEvents(eventManager),
|
||||
Log: NewLog(),
|
||||
Dialog: NewDialog(renderer),
|
||||
Window: NewWindow(renderer),
|
||||
Browser: NewBrowser(),
|
||||
FileSystem: NewFileSystem(),
|
||||
}
|
||||
// We need a reference to itself
|
||||
result.Store = NewStoreProvider(result)
|
||||
return result
|
||||
}
|
||||
248
runtime/store.go
248
runtime/store.go
@@ -1,248 +0,0 @@
|
||||
// Package runtime contains all the methods and data structures related to the
|
||||
// runtime library of Wails. This includes both Go and JS runtimes.
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"reflect"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Options defines the optional data that may be used
|
||||
// when creating a Store
|
||||
type Options struct {
|
||||
|
||||
// The name of the store
|
||||
Name string
|
||||
|
||||
// The runtime to attach the store to
|
||||
Runtime *Runtime
|
||||
|
||||
// Indicates if notifying Go listeners should be notified of updates
|
||||
// synchronously (on the current thread) or asynchronously using
|
||||
// goroutines
|
||||
NotifySynchronously bool
|
||||
}
|
||||
|
||||
// StoreProvider is a struct that creates Stores
|
||||
type StoreProvider struct {
|
||||
runtime *Runtime
|
||||
}
|
||||
|
||||
// NewStoreProvider creates new stores using the provided Runtime reference.
|
||||
func NewStoreProvider(runtime *Runtime) *StoreProvider {
|
||||
return &StoreProvider{
|
||||
runtime: runtime,
|
||||
}
|
||||
}
|
||||
|
||||
// Store is where we keep named data
|
||||
type Store struct {
|
||||
name string
|
||||
data reflect.Value
|
||||
dataType reflect.Type
|
||||
eventPrefix string
|
||||
callbacks []func(interface{})
|
||||
runtime *Runtime
|
||||
notifySynchronously bool
|
||||
|
||||
// Lock
|
||||
mux sync.Mutex
|
||||
|
||||
// Error handler
|
||||
errorHandler func(error)
|
||||
}
|
||||
|
||||
// New creates a new store
|
||||
func (p *StoreProvider) New(name string, defaultValue interface{}) *Store {
|
||||
|
||||
dataType := reflect.TypeOf(defaultValue)
|
||||
|
||||
result := Store{
|
||||
name: name,
|
||||
runtime: p.runtime,
|
||||
data: reflect.ValueOf(defaultValue),
|
||||
dataType: dataType,
|
||||
}
|
||||
|
||||
// Setup the sync listener
|
||||
result.setupListener()
|
||||
|
||||
return &result
|
||||
}
|
||||
|
||||
// OnError takes a function that will be called
|
||||
// whenever an error occurs
|
||||
func (s *Store) OnError(callback func(error)) {
|
||||
s.errorHandler = callback
|
||||
}
|
||||
|
||||
// Processes the updates sent by the front end
|
||||
func (s *Store) processUpdatedData(data string) error {
|
||||
|
||||
// Decode incoming data
|
||||
var rawdata json.RawMessage
|
||||
d := json.NewDecoder(bytes.NewBufferString(data))
|
||||
err := d.Decode(&rawdata)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create a new instance of our data and unmarshal
|
||||
// the received value into it
|
||||
newData := reflect.New(s.dataType).Interface()
|
||||
err = json.Unmarshal(rawdata, &newData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Lock mutex for writing
|
||||
s.mux.Lock()
|
||||
|
||||
// Handle nulls
|
||||
if newData == nil {
|
||||
s.data = reflect.Zero(s.dataType)
|
||||
} else {
|
||||
// Store the resultant value in the data store
|
||||
s.data = reflect.ValueOf(newData).Elem()
|
||||
}
|
||||
|
||||
// Unlock mutex
|
||||
s.mux.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Setup listener for front end changes
|
||||
func (s *Store) setupListener() {
|
||||
|
||||
// Listen for updates from the front end
|
||||
s.runtime.Events.On("wails:sync:store:updatedbyfrontend:"+s.name, func(data ...interface{}) {
|
||||
|
||||
// Process the incoming data
|
||||
err := s.processUpdatedData(data[0].(string))
|
||||
|
||||
if err != nil {
|
||||
if s.errorHandler != nil {
|
||||
s.errorHandler(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Notify listeners
|
||||
s.notify()
|
||||
})
|
||||
}
|
||||
|
||||
// notify the listeners of the current data state
|
||||
func (s *Store) notify() {
|
||||
|
||||
// Execute callbacks
|
||||
for _, callback := range s.callbacks {
|
||||
|
||||
if s.notifySynchronously {
|
||||
callback(s.data)
|
||||
} else {
|
||||
go callback(s.data)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Set will update the data held by the store
|
||||
// and notify listeners of the change
|
||||
func (s *Store) Set(data interface{}) error {
|
||||
|
||||
inType := reflect.TypeOf(data)
|
||||
|
||||
if inType != s.dataType {
|
||||
return fmt.Errorf("invalid data given in Store.Set(). Expected %s, got %s", s.dataType.String(), inType.String())
|
||||
}
|
||||
|
||||
// Save data
|
||||
s.mux.Lock()
|
||||
s.data = reflect.ValueOf(data)
|
||||
s.mux.Unlock()
|
||||
|
||||
// Stringify data
|
||||
newdata, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
if s.errorHandler != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Emit event to front end
|
||||
s.runtime.Events.Emit("wails:sync:store:updatedbybackend:"+s.name, string(newdata))
|
||||
|
||||
// Notify subscribers
|
||||
s.notify()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Subscribe will subscribe to updates to the store by
|
||||
// providing a callback. Any updates to the store are sent
|
||||
// to the callback
|
||||
func (s *Store) Subscribe(callback func(interface{})) {
|
||||
s.callbacks = append(s.callbacks, callback)
|
||||
}
|
||||
|
||||
// updaterCheck ensures the given function to Update() is
|
||||
// of the correct signature. Absolutely cannot wait for
|
||||
// generics to land rather than writing this nonsense.
|
||||
func (s *Store) updaterCheck(updater interface{}) error {
|
||||
|
||||
// Get type
|
||||
updaterType := reflect.TypeOf(updater)
|
||||
|
||||
// Check updater is a function
|
||||
if updaterType.Kind() != reflect.Func {
|
||||
return fmt.Errorf("invalid value given to store.Update(). Expected 'func(%s) %s'", s.dataType.String(), s.dataType.String())
|
||||
}
|
||||
|
||||
// Check input param
|
||||
if updaterType.NumIn() != 1 {
|
||||
return fmt.Errorf("invalid number of parameters given in updater function. Expected 1")
|
||||
}
|
||||
|
||||
// Check input data type
|
||||
if updaterType.In(0) != s.dataType {
|
||||
return fmt.Errorf("invalid type for input parameter given in updater function. Expected %s, got %s", s.dataType.String(), updaterType.In(0))
|
||||
}
|
||||
|
||||
// Check output param
|
||||
if updaterType.NumOut() != 1 {
|
||||
return fmt.Errorf("invalid number of return parameters given in updater function. Expected 1")
|
||||
}
|
||||
|
||||
// Check output data type
|
||||
if updaterType.Out(0) != s.dataType {
|
||||
return fmt.Errorf("invalid type for return parameter given in updater function. Expected %s, got %s", s.dataType.String(), updaterType.Out(0))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Update takes a function that is passed the current state.
|
||||
// The result of that function is then set as the new state
|
||||
// of the store. This will notify listeners of the change
|
||||
func (s *Store) Update(updater interface{}) {
|
||||
|
||||
err := s.updaterCheck(updater)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Build args
|
||||
args := []reflect.Value{s.data}
|
||||
|
||||
// Make call
|
||||
results := reflect.ValueOf(updater).Call(args)
|
||||
|
||||
// We will only have 1 result. Set the store to it
|
||||
s.Set(results[0].Interface())
|
||||
}
|
||||
Reference in New Issue
Block a user