mirror of
https://github.com/taigrr/wails.git
synced 2026-04-02 13:19:00 -07:00
Compare commits
121 Commits
runtime-re
...
migrate-to
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0367bdf8be | ||
|
|
315ef5f7ea | ||
|
|
594efcb79e | ||
|
|
8c96bba1f9 | ||
|
|
1d785d7d40 | ||
|
|
cfc0cc053b | ||
|
|
24530d9da4 | ||
|
|
d572418ec3 | ||
|
|
8c7480d277 | ||
|
|
96fc70df26 | ||
|
|
1c8d4c902a | ||
|
|
08fc1d53d0 | ||
|
|
6c5d5e40f4 | ||
|
|
3f1dfe931c | ||
|
|
cb850c9653 | ||
|
|
8d8f47363a | ||
|
|
d399b7580d | ||
|
|
1b04b71254 | ||
|
|
0b19ad1427 | ||
|
|
9aca99911e | ||
|
|
a7f61e335e | ||
|
|
9fff0a513e | ||
|
|
f453be12c8 | ||
|
|
20428b0407 | ||
|
|
7fd5b77cbe | ||
|
|
d2cac50f93 | ||
|
|
00f1f82520 | ||
|
|
02fbb14e34 | ||
|
|
f961659ada | ||
|
|
93942111bc | ||
|
|
dc5a68acce | ||
|
|
12ff0f8c97 | ||
|
|
c375c281ee | ||
|
|
7d86b0f7c4 | ||
|
|
990f7dd06c | ||
|
|
0b6f256d55 | ||
|
|
694f80434a | ||
|
|
0a57fa4035 | ||
|
|
099967ae94 | ||
|
|
718bb1b852 | ||
|
|
af1a1a2498 | ||
|
|
cc0617d247 | ||
|
|
99a3f87cef | ||
|
|
1ccdb1bc4e | ||
|
|
62b1967e45 | ||
|
|
c10303e7c0 | ||
|
|
4a61584827 | ||
|
|
cf249ba836 | ||
|
|
08fe7b64d6 | ||
|
|
77939ea414 | ||
|
|
468394d03c | ||
|
|
dc87699a1e | ||
|
|
36e906507d | ||
|
|
a5f9688708 | ||
|
|
880f900e51 | ||
|
|
349306cf73 | ||
|
|
f140697857 | ||
|
|
3d9e9a1342 | ||
|
|
1a82406d2b | ||
|
|
26ff8df7e5 | ||
|
|
54b4b157b3 | ||
|
|
add7e89097 | ||
|
|
b7dae216df | ||
|
|
0b9d093d6c | ||
|
|
7f282ad071 | ||
|
|
d6ed583e07 | ||
|
|
930cab2d9d | ||
|
|
ae41f33dcc | ||
|
|
5af6b7cafe | ||
|
|
68ac3763d0 | ||
|
|
cdc66b556e | ||
|
|
3ff16322c2 | ||
|
|
d60066a0b1 | ||
|
|
9d6ebf0fd4 | ||
|
|
839815e2fb | ||
|
|
846fe479bf | ||
|
|
62f7070e0c | ||
|
|
dd418b36c2 | ||
|
|
f4f04f2199 | ||
|
|
3a7514bbdc | ||
|
|
213f07fed4 | ||
|
|
ed3ed8aa18 | ||
|
|
d038dca37c | ||
|
|
bb86d770a1 | ||
|
|
33daa8621e | ||
|
|
6c124fcff4 | ||
|
|
45833574b3 | ||
|
|
5cb00eb481 | ||
|
|
e2105331c1 | ||
|
|
21d2383e63 | ||
|
|
6c945a4eed | ||
|
|
6c8d34dfd3 | ||
|
|
b9b42c059e | ||
|
|
3f657b34cf | ||
|
|
6e81a36ada | ||
|
|
ddec01a429 | ||
|
|
21fdb3be7d | ||
|
|
c1a13ab6d0 | ||
|
|
750a02efc6 | ||
|
|
5e047debfc | ||
|
|
9cac336708 | ||
|
|
827c2b9a95 | ||
|
|
b36a3c4abb | ||
|
|
0bac205565 | ||
|
|
67a8ad8e12 | ||
|
|
9de2f66f50 | ||
|
|
9370030ff3 | ||
|
|
e38d6e7ef0 | ||
|
|
2f21fc3575 | ||
|
|
63e73f5f64 | ||
|
|
e1adc1ba49 | ||
|
|
030e911ea4 | ||
|
|
d2f114e44e | ||
|
|
700d3f84d3 | ||
|
|
1d49042013 | ||
|
|
8671b1e6cf | ||
|
|
517d6c44ec | ||
|
|
a082a659ea | ||
|
|
083153efc9 | ||
|
|
65a2560153 | ||
|
|
29535c10a3 |
@@ -1 +1 @@
|
||||
runtime/js/dist/wails.js
|
||||
runtime/assets/default.html
|
||||
@@ -1,7 +1,8 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true
|
||||
"es6": true,
|
||||
"node": true,
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"parserOptions": {
|
||||
|
||||
19
.github/stale.yml
vendored
Normal file
19
.github/stale.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 30
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
- onhold
|
||||
- inprogress
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: wontfix
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -16,4 +16,4 @@ examples/**/example*
|
||||
cmd/wails/wails
|
||||
.DS_Store
|
||||
tmp
|
||||
node_modules
|
||||
node_modules/
|
||||
7
.vscode/launch.json
vendored
7
.vscode/launch.json
vendored
@@ -4,6 +4,13 @@
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Test cmd package",
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"mode": "test",
|
||||
"program": "${workspaceFolder}/cmd/"
|
||||
},
|
||||
{
|
||||
"name": "Wails Init",
|
||||
"type": "go",
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
|
||||
2019-07-20 **v0.17.6-pre**
|
||||
* Significant refactor of runtime
|
||||
* Removed wailsbridge file - now a unified approach taken
|
||||
* Fixed React on Windows - Thanks [Florian Didran](https://github.com/fdidron)!
|
||||
|
||||
2019-06-18 **v0.16.0**
|
||||
* React template FTW! - Thanks [admin_3.exe](https://github.com/bh90210)!
|
||||
* Updated contributors
|
||||
|
||||
@@ -6,6 +6,7 @@ Wails is what it is because of the time and effort given by these great people.
|
||||
* [Qais Patankar](https://github.com/qaisjp)
|
||||
* [Anthony Lee](https://github.com/alee792)
|
||||
* [Adrian Lanzafame](https://github.com/lanzafame)
|
||||
* [Mattn](https://github.com/mattn)
|
||||
* [0xflotus](https://github.com/0xflotus)
|
||||
* [Michael D Henderson](https://github.com/mdhender)
|
||||
* [fred2104](https://github.com/fishfishfish2104)
|
||||
@@ -14,3 +15,8 @@ Wails is what it is because of the time and effort given by these great people.
|
||||
* [admin_3.exe](https://github.com/bh90210)
|
||||
* [iceleo-com](https://github.com/iceleo-com)
|
||||
* [fallendusk](https://github.com/fallendusk)
|
||||
* [Florian Didran](https://github.com/fdidron)
|
||||
* [Nikolai Zimmermann](https://github.com/Chronophylos)
|
||||
* [Toyam Cox](https://github.com/Vaelatern)
|
||||
* [Robin Eklind](https://github.com/mewmew)
|
||||
* [Kris Raney](https://github.com/kraney)
|
||||
|
||||
38
README.md
38
README.md
@@ -8,9 +8,10 @@
|
||||
<a href="http://godoc.org/github.com/wailsapp/wails"><img src="https://img.shields.io/badge/godoc-reference-blue.svg"/></a>
|
||||
<a href="https://www.codefactor.io/repository/github/wailsapp/wails"><img src="https://www.codefactor.io/repository/github/wailsapp/wails/badge" alt="CodeFactor" /></a>
|
||||
<a href="https://github.com/wailsapp/wails/issues"><img src="https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat" alt="CodeFactor" /></a>
|
||||
<a href="https://app.fossa.io/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_shield" alt="FOSSA Status"><img src="https://app.fossa.io/api/projects/git%2Bgithub.com%2Fwailsapp%2Fwails.svg?type=shield"/></a>
|
||||
<a href="https://houndci.com"><img src="https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg"/></a>
|
||||
<a href="https://github.com/avelino/awesome-go" rel="nofollow"><img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome"></a>
|
||||
<a href="https://dashboard.guardrails.io/default/gh/wailsapp/wails"><img src="https://badges.guardrails.io/wailsapp/wails.svg?token=53657bc22ec360d7673c894fdd70568e918ec581d10d84427ed4de5fe1eeff1a"></a>
|
||||
<a href="https://dev.azure.com/leaanthony/Wails/_build/latest?definitionId=1&branchName=master" rel="nofollow"><img src="https://dev.azure.com/leaanthony/Wails/_apis/build/status/wailsapp.wails?branchName=master" alt="Pipelines"></a>
|
||||
</p>
|
||||
|
||||
The traditional method of providing web interfaces to Go programs is via a built-in web server. Wails offers a different approach: it provides the ability to wrap both Go code and a web frontend into a single binary. Tools are provided to make this easy for you by handling project creation, compilation and bundling. All you have to do is get creative!
|
||||
@@ -46,19 +47,41 @@ Make sure you have the xcode command line tools installed. This can be done by r
|
||||
|
||||
### Linux
|
||||
|
||||
#### Ubuntu 18.04, Debian 9, Zorin 15
|
||||
#### Debian/Ubuntu
|
||||
|
||||
`sudo apt install pkg-config build-essential libgtk-3-dev libwebkit2gtk-4.0-dev`
|
||||
`sudo apt install libgtk-3-dev libwebkit2gtk-4.0-dev`
|
||||
|
||||
_Debian: 8, 9, 10_
|
||||
|
||||
_Ubuntu: 16.04, 18.04, 19.04_
|
||||
|
||||
_Also succesfully tested on: Zorin 15, Parrot 4.7, Linuxmint 19, Elementary 5, Kali, Neon_
|
||||
|
||||
#### Arch Linux
|
||||
|
||||
`sudo pacman -S webkit2gtk gtk3`
|
||||
|
||||
#### Red Hat Based Distros
|
||||
_Also succesfully test on: Manjaro & ArcoLinux_
|
||||
|
||||
`sudo yum install webkit2gtk-devel gtk3-devel`
|
||||
#### Centos
|
||||
|
||||
Note: If you have successfully installed these dependencies on a different flavour of Linux, please consider submitting a PR.
|
||||
`sudo yum install webkitgtk3-devel gtk3-devel`
|
||||
|
||||
_CentOS 6, 7_
|
||||
|
||||
#### Fedora
|
||||
|
||||
`sudo yum install webkit2gtk3-devel gtk3-devel`
|
||||
|
||||
_Fedora 29, 30_
|
||||
|
||||
#### VoidLinux & VoidLinux-musl
|
||||
|
||||
`xbps-install gtk+3-devel webkit2gtk-devel`
|
||||
|
||||
#### Gentoo
|
||||
|
||||
`sudo emerge gtk+:3 webkit-gtk`
|
||||
|
||||
### Windows
|
||||
|
||||
@@ -122,3 +145,6 @@ This project was mainly coded to the following albums:
|
||||
* [Maxthor - Another World](https://open.spotify.com/album/3tklE2Fgw1hCIUstIwPBJF)
|
||||
* [Alun Tan Lan - Y Distawrwydd](https://open.spotify.com/album/0c32OywcLpdJCWWMC6vB8v)
|
||||
|
||||
## Licensing
|
||||
|
||||
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_large)
|
||||
|
||||
70
app.go
70
app.go
@@ -1,14 +1,17 @@
|
||||
package wails
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
"github.com/syossan27/tebata"
|
||||
"github.com/wailsapp/wails/cmd"
|
||||
"github.com/wailsapp/wails/lib/logger"
|
||||
"github.com/wailsapp/wails/runtime/go/runtime"
|
||||
"github.com/wailsapp/wails/lib/renderer"
|
||||
"github.com/wailsapp/wails/lib/binding"
|
||||
"github.com/wailsapp/wails/lib/ipc"
|
||||
"github.com/wailsapp/wails/lib/event"
|
||||
"github.com/wailsapp/wails/lib/interfaces"
|
||||
"github.com/wailsapp/wails/lib/ipc"
|
||||
"github.com/wailsapp/wails/lib/logger"
|
||||
"github.com/wailsapp/wails/lib/renderer"
|
||||
)
|
||||
|
||||
// -------------------------------- Compile time Flags ------------------------------
|
||||
@@ -20,15 +23,15 @@ var BuildMode = cmd.BuildModeProd
|
||||
|
||||
// App defines the main application struct
|
||||
type App struct {
|
||||
config *AppConfig // The Application configuration object
|
||||
cli *cmd.Cli // In debug mode, we have a cli
|
||||
renderer interfaces.Renderer // The renderer is what we will render the app to
|
||||
logLevel string // The log level of the app
|
||||
ipc interfaces.IPCManager // Handles the IPC calls
|
||||
log *logger.CustomLogger // Logger
|
||||
bindingManager interfaces.BindingManager // Handles binding of Go code to renderer
|
||||
eventManager interfaces.EventManager // Handles all the events
|
||||
runtime interfaces.Runtime // The runtime object for registered structs
|
||||
config *AppConfig // The Application configuration object
|
||||
cli *cmd.Cli // In debug mode, we have a cli
|
||||
renderer interfaces.Renderer // The renderer is what we will render the app to
|
||||
logLevel string // The log level of the app
|
||||
ipc interfaces.IPCManager // Handles the IPC calls
|
||||
log *logger.CustomLogger // Logger
|
||||
bindingManager interfaces.BindingManager // Handles binding of Go code to renderer
|
||||
eventManager interfaces.EventManager // Handles all the events
|
||||
runtime interfaces.Runtime // The runtime object for registered structs
|
||||
}
|
||||
|
||||
// CreateApp creates the application window with the given configuration
|
||||
@@ -67,6 +70,7 @@ func CreateApp(optionalConfig ...*AppConfig) *App {
|
||||
|
||||
// Run the app
|
||||
func (a *App) Run() error {
|
||||
|
||||
if BuildMode != cmd.BuildModeProd {
|
||||
return a.cli.Run()
|
||||
}
|
||||
@@ -87,9 +91,9 @@ func (a *App) start() error {
|
||||
// Log starup
|
||||
a.log.Info("Starting")
|
||||
|
||||
// Check if we are to run in headless mode
|
||||
// Check if we are to run in bridge mode
|
||||
if BuildMode == cmd.BuildModeBridge {
|
||||
a.renderer = &renderer.Headless{}
|
||||
a.renderer = &renderer.Bridge{}
|
||||
}
|
||||
|
||||
// Initialise the renderer
|
||||
@@ -98,6 +102,13 @@ func (a *App) start() error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Start signal handler
|
||||
t := tebata.New(os.Interrupt, os.Kill, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL)
|
||||
t.Reserve(func() {
|
||||
a.log.Debug("SIGNAL CAUGHT! Starting Shutdown")
|
||||
a.renderer.Close()
|
||||
})
|
||||
|
||||
// Start event manager and give it our renderer
|
||||
a.eventManager.Start(a.renderer)
|
||||
|
||||
@@ -105,7 +116,7 @@ func (a *App) start() error {
|
||||
a.ipc.Start(a.eventManager, a.bindingManager)
|
||||
|
||||
// Create the runtime
|
||||
a.runtime = runtime.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)
|
||||
@@ -113,8 +124,33 @@ func (a *App) start() error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Defer the shutdown
|
||||
defer a.shutdown()
|
||||
|
||||
// Run the renderer
|
||||
return a.renderer.Run()
|
||||
err = a.renderer.Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// shutdown the app
|
||||
func (a *App) shutdown() {
|
||||
// Make sure this is only called once
|
||||
a.log.Debug("Shutting down")
|
||||
|
||||
// Shutdown Binding Manager
|
||||
a.bindingManager.Shutdown()
|
||||
|
||||
// Shutdown IPC Manager
|
||||
a.ipc.Shutdown()
|
||||
|
||||
// Shutdown Event Manager
|
||||
a.eventManager.Shutdown()
|
||||
|
||||
a.log.Debug("Cleanly Shutdown")
|
||||
}
|
||||
|
||||
// Bind allows the user to bind the given object
|
||||
|
||||
138
azure-pipelines.yaml
Normal file
138
azure-pipelines.yaml
Normal file
@@ -0,0 +1,138 @@
|
||||
# avoid double trigger by applying some rules
|
||||
# start a pipeline when push to 'master' branch
|
||||
trigger:
|
||||
- master
|
||||
# or when pull request on 'develop' branch
|
||||
pr:
|
||||
- develop
|
||||
|
||||
# for now there is only one stage 'Build'
|
||||
# in the future we could use multistage strategy for releases
|
||||
stages:
|
||||
- stage: Build
|
||||
|
||||
# there are 3 jobs
|
||||
# one for each os
|
||||
jobs:
|
||||
- deployment: Linux
|
||||
displayName: Lin
|
||||
variables:
|
||||
GOPATH: '$(Agent.BuildDirectory)/gopath' # Go workspace path
|
||||
GOROOT: '$(Agent.BuildDirectory)/go' # Go installation path
|
||||
GOBIN: '$(GOPATH)/bin' # Go binaries path
|
||||
GOMODULE: 'on'
|
||||
modulePath: '$(Agent.BuildDirectory)/wails' # Path to the module's code
|
||||
pool:
|
||||
vmImage: 'Ubuntu-16.04'
|
||||
environment: 'linux-dev'
|
||||
strategy:
|
||||
runOnce:
|
||||
deploy:
|
||||
steps:
|
||||
- checkout: self # self represents the repo where the initial Pipelines YAML file was found
|
||||
clean: true # whether to fetch clean each time
|
||||
path: wails # path to check out source code, relative to the agent's build directory (e.g. \_work\1)
|
||||
# go version 1.12.7
|
||||
- script: |
|
||||
wget "https://storage.googleapis.com/golang/go1.12.7.linux-amd64.tar.gz" --output-document "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
|
||||
tar -C '$(Agent.BuildDirectory)' -xzf "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
|
||||
displayName: 'Install Go 1.12.7 Linux'
|
||||
- script: |
|
||||
mkdir -p '$(GOBIN)'
|
||||
mkdir -p '$(GOPATH)/pkg'
|
||||
mkdir -p '$(GOROOT)'
|
||||
shopt -s extglob
|
||||
shopt -s dotglob
|
||||
echo '##vso[task.prependpath]$(GOBIN)'
|
||||
echo '##vso[task.prependpath]$(GOROOT)/bin'
|
||||
displayName: 'Set up the Go workspace'
|
||||
- script: |
|
||||
go version
|
||||
go get -v -d ./...
|
||||
cd cmd/wails
|
||||
go install
|
||||
workingDirectory: '$(modulePath)'
|
||||
displayName: 'Get dependencies, then build'
|
||||
- script: |
|
||||
wails version
|
||||
workingDirectory: '$(modulePath)'
|
||||
displayName: 'Check we have output'
|
||||
|
||||
- deployment: Mac
|
||||
displayName: Mac
|
||||
variables:
|
||||
GOPATH: '$(Agent.BuildDirectory)/gopath' # Go workspace path
|
||||
GOROOT: '$(Agent.BuildDirectory)/go' # Go installation path
|
||||
GOBIN: '$(GOPATH)/bin' # Go binaries path
|
||||
GOMODULE: 'on'
|
||||
modulePath: '$(Agent.BuildDirectory)/wails' # Path to the module's code
|
||||
pool:
|
||||
vmImage: 'macOS-10.14'
|
||||
environment: 'mac-dev'
|
||||
strategy:
|
||||
runOnce:
|
||||
deploy:
|
||||
steps:
|
||||
- checkout: self # self represents the repo where the initial Pipelines YAML file was found
|
||||
clean: true # whether to fetch clean each time
|
||||
path: wails # path to check out source code, relative to the agent's build directory (e.g. \_work\1)
|
||||
# go version 1.12.7
|
||||
- script: |
|
||||
wget "https://storage.googleapis.com/golang/go1.12.7.darwin-amd64.tar.gz" --output-document "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
|
||||
tar -C '$(Agent.BuildDirectory)' -xzf "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
|
||||
displayName: 'Install Go 1.12.7 Linux'
|
||||
- script: |
|
||||
mkdir -p '$(GOBIN)'
|
||||
mkdir -p '$(GOPATH)/pkg'
|
||||
mkdir -p '$(GOROOT)'
|
||||
shopt -s extglob
|
||||
shopt -s dotglob
|
||||
echo '##vso[task.prependpath]$(GOBIN)'
|
||||
echo '##vso[task.prependpath]$(GOROOT)/bin'
|
||||
displayName: 'Set up the Go workspace'
|
||||
- script: |
|
||||
go version
|
||||
go get -v -d ./...
|
||||
cd cmd/wails
|
||||
go install
|
||||
workingDirectory: '$(modulePath)'
|
||||
displayName: 'Get dependencies, then build'
|
||||
- script: |
|
||||
wails version
|
||||
workingDirectory: '$(modulePath)'
|
||||
displayName: 'Check we have output'
|
||||
|
||||
- deployment: Win
|
||||
displayName: Win
|
||||
variables:
|
||||
GOMODULE: 'on'
|
||||
modulePath: '$(Agent.BuildDirectory)/wails' # Path to the module's code
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
environment: 'win-dev'
|
||||
strategy:
|
||||
runOnce:
|
||||
deploy:
|
||||
steps:
|
||||
- checkout: self # self represents the repo where the initial Pipelines YAML file was found
|
||||
clean: true # whether to fetch clean each time
|
||||
path: wails # path to check out source code, relative to the agent's build directory (e.g. \_work\1)
|
||||
# Go tool installer
|
||||
# Find in cache or download a specific version of Go and add it to the PATH
|
||||
- task: GoTool@0
|
||||
inputs:
|
||||
version: '1.12.7'
|
||||
goPath: '$(Agent.BuildDirectory)/go'
|
||||
goBin: '$(Agent.BuildDirectory)/go/bin'
|
||||
displayName: 'Set up the Go workspace'
|
||||
- script: |
|
||||
go version
|
||||
go get -v -d ./...
|
||||
cd cmd/wails
|
||||
go install
|
||||
workingDirectory: '$(modulePath)'
|
||||
displayName: 'Get dependencies, then build'
|
||||
- script: |
|
||||
wails version
|
||||
workingDirectory: '$(Agent.BuildDirectory)/go/bin'
|
||||
displayName: 'Check we have output'
|
||||
138
azure-pipelines.yml
Normal file
138
azure-pipelines.yml
Normal file
@@ -0,0 +1,138 @@
|
||||
# avoid double trigger by applying some rules
|
||||
# start a pipeline when push to 'master' branch
|
||||
trigger:
|
||||
- master
|
||||
# or when pull request on 'develop' branch
|
||||
pr:
|
||||
- develop
|
||||
|
||||
# for now there is only one stage 'Build'
|
||||
# in the future we could use multistage strategy for releases
|
||||
stages:
|
||||
- stage: Build
|
||||
|
||||
# there are 3 jobs
|
||||
# one for each os
|
||||
jobs:
|
||||
- deployment: Linux
|
||||
displayName: Lin
|
||||
variables:
|
||||
GOPATH: '$(Agent.BuildDirectory)/gopath' # Go workspace path
|
||||
GOROOT: '$(Agent.BuildDirectory)/go' # Go installation path
|
||||
GOBIN: '$(GOPATH)/bin' # Go binaries path
|
||||
GOMODULE: 'on'
|
||||
modulePath: '$(Agent.BuildDirectory)/wails' # Path to the module's code
|
||||
pool:
|
||||
vmImage: 'Ubuntu-16.04'
|
||||
environment: 'linux-dev'
|
||||
strategy:
|
||||
runOnce:
|
||||
deploy:
|
||||
steps:
|
||||
- checkout: self # self represents the repo where the initial Pipelines YAML file was found
|
||||
clean: true # whether to fetch clean each time
|
||||
path: wails # path to check out source code, relative to the agent's build directory (e.g. \_work\1)
|
||||
# go version 1.12.7
|
||||
- script: |
|
||||
wget "https://storage.googleapis.com/golang/go1.12.7.linux-amd64.tar.gz" --output-document "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
|
||||
tar -C '$(Agent.BuildDirectory)' -xzf "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
|
||||
displayName: 'Install Go 1.12.7 Linux'
|
||||
- script: |
|
||||
mkdir -p '$(GOBIN)'
|
||||
mkdir -p '$(GOPATH)/pkg'
|
||||
mkdir -p '$(GOROOT)'
|
||||
shopt -s extglob
|
||||
shopt -s dotglob
|
||||
echo '##vso[task.prependpath]$(GOBIN)'
|
||||
echo '##vso[task.prependpath]$(GOROOT)/bin'
|
||||
displayName: 'Set up the Go workspace'
|
||||
- script: |
|
||||
go version
|
||||
go get -v -d ./...
|
||||
cd cmd/wails
|
||||
go install
|
||||
workingDirectory: '$(modulePath)'
|
||||
displayName: 'Get dependencies, then build'
|
||||
- script: |
|
||||
wails version
|
||||
workingDirectory: '$(modulePath)'
|
||||
displayName: 'Check we have output'
|
||||
|
||||
- deployment: Mac
|
||||
displayName: Mac
|
||||
variables:
|
||||
GOPATH: '$(Agent.BuildDirectory)/gopath' # Go workspace path
|
||||
GOROOT: '$(Agent.BuildDirectory)/go' # Go installation path
|
||||
GOBIN: '$(GOPATH)/bin' # Go binaries path
|
||||
GOMODULE: 'on'
|
||||
modulePath: '$(Agent.BuildDirectory)/wails' # Path to the module's code
|
||||
pool:
|
||||
vmImage: 'macOS-10.14'
|
||||
environment: 'mac-dev'
|
||||
strategy:
|
||||
runOnce:
|
||||
deploy:
|
||||
steps:
|
||||
- checkout: self # self represents the repo where the initial Pipelines YAML file was found
|
||||
clean: true # whether to fetch clean each time
|
||||
path: wails # path to check out source code, relative to the agent's build directory (e.g. \_work\1)
|
||||
# go version 1.12.7
|
||||
- script: |
|
||||
wget "https://storage.googleapis.com/golang/go1.12.7.darwin-amd64.tar.gz" --output-document "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
|
||||
tar -C '$(Agent.BuildDirectory)' -xzf "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
|
||||
displayName: 'Install Go 1.12.7 Linux'
|
||||
- script: |
|
||||
mkdir -p '$(GOBIN)'
|
||||
mkdir -p '$(GOPATH)/pkg'
|
||||
mkdir -p '$(GOROOT)'
|
||||
shopt -s extglob
|
||||
shopt -s dotglob
|
||||
echo '##vso[task.prependpath]$(GOBIN)'
|
||||
echo '##vso[task.prependpath]$(GOROOT)/bin'
|
||||
displayName: 'Set up the Go workspace'
|
||||
- script: |
|
||||
go version
|
||||
go get -v -d ./...
|
||||
cd cmd/wails
|
||||
go install
|
||||
workingDirectory: '$(modulePath)'
|
||||
displayName: 'Get dependencies, then build'
|
||||
- script: |
|
||||
wails version
|
||||
workingDirectory: '$(modulePath)'
|
||||
displayName: 'Check we have output'
|
||||
|
||||
- deployment: Win
|
||||
displayName: Win
|
||||
variables:
|
||||
GOMODULE: 'on'
|
||||
modulePath: '$(Agent.BuildDirectory)/wails' # Path to the module's code
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
environment: 'win-dev'
|
||||
strategy:
|
||||
runOnce:
|
||||
deploy:
|
||||
steps:
|
||||
- checkout: self # self represents the repo where the initial Pipelines YAML file was found
|
||||
clean: true # whether to fetch clean each time
|
||||
path: wails # path to check out source code, relative to the agent's build directory (e.g. \_work\1)
|
||||
# Go tool installer
|
||||
# Find in cache or download a specific version of Go and add it to the PATH
|
||||
- task: GoTool@0
|
||||
inputs:
|
||||
version: '1.12.7'
|
||||
goPath: '$(Agent.BuildDirectory)/go'
|
||||
goBin: '$(Agent.BuildDirectory)/go/bin'
|
||||
displayName: 'Set up the Go workspace'
|
||||
- script: |
|
||||
go version
|
||||
go get -v -d ./...
|
||||
cd cmd/wails
|
||||
go install
|
||||
workingDirectory: '$(modulePath)'
|
||||
displayName: 'Get dependencies, then build'
|
||||
- script: |
|
||||
wails version
|
||||
workingDirectory: '$(Agent.BuildDirectory)/go/bin'
|
||||
displayName: 'Check we have output'
|
||||
3
cli.go
3
cli.go
@@ -11,10 +11,9 @@ func (app *App) setupCli() *cmd.Cli {
|
||||
result := cmd.NewCli(app.config.Title, "Debug build")
|
||||
result.Version(cmd.Version)
|
||||
|
||||
// Setup cli to handle loglevel and headless flags
|
||||
// Setup cli to handle loglevel
|
||||
result.
|
||||
StringFlag("loglevel", "Sets the log level [debug|info|error|panic|fatal]. Default debug", &app.logLevel).
|
||||
// BoolFlag("headless", "Runs the app in headless mode", &app.headless).
|
||||
Action(app.start)
|
||||
|
||||
// Banner
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -18,7 +18,7 @@ func NewGitHubHelper() *GitHubHelper {
|
||||
}
|
||||
|
||||
// GetVersionTags gets the list of tags on the Wails repo
|
||||
// It retuns a list of sorted tags in descending order
|
||||
// It returns a list of sorted tags in descending order
|
||||
func (g *GitHubHelper) GetVersionTags() ([]*SemanticVersion, error) {
|
||||
|
||||
result := []*SemanticVersion{}
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
mewn "github.com/leaanthony/mewn"
|
||||
"github.com/leaanthony/mewn"
|
||||
"github.com/leaanthony/slicer"
|
||||
"github.com/leaanthony/spinner"
|
||||
)
|
||||
@@ -219,6 +219,15 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
|
||||
|
||||
const md5sumFile = "package.json.md5"
|
||||
|
||||
// If node_modules does not exist, force a rebuild.
|
||||
nodeModulesPath, err := filepath.Abs(filepath.Join(".", "node_modules"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !fs.DirExists(nodeModulesPath) {
|
||||
forceRebuild = true
|
||||
}
|
||||
|
||||
// If we aren't forcing the install and the md5sum file exists
|
||||
if !forceRebuild && fs.FileExists(md5sumFile) {
|
||||
// Yes - read contents
|
||||
@@ -249,8 +258,8 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
|
||||
ioutil.WriteFile(md5sumFile, []byte(packageJSONMD5), 0644)
|
||||
}
|
||||
|
||||
// Install the bridge library
|
||||
err = InstallBridge(caller, projectDir, projectOptions)
|
||||
// Install the runtime
|
||||
err = InstallRuntime(caller, projectDir, projectOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -263,22 +272,29 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
|
||||
return nil
|
||||
}
|
||||
|
||||
// InstallBridge installs the relevant bridge javascript library
|
||||
func InstallBridge(caller string, projectDir string, projectOptions *ProjectOptions) error {
|
||||
bridgeFile := "wailsbridge.prod.js"
|
||||
if caller == "serve" {
|
||||
bridgeFile = "wailsbridge.js"
|
||||
// InstallRuntime installs the correct runtime for the type of build
|
||||
func InstallRuntime(caller string, projectDir string, projectOptions *ProjectOptions) error {
|
||||
if caller == "build" {
|
||||
return InstallProdRuntime(projectDir, projectOptions)
|
||||
}
|
||||
|
||||
// Copy bridge to project
|
||||
bridgeAssets := mewn.Group("../runtime/bridge/")
|
||||
bridgeFileData := bridgeAssets.Bytes(bridgeFile)
|
||||
bridgeFileTarget := filepath.Join(projectDir, projectOptions.FrontEnd.Dir, projectOptions.FrontEnd.Bridge, "wailsbridge.js")
|
||||
err := fs.CreateFile(bridgeFileTarget, bridgeFileData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return InstallBridge(projectDir, projectOptions)
|
||||
}
|
||||
|
||||
// InstallBridge installs the relevant bridge javascript library
|
||||
func InstallBridge(projectDir string, projectOptions *ProjectOptions) error {
|
||||
bridgeFileData := mewn.String("../runtime/assets/bridge.js")
|
||||
bridgeFileTarget := filepath.Join(projectDir, projectOptions.FrontEnd.Dir, "node_modules", "@wailsapp", "runtime", "init.js")
|
||||
err := fs.CreateFile(bridgeFileTarget, []byte(bridgeFileData))
|
||||
return err
|
||||
}
|
||||
|
||||
// InstallProdRuntime installs the production runtime
|
||||
func InstallProdRuntime(projectDir string, projectOptions *ProjectOptions) error {
|
||||
prodInit := mewn.String("../runtime/js/runtime/init.js")
|
||||
bridgeFileTarget := filepath.Join(projectDir, projectOptions.FrontEnd.Dir, "node_modules", "@wailsapp", "runtime", "init.js")
|
||||
err := fs.CreateFile(bridgeFileTarget, []byte(prodInit))
|
||||
return err
|
||||
}
|
||||
|
||||
// ServeProject attempts to serve up the current project so that it may be connected to
|
||||
|
||||
229
cmd/linux.go
229
cmd/linux.go
@@ -17,122 +17,133 @@ type LinuxDistribution int
|
||||
const (
|
||||
// Unknown is the catch-all distro
|
||||
Unknown LinuxDistribution = iota
|
||||
// Debian distribution
|
||||
Debian
|
||||
// Ubuntu distribution
|
||||
Ubuntu
|
||||
// Arch linux distribution
|
||||
Arch
|
||||
// RedHat linux distribution
|
||||
RedHat
|
||||
// Debian distribution
|
||||
Debian
|
||||
// CentOS linux distribution
|
||||
CentOS
|
||||
// Fedora linux distribution
|
||||
Fedora
|
||||
// Gentoo distribution
|
||||
Gentoo
|
||||
// Zorin distribution
|
||||
Zorin
|
||||
// Parrot distribution
|
||||
Parrot
|
||||
// Linuxmint distribution
|
||||
Linuxmint
|
||||
// VoidLinux distribution
|
||||
VoidLinux
|
||||
// Elementary distribution
|
||||
Elementary
|
||||
// Kali distribution
|
||||
Kali
|
||||
// Neon distribution
|
||||
Neon
|
||||
// Manjaro distribution
|
||||
Manjaro
|
||||
)
|
||||
|
||||
// DistroInfo contains all the information relating to a linux distribution
|
||||
type DistroInfo struct {
|
||||
Distribution LinuxDistribution
|
||||
Description string
|
||||
Release string
|
||||
Codename string
|
||||
DistributorID string
|
||||
DiscoveredBy string
|
||||
Distribution LinuxDistribution
|
||||
Name string
|
||||
ID string
|
||||
Description string
|
||||
Release string
|
||||
}
|
||||
|
||||
// GetLinuxDistroInfo returns information about the running linux distribution
|
||||
func GetLinuxDistroInfo() *DistroInfo {
|
||||
result := &DistroInfo{Distribution: Unknown}
|
||||
program := NewProgramHelper()
|
||||
// Does lsb_release exist?
|
||||
|
||||
lsbRelease := program.FindProgram("lsb_release")
|
||||
if lsbRelease != nil {
|
||||
stdout, _, _, err := lsbRelease.Run("-a")
|
||||
if err != nil {
|
||||
return result
|
||||
}
|
||||
result.DiscoveredBy = "lsb"
|
||||
for _, line := range strings.Split(stdout, "\n") {
|
||||
if strings.Contains(line, ":") {
|
||||
// Iterate lines a
|
||||
details := strings.Split(line, ":")
|
||||
key := strings.TrimSpace(details[0])
|
||||
value := strings.TrimSpace(details[1])
|
||||
switch key {
|
||||
case "Distributor ID":
|
||||
result.DistributorID = value
|
||||
switch value {
|
||||
case "Ubuntu":
|
||||
result.Distribution = Ubuntu
|
||||
case "Arch", "ManjaroLinux":
|
||||
result.Distribution = Arch
|
||||
case "Debian":
|
||||
result.Distribution = Debian
|
||||
case "Gentoo":
|
||||
result.Distribution = Gentoo
|
||||
case "Zorin":
|
||||
result.Distribution = Zorin
|
||||
case "Fedora":
|
||||
result.Distribution = RedHat
|
||||
}
|
||||
case "Description":
|
||||
result.Description = value
|
||||
case "Release":
|
||||
result.Release = value
|
||||
case "Codename":
|
||||
result.Codename = value
|
||||
}
|
||||
}
|
||||
}
|
||||
// check if /etc/os-release exists
|
||||
} else if _, err := os.Stat("/etc/os-release"); !os.IsNotExist(err) {
|
||||
// Default value
|
||||
osName := "Unknown"
|
||||
version := ""
|
||||
// read /etc/os-release
|
||||
result := &DistroInfo{
|
||||
Distribution: Unknown,
|
||||
ID: "unknown",
|
||||
Name: "Unknown",
|
||||
}
|
||||
_, err := os.Stat("/etc/os-release")
|
||||
if !os.IsNotExist(err) {
|
||||
osRelease, _ := ioutil.ReadFile("/etc/os-release")
|
||||
// Split into lines
|
||||
lines := strings.Split(string(osRelease), "\n")
|
||||
// Iterate lines
|
||||
for _, line := range lines {
|
||||
// Split each line by the equals char
|
||||
splitLine := strings.SplitN(line, "=", 2)
|
||||
// Check we have
|
||||
if len(splitLine) != 2 {
|
||||
continue
|
||||
}
|
||||
switch splitLine[0] {
|
||||
case "NAME":
|
||||
osName = strings.Trim(splitLine[1], "\"")
|
||||
case "VERSION_ID":
|
||||
version = strings.Trim(splitLine[1], "\"")
|
||||
}
|
||||
|
||||
}
|
||||
// Check distro name against list of distros
|
||||
result.Release = version
|
||||
result.DiscoveredBy = "os-release"
|
||||
switch osName {
|
||||
case "Fedora":
|
||||
result.Distribution = RedHat
|
||||
case "CentOS":
|
||||
result.Distribution = RedHat
|
||||
case "Arch Linux":
|
||||
result.Distribution = Arch
|
||||
case "Debian GNU/Linux":
|
||||
result.Distribution = Debian
|
||||
case "Gentoo/Linux":
|
||||
result.Distribution = Gentoo
|
||||
default:
|
||||
result.Distribution = Unknown
|
||||
result.DistributorID = osName
|
||||
}
|
||||
result = parseOsRelease(string(osRelease))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// parseOsRelease parses the given os-release data and returns
|
||||
// a DistroInfo struct with the details
|
||||
func parseOsRelease(osRelease string) *DistroInfo {
|
||||
result := &DistroInfo{Distribution: Unknown}
|
||||
|
||||
// Default value
|
||||
osID := "unknown"
|
||||
osNAME := "Unknown"
|
||||
version := ""
|
||||
|
||||
// Split into lines
|
||||
lines := strings.Split(osRelease, "\n")
|
||||
// Iterate lines
|
||||
for _, line := range lines {
|
||||
// Split each line by the equals char
|
||||
splitLine := strings.SplitN(line, "=", 2)
|
||||
// Check we have
|
||||
if len(splitLine) != 2 {
|
||||
continue
|
||||
}
|
||||
switch splitLine[0] {
|
||||
case "ID":
|
||||
osID = strings.Trim(splitLine[1], "\"")
|
||||
case "NAME":
|
||||
osNAME = strings.Trim(splitLine[1], "\"")
|
||||
case "VERSION_ID":
|
||||
version = strings.Trim(splitLine[1], "\"")
|
||||
}
|
||||
}
|
||||
// Check distro name against list of distros
|
||||
switch osID {
|
||||
case "fedora":
|
||||
result.Distribution = Fedora
|
||||
case "centos":
|
||||
result.Distribution = CentOS
|
||||
case "arch":
|
||||
result.Distribution = Arch
|
||||
case "debian":
|
||||
result.Distribution = Debian
|
||||
case "ubuntu":
|
||||
result.Distribution = Ubuntu
|
||||
case "gentoo":
|
||||
result.Distribution = Gentoo
|
||||
case "zorin":
|
||||
result.Distribution = Zorin
|
||||
case "parrot":
|
||||
result.Distribution = Parrot
|
||||
case "linuxmint":
|
||||
result.Distribution = Linuxmint
|
||||
case "void":
|
||||
result.Distribution = VoidLinux
|
||||
case "elementary":
|
||||
result.Distribution = Elementary
|
||||
case "kali":
|
||||
result.Distribution = Kali
|
||||
case "neon":
|
||||
result.Distribution = Neon
|
||||
case "manjaro":
|
||||
result.Distribution = Manjaro
|
||||
default:
|
||||
result.Distribution = Unknown
|
||||
}
|
||||
|
||||
result.Name = osNAME
|
||||
result.ID = osID
|
||||
result.Release = version
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// CheckPkgInstalled is all functions that use local programs to see if a package is installed
|
||||
type CheckPkgInstalled func(string) (bool, error)
|
||||
|
||||
// EqueryInstalled uses equery to see if a package is installed
|
||||
func EqueryInstalled(packageName string) (bool, error) {
|
||||
program := NewProgramHelper()
|
||||
@@ -166,6 +177,17 @@ func PacmanInstalled(packageName string) (bool, error) {
|
||||
return exitCode == 0, nil
|
||||
}
|
||||
|
||||
// XbpsInstalled uses pacman to see if a package is installed.
|
||||
func XbpsInstalled(packageName string) (bool, error) {
|
||||
program := NewProgramHelper()
|
||||
xbpsQuery := program.FindProgram("xbps-query")
|
||||
if xbpsQuery == nil {
|
||||
return false, fmt.Errorf("cannot check dependencies: xbps-query not found")
|
||||
}
|
||||
_, _, exitCode, _ := xbpsQuery.Run("-S", packageName)
|
||||
return exitCode == 0, nil
|
||||
}
|
||||
|
||||
// RpmInstalled uses rpm to see if a package is installed
|
||||
func RpmInstalled(packageName string) (bool, error) {
|
||||
program := NewProgramHelper()
|
||||
@@ -179,18 +201,18 @@ func RpmInstalled(packageName string) (bool, error) {
|
||||
|
||||
// RequestSupportForDistribution promts the user to submit a request to support their
|
||||
// currently unsupported distribution
|
||||
func RequestSupportForDistribution(distroInfo *DistroInfo, libraryName string) error {
|
||||
func RequestSupportForDistribution(distroInfo *DistroInfo) error {
|
||||
var logger = NewLogger()
|
||||
defaultError := fmt.Errorf("unable to check libraries on distribution '%s'. Please ensure that the '%s' equivalent is installed", distroInfo.DistributorID, libraryName)
|
||||
defaultError := fmt.Errorf("unable to check libraries on distribution '%s'", distroInfo.Name)
|
||||
|
||||
logger.Yellow("Distribution '%s' is not currently supported, but we would love to!", distroInfo.DistributorID)
|
||||
q := fmt.Sprintf("Would you like to submit a request to support distribution '%s'?", distroInfo.DistributorID)
|
||||
logger.Yellow("Distribution '%s' is not currently supported, but we would love to!", distroInfo.Name)
|
||||
q := fmt.Sprintf("Would you like to submit a request to support distribution '%s'?", distroInfo.Name)
|
||||
result := Prompt(q, "yes")
|
||||
if strings.ToLower(result) != "yes" {
|
||||
return defaultError
|
||||
}
|
||||
|
||||
title := fmt.Sprintf("Support Distribution '%s'", distroInfo.DistributorID)
|
||||
title := fmt.Sprintf("Support Distribution '%s'", distroInfo.Name)
|
||||
|
||||
var str strings.Builder
|
||||
|
||||
@@ -205,16 +227,15 @@ func RequestSupportForDistribution(distroInfo *DistroInfo, libraryName string) e
|
||||
str.WriteString(fmt.Sprintf("| Platform | %s |\n", runtime.GOOS))
|
||||
str.WriteString(fmt.Sprintf("| Arch | %s |\n", runtime.GOARCH))
|
||||
str.WriteString(fmt.Sprintf("| GO111MODULE | %s |\n", gomodule))
|
||||
str.WriteString(fmt.Sprintf("| Distribution ID | %s |\n", distroInfo.DistributorID))
|
||||
str.WriteString(fmt.Sprintf("| Distribution ID | %s |\n", distroInfo.ID))
|
||||
str.WriteString(fmt.Sprintf("| Distribution Name | %s |\n", distroInfo.Name))
|
||||
str.WriteString(fmt.Sprintf("| Distribution Version | %s |\n", distroInfo.Release))
|
||||
str.WriteString(fmt.Sprintf("| Discovered by | %s |\n", distroInfo.DiscoveredBy))
|
||||
|
||||
body := fmt.Sprintf("**Description**\nDistribution '%s' is currently unsupported.\n\n**Further Information**\n\n%s\n\n*Please add any extra information here, EG: libraries that are needed to make the distribution work, or commands to install them*", distroInfo.DistributorID, str.String())
|
||||
body := fmt.Sprintf("**Description**\nDistribution '%s' is currently unsupported.\n\n**Further Information**\n\n%s\n\n*Please add any extra information here, EG: libraries that are needed to make the distribution work, or commands to install them*", distroInfo.ID, str.String())
|
||||
fullURL := "https://github.com/wailsapp/wails/issues/new?"
|
||||
params := "title=" + title + "&body=" + body
|
||||
|
||||
fmt.Println("Opening browser to file request.")
|
||||
browser.OpenURL(fullURL + url.PathEscape(params))
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
26
cmd/linux_test.go
Normal file
26
cmd/linux_test.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package cmd
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestUbuntuDetection(t *testing.T) {
|
||||
osrelease := `
|
||||
NAME="Ubuntu"
|
||||
VERSION="18.04.2 LTS (Bionic Beaver)"
|
||||
ID=ubuntu
|
||||
ID_LIKE=debian
|
||||
PRETTY_NAME="Ubuntu 18.04.2 LTS"
|
||||
VERSION_ID="18.04"
|
||||
HOME_URL="https://www.ubuntu.com/"
|
||||
SUPPORT_URL="https://help.ubuntu.com/"
|
||||
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
|
||||
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
|
||||
VERSION_CODENAME=bionic
|
||||
UBUNTU_CODENAME=bionic
|
||||
`
|
||||
|
||||
result := parseOsRelease(osrelease)
|
||||
if result.Distribution != Ubuntu {
|
||||
t.Errorf("expected 'Ubuntu' ID but got '%d'", result.Distribution)
|
||||
}
|
||||
|
||||
}
|
||||
91
cmd/linuxdb.go
Normal file
91
cmd/linuxdb.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/leaanthony/mewn"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// LinuxDB is the database for linux distribution data.
|
||||
type LinuxDB struct {
|
||||
Distributions map[string]*Distribution `yaml:"distributions"`
|
||||
}
|
||||
|
||||
// Distribution holds the os-release ID and a map of releases.
|
||||
type Distribution struct {
|
||||
ID string `yaml:"id"`
|
||||
Releases map[string]*Release `yaml:"releases"`
|
||||
}
|
||||
|
||||
// GetRelease attempts to return the specific Release information
|
||||
// for the given release name. If there is no specific match, the
|
||||
// default release data is returned.
|
||||
func (d *Distribution) GetRelease(version string) *Release {
|
||||
result := d.Releases[version]
|
||||
if result == nil {
|
||||
result = d.Releases["default"]
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Release holds the name and version of the release as given by
|
||||
// os-release. Programs is a slice of dependant programs required
|
||||
// to be present on the local installation for Wails to function.
|
||||
// Libraries is a slice of libraries that must be present for Wails
|
||||
// applications to compile.
|
||||
type Release struct {
|
||||
Name string `yaml:"name"`
|
||||
Version string `yaml:"version"`
|
||||
GccVersionCommand string `yaml:"gccversioncommand"`
|
||||
Programs []*Prerequisite `yaml:"programs"`
|
||||
Libraries []*Prerequisite `yaml:"libraries"`
|
||||
}
|
||||
|
||||
// Prerequisite is a simple struct containing a program/library name
|
||||
// plus the distribution specific help text indicating how to install
|
||||
// it.
|
||||
type Prerequisite struct {
|
||||
Name string `yaml:"name"`
|
||||
Help string `yaml:"help,omitempty"`
|
||||
}
|
||||
|
||||
// Load will load the given filename from disk and attempt to
|
||||
// import the data into the LinuxDB.
|
||||
func (l *LinuxDB) Load(filename string) error {
|
||||
if fs.FileExists(filename) {
|
||||
data, err := fs.LoadAsBytes(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return l.ImportData(data)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ImportData will unmarshal the given YAML formatted data
|
||||
// into the LinuxDB
|
||||
func (l *LinuxDB) ImportData(data []byte) error {
|
||||
return yaml.Unmarshal(data, l)
|
||||
}
|
||||
|
||||
// GetDistro returns the Distribution information for the
|
||||
// given distribution name. If the distribution is not supported,
|
||||
// nil is returned.
|
||||
func (l *LinuxDB) GetDistro(distro string) *Distribution {
|
||||
return l.Distributions[distro]
|
||||
}
|
||||
|
||||
// NewLinuxDB creates a new LinuxDB instance from the bundled
|
||||
// linuxdb.yaml file.
|
||||
func NewLinuxDB() *LinuxDB {
|
||||
data := mewn.Bytes("./linuxdb.yaml")
|
||||
result := LinuxDB{
|
||||
Distributions: make(map[string]*Distribution),
|
||||
}
|
||||
err := result.ImportData(data)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return &result
|
||||
}
|
||||
188
cmd/linuxdb.yaml
Normal file
188
cmd/linuxdb.yaml
Normal file
@@ -0,0 +1,188 @@
|
||||
---
|
||||
distributions:
|
||||
debian:
|
||||
id: debian
|
||||
releases:
|
||||
default:
|
||||
name: Debian
|
||||
version: default
|
||||
gccversioncommand: &gccdumpversion -dumpversion
|
||||
programs: &debiandefaultprograms
|
||||
- name: gcc
|
||||
help: Please install with `sudo apt-get install build-essential` and try again
|
||||
- name: pkg-config
|
||||
help: Please install with `sudo apt-get install pkg-config` and try again
|
||||
- name: npm
|
||||
help: Please install with `curl -sL https://deb.nodesource.com/setup_12.x | sudo bash - && sudo apt-get install -y nodejs` and try again
|
||||
libraries: &debiandefaultlibraries
|
||||
- name: libgtk-3-dev
|
||||
help: Please install with `sudo apt-get install libgtk-3-dev` and try again
|
||||
- name: libwebkit2gtk-4.0-dev
|
||||
help: Please install with `sudo apt-get install libwebkit2gtk-4.0-dev` and try again
|
||||
ubuntu:
|
||||
id: ubuntu
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: Ubuntu
|
||||
gccversioncommand: &gccdumpfullversion -dumpfullversion
|
||||
programs: *debiandefaultprograms
|
||||
libraries: *debiandefaultlibraries
|
||||
kali:
|
||||
id: kali
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: Kali GNU/Linux
|
||||
gccversioncommand: *gccdumpfullversion
|
||||
programs: *debiandefaultprograms
|
||||
libraries: *debiandefaultlibraries
|
||||
parrot:
|
||||
id: parrot
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: Parrot GNU/Linux
|
||||
gccversioncommand: *gccdumpversion
|
||||
programs: *debiandefaultprograms
|
||||
libraries: *debiandefaultlibraries
|
||||
zorin:
|
||||
id: zorin
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: Zorin
|
||||
gccversioncommand: *gccdumpversion
|
||||
programs: *debiandefaultprograms
|
||||
libraries: *debiandefaultlibraries
|
||||
linuxmint:
|
||||
id: linuxmint
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: Linux Mint
|
||||
gccversioncommand: *gccdumpversion
|
||||
programs: *debiandefaultprograms
|
||||
libraries: *debiandefaultlibraries
|
||||
elementary:
|
||||
id: elementary
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: elementary OS
|
||||
gccversioncommand: *gccdumpfullversion
|
||||
programs: *debiandefaultprograms
|
||||
libraries: *debiandefaultlibraries
|
||||
neon:
|
||||
id: neon
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: KDE neon
|
||||
gccversioncommand: *gccdumpfullversion
|
||||
programs: *debiandefaultprograms
|
||||
libraries: *debiandefaultlibraries
|
||||
void:
|
||||
id: void
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: VoidLinux
|
||||
gccversioncommand: *gccdumpversion
|
||||
programs:
|
||||
- name: gcc
|
||||
help: Please install with `xbps-install base-devel` and try again
|
||||
- name: pkg-config
|
||||
help: Please install with `xbps-install pkg-config` and try again
|
||||
- name: npm
|
||||
help: Please install with `xbps-install nodejs` and try again
|
||||
libraries:
|
||||
- name: gtk+3-devel
|
||||
help: Please install with `xbps-install gtk+3-devel` and try again
|
||||
- name: webkit2gtk-devel
|
||||
help: Please install with `xbps-install webkit2gtk-devel` and try again
|
||||
centos:
|
||||
id: centos
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: CentOS Linux
|
||||
gccversioncommand: *gccdumpversion
|
||||
programs:
|
||||
- name: gcc
|
||||
help: Please install with `sudo yum install gcc-c++ make` and try again
|
||||
- name: pkg-config
|
||||
help: Please install with `sudo yum install pkgconf-pkg-config` and try again
|
||||
- name: npm
|
||||
help: Please install with `sudo yum install epel-release && sudo yum install nodejs` and try again
|
||||
libraries:
|
||||
- name: gtk3-devel
|
||||
help: Please install with `sudo yum install gtk3-devel` and try again
|
||||
- name: webkitgtk3-devel
|
||||
help: Please install with `sudo yum install webkitgtk3-devel` and try again
|
||||
fedora:
|
||||
id: fedora
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: Fedora
|
||||
gccversioncommand: *gccdumpfullversion
|
||||
programs:
|
||||
- name: gcc
|
||||
help: Please install with `sudo yum install gcc-c++ make` and try again
|
||||
- name: pkg-config
|
||||
help: Please install with `sudo yum install pkgconf-pkg-config` and try again
|
||||
- name: npm
|
||||
help: Please install `sudo yum install nodejs` and try again
|
||||
libraries:
|
||||
- name: gtk3-devel
|
||||
help: Please install with `sudo yum install gtk3-devel` and try again
|
||||
- name: webkit2gtk3-devel
|
||||
help: Please install with `sudo yum install webkit2gtk3-devel` and try again
|
||||
arch:
|
||||
id: arch
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: Arch Linux
|
||||
gccversioncommand: *gccdumpversion
|
||||
programs: &archdefaultprograms
|
||||
- name: gcc
|
||||
help: Please install with `sudo pacman -S gcc` and try again
|
||||
- name: pkgconf
|
||||
help: Please install with `sudo pacman -S pkgconf` and try again
|
||||
- name: npm
|
||||
help: Please install with `sudo pacman -S npm` and try again
|
||||
libraries: &archdefaultlibraries
|
||||
- name: gtk3
|
||||
help: Please install with `sudo pacman -S gtk3` and try again
|
||||
- name: webkit2gtk
|
||||
help: Please install with `sudo pacman -S webkit2gtk` and try again
|
||||
manjaro:
|
||||
id: manjaro
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: Manjaro Linux
|
||||
gccversioncommand: *gccdumpversion
|
||||
programs: *archdefaultprograms
|
||||
libraries: *archdefaultlibraries
|
||||
gentoo:
|
||||
id: gentoo
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: Gentoo
|
||||
gccversioncommand: *gccdumpversion
|
||||
programs:
|
||||
- name: gcc
|
||||
help: Please install using your system's package manager
|
||||
- name: pkg-config
|
||||
help: Please install using your system's package manager
|
||||
- name: npm
|
||||
help: Please install using your system's package manager
|
||||
libraries:
|
||||
- name: gtk+:3
|
||||
help: Please install with `sudo emerge gtk+:3` and try again
|
||||
- name: webkit-gtk
|
||||
help: Please install with `sudo emerge webkit-gtk` and try again
|
||||
81
cmd/linuxdb_test.go
Normal file
81
cmd/linuxdb_test.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package cmd
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestNewLinuxDB(t *testing.T) {
|
||||
_ = NewLinuxDB()
|
||||
}
|
||||
|
||||
func TestKnownDistro(t *testing.T) {
|
||||
var linuxDB = NewLinuxDB()
|
||||
result := linuxDB.GetDistro("ubuntu")
|
||||
if result == nil {
|
||||
t.Error("Cannot get distro 'ubuntu'")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnknownDistro(t *testing.T) {
|
||||
var linuxDB = NewLinuxDB()
|
||||
result := linuxDB.GetDistro("unknown")
|
||||
if result != nil {
|
||||
t.Error("Should get nil for distribution 'unknown'")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefaultRelease(t *testing.T) {
|
||||
var linuxDB = NewLinuxDB()
|
||||
result := linuxDB.GetDistro("ubuntu")
|
||||
if result == nil {
|
||||
t.Error("Cannot get distro 'ubuntu'")
|
||||
}
|
||||
|
||||
release := result.GetRelease("default")
|
||||
if release == nil {
|
||||
t.Error("Cannot get release 'default' for distro 'ubuntu'")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnknownRelease(t *testing.T) {
|
||||
var linuxDB = NewLinuxDB()
|
||||
result := linuxDB.GetDistro("ubuntu")
|
||||
if result == nil {
|
||||
t.Error("Cannot get distro 'ubuntu'")
|
||||
}
|
||||
|
||||
release := result.GetRelease("16.04")
|
||||
if release == nil {
|
||||
t.Error("Failed to get release 'default' for unknown release version '16.04'")
|
||||
}
|
||||
|
||||
if release.Version != "default" {
|
||||
t.Errorf("Got version '%s' instead of 'default' for unknown release version '16.04'", result.ID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPrerequisites(t *testing.T) {
|
||||
var linuxDB = NewLinuxDB()
|
||||
result := linuxDB.GetDistro("debian")
|
||||
if result == nil {
|
||||
t.Error("Cannot get distro 'debian'")
|
||||
}
|
||||
|
||||
release := result.GetRelease("default")
|
||||
if release == nil {
|
||||
t.Error("Failed to get release 'default' for unknown release version '16.04'")
|
||||
}
|
||||
|
||||
if release.Version != "default" {
|
||||
t.Errorf("Got version '%s' instead of 'default' for unknown release version '16.04'", result.ID)
|
||||
}
|
||||
|
||||
if release.Name != "Debian" {
|
||||
t.Errorf("Got Release Name '%s' instead of 'debian' for unknown release version '16.04'", release.Name)
|
||||
}
|
||||
|
||||
if len(release.Programs) != 3 {
|
||||
t.Errorf("Expected %d programs for unknown release version '16.04'", len(release.Programs))
|
||||
}
|
||||
if len(release.Libraries) != 2 {
|
||||
t.Errorf("Expected %d libraries for unknown release version '16.04'", len(release.Libraries))
|
||||
}
|
||||
}
|
||||
@@ -5,13 +5,6 @@ import (
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// Prerequisite defines a Prerequisite!
|
||||
type Prerequisite struct {
|
||||
Name string
|
||||
Help string
|
||||
Path string
|
||||
}
|
||||
|
||||
func newPrerequisite(name, help string) *Prerequisite {
|
||||
return &Prerequisite{Name: name, Help: help}
|
||||
}
|
||||
@@ -48,16 +41,13 @@ func getRequiredProgramsOSX() *Prerequisites {
|
||||
func getRequiredProgramsLinux() *Prerequisites {
|
||||
result := &Prerequisites{}
|
||||
distroInfo := GetLinuxDistroInfo()
|
||||
switch distroInfo.Distribution {
|
||||
case Ubuntu, Debian, Zorin:
|
||||
result.Add(newPrerequisite("gcc", "Please install with `sudo apt install build-essentials` and try again"))
|
||||
result.Add(newPrerequisite("pkg-config", "Please install with `sudo apt install pkg-config` and try again"))
|
||||
result.Add(newPrerequisite("npm", "Please install with `sudo snap install node --channel=12/stable --classic` and try again"))
|
||||
default:
|
||||
result.Add(newPrerequisite("gcc", "Please install with your system package manager and try again"))
|
||||
result.Add(newPrerequisite("pkg-config", "Please install with your system package manager and try again"))
|
||||
result.Add(newPrerequisite("npm", "Please install from https://nodejs.org/en/download/ and try again"))
|
||||
|
||||
if distroInfo.Distribution != Unknown {
|
||||
var linuxDB = NewLinuxDB()
|
||||
distro := linuxDB.GetDistro(distroInfo.ID)
|
||||
release := distro.GetRelease(distroInfo.Release)
|
||||
for _, program := range release.Programs {
|
||||
result.Add(program)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -91,23 +81,15 @@ func getRequiredLibrariesOSX() (*Prerequisites, error) {
|
||||
|
||||
func getRequiredLibrariesLinux() (*Prerequisites, error) {
|
||||
result := &Prerequisites{}
|
||||
// The Linux Distribution DB
|
||||
distroInfo := GetLinuxDistroInfo()
|
||||
switch distroInfo.Distribution {
|
||||
case Ubuntu, Debian, Zorin:
|
||||
result.Add(newPrerequisite("libgtk-3-dev", "Please install with `sudo apt install libgtk-3-dev` and try again"))
|
||||
result.Add(newPrerequisite("libwebkit2gtk-4.0-dev", "Please install with `sudo apt install libwebkit2gtk-4.0-dev` and try again"))
|
||||
case Gentoo:
|
||||
result.Add(newPrerequisite("gtk+:3", "Please install with `sudo emerge gtk+:3` and try again"))
|
||||
result.Add(newPrerequisite("webkit-gtk", "Please install with `sudo emerge webkit-gtk` and try again"))
|
||||
case Arch:
|
||||
result.Add(newPrerequisite("gtk3", "Please install with `sudo pacman -S gtk3` and try again"))
|
||||
result.Add(newPrerequisite("webkit2gtk", "Please install with `sudo pacman -S webkit2gtk` and try again"))
|
||||
case RedHat:
|
||||
result.Add(newPrerequisite("gtk3-devel", "Please install with `sudo yum install gtk3-devel` and try again"))
|
||||
result.Add(newPrerequisite("webkit2gtk3-devel", "Please install with `sudo yum install webkit2gtk3-devel` and try again"))
|
||||
default:
|
||||
result.Add(newPrerequisite("libgtk-3-dev", "Please install with your system package manager and try again"))
|
||||
result.Add(newPrerequisite("libwebkit2gtk-4.0-dev", "Please install with your system package manager and try again"))
|
||||
if distroInfo.Distribution != Unknown {
|
||||
var linuxDB = NewLinuxDB()
|
||||
distro := linuxDB.GetDistro(distroInfo.ID)
|
||||
release := distro.GetRelease(distroInfo.Release)
|
||||
for _, library := range release.Libraries {
|
||||
result.Add(library)
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -100,6 +100,19 @@ func (p *ProgramHelper) InstallGoPackage(packageName string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// InstallNPMPackage installs the given npm package
|
||||
func (p *ProgramHelper) InstallNPMPackage(packageName string, save bool) error {
|
||||
args := strings.Split("install "+packageName, " ")
|
||||
if save {
|
||||
args = append(args, "--save")
|
||||
}
|
||||
_, stderr, err := p.shell.Run("npm", args...)
|
||||
if err != nil {
|
||||
fmt.Println(stderr)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// RunCommand runs the given command
|
||||
func (p *ProgramHelper) RunCommand(command string) error {
|
||||
args := strings.Split(command, " ")
|
||||
@@ -117,14 +130,15 @@ func (p *ProgramHelper) RunCommandArray(args []string, dir ...string) error {
|
||||
}
|
||||
args = args[1:]
|
||||
var stderr string
|
||||
// fmt.Printf("RunCommandArray = %s %+v\n", program, args)
|
||||
var stdout string
|
||||
if len(dir) > 0 {
|
||||
_, stderr, err = p.shell.RunInDirectory(dir[0], program, args...)
|
||||
stdout, stderr, err = p.shell.RunInDirectory(dir[0], program, args...)
|
||||
} else {
|
||||
_, stderr, err = p.shell.Run(program, args...)
|
||||
stdout, stderr, err = p.shell.Run(program, args...)
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println(stderr)
|
||||
fmt.Println(stdout)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -13,6 +13,18 @@ import (
|
||||
"github.com/leaanthony/slicer"
|
||||
)
|
||||
|
||||
// PackageManager indicates different package managers
|
||||
type PackageManager int
|
||||
|
||||
const (
|
||||
// UNKNOWN package manager
|
||||
UNKNOWN PackageManager = iota
|
||||
// NPM package manager
|
||||
NPM
|
||||
// YARN package manager
|
||||
YARN
|
||||
)
|
||||
|
||||
type author struct {
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
@@ -112,9 +124,9 @@ func (ph *ProjectHelper) NewProjectOptions() *ProjectOptions {
|
||||
Description: "Enter your project description",
|
||||
Version: "0.1.0",
|
||||
BinaryName: "",
|
||||
system: NewSystemHelper(),
|
||||
log: NewLogger(),
|
||||
templates: NewTemplateHelper(),
|
||||
system: ph.system,
|
||||
log: ph.log,
|
||||
templates: ph.templates,
|
||||
Author: &author{},
|
||||
}
|
||||
|
||||
@@ -153,6 +165,23 @@ func (po *ProjectOptions) Defaults() {
|
||||
po.WailsVersion = Version
|
||||
}
|
||||
|
||||
// GetNPMBinaryName returns the type of package manager used by the project
|
||||
func (po *ProjectOptions) GetNPMBinaryName() (PackageManager, error) {
|
||||
if po.FrontEnd == nil {
|
||||
return UNKNOWN, fmt.Errorf("No frontend specified in project options")
|
||||
}
|
||||
|
||||
if strings.Index(po.FrontEnd.Install, "npm") > -1 {
|
||||
return NPM, nil
|
||||
}
|
||||
|
||||
if strings.Index(po.FrontEnd.Install, "yarn") > -1 {
|
||||
return YARN, nil
|
||||
}
|
||||
|
||||
return UNKNOWN, nil
|
||||
}
|
||||
|
||||
// PromptForInputs asks the user to input project details
|
||||
func (po *ProjectOptions) PromptForInputs() error {
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
@@ -20,11 +19,7 @@ func Prompt(question string, defaultValue ...string) string {
|
||||
fmt.Printf(question + ": ")
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
input, _ := reader.ReadString('\n')
|
||||
EOL := "\n"
|
||||
if runtime.GOOS == "windows" {
|
||||
EOL = "\r\n"
|
||||
}
|
||||
input = strings.Replace(input, EOL, "", -1)
|
||||
input = strings.TrimSpace(input)
|
||||
|
||||
if input != "" {
|
||||
answer = input
|
||||
|
||||
@@ -3,7 +3,7 @@ package cmd
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/masterminds/semver"
|
||||
"github.com/Masterminds/semver"
|
||||
)
|
||||
|
||||
// SemanticVersion is a struct containing a semantic version
|
||||
|
||||
@@ -269,55 +269,35 @@ func CheckDependencies(logger *Logger) (bool, error) {
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var libraryChecker CheckPkgInstalled
|
||||
distroInfo := GetLinuxDistroInfo()
|
||||
|
||||
switch distroInfo.Distribution {
|
||||
case Ubuntu, Debian, Zorin, Parrot, Linuxmint, Elementary, Kali, Neon:
|
||||
libraryChecker = DpkgInstalled
|
||||
case Arch, Manjaro:
|
||||
libraryChecker = PacmanInstalled
|
||||
case CentOS, Fedora:
|
||||
libraryChecker = RpmInstalled
|
||||
case Gentoo:
|
||||
libraryChecker = EqueryInstalled
|
||||
case VoidLinux:
|
||||
libraryChecker = XbpsInstalled
|
||||
default:
|
||||
return false, RequestSupportForDistribution(distroInfo)
|
||||
}
|
||||
|
||||
for _, library := range *requiredLibraries {
|
||||
switch distroInfo.Distribution {
|
||||
case Ubuntu, Zorin, Debian:
|
||||
installed, err := DpkgInstalled(library.Name)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !installed {
|
||||
errors = true
|
||||
logger.Error("Library '%s' not found. %s", library.Name, library.Help)
|
||||
} else {
|
||||
logger.Green("Library '%s' installed.", library.Name)
|
||||
}
|
||||
case Arch:
|
||||
installed, err := PacmanInstalled(library.Name)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !installed {
|
||||
errors = true
|
||||
logger.Error("Library '%s' not found. %s", library.Name, library.Help)
|
||||
} else {
|
||||
logger.Green("Library '%s' installed.", library.Name)
|
||||
}
|
||||
case RedHat:
|
||||
installed, err := RpmInstalled(library.Name)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !installed {
|
||||
errors = true
|
||||
logger.Error("Library '%s' not found. %s", library.Name, library.Help)
|
||||
} else {
|
||||
logger.Green("Library '%s' installed.", library.Name)
|
||||
}
|
||||
case Gentoo:
|
||||
installed, err := EqueryInstalled(library.Name)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !installed {
|
||||
errors = true
|
||||
logger.Error("Library '%s' not found. %s", library.Name, library.Help)
|
||||
} else {
|
||||
logger.Green("Library '%s' installed.", library.Name)
|
||||
}
|
||||
default:
|
||||
return false, RequestSupportForDistribution(distroInfo, library.Name)
|
||||
installed, err := libraryChecker(library.Name)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !installed {
|
||||
errors = true
|
||||
logger.Error("Library '%s' not found. %s", library.Name, library.Help)
|
||||
} else {
|
||||
logger.Green("Library '%s' installed.", library.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ func NewTemplateHelper() *TemplateHelper {
|
||||
}
|
||||
}
|
||||
|
||||
// IsValidTemplate returns true if the given tempalte name resides on disk
|
||||
// IsValidTemplate returns true if the given template name resides on disk
|
||||
func (t *TemplateHelper) IsValidTemplate(templateName string) bool {
|
||||
pathToTemplate := filepath.Join(t.templateDir.fullPath, templateName)
|
||||
return t.fs.DirExists(pathToTemplate)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"@angular/platform-browser": "~8.0.1",
|
||||
"@angular/platform-browser-dynamic": "~8.0.1",
|
||||
"@angular/router": "~8.0.1",
|
||||
"@wailsapp/runtime": "^1.0.0",
|
||||
"ngx-build-plus": "^8.0.3",
|
||||
"rxjs": "~6.4.0",
|
||||
"tslib": "^1.9.0",
|
||||
|
||||
@@ -6,13 +6,13 @@ import { environment } from './environments/environment';
|
||||
|
||||
import 'zone.js'
|
||||
|
||||
import Bridge from './wailsbridge';
|
||||
import * as Wails from '@wailsapp/runtime';
|
||||
|
||||
if (environment.production) {
|
||||
enableProdMode();
|
||||
}
|
||||
|
||||
Bridge.Start(() => {
|
||||
Wails.Init(() => {
|
||||
platformBrowserDynamic().bootstrapModule(AppModule)
|
||||
.catch(err => console.error(err));
|
||||
});
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"core-js": "^3.1.4",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6",
|
||||
"wails-react-scripts": "3.0.1-2",
|
||||
"react-modal": "3.8.1"
|
||||
"react-modal": "3.8.1",
|
||||
"@wailsapp/runtime": "^1.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import 'core-js/stable';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
|
||||
import Bridge from "./wailsbridge";
|
||||
import * as Wails from '@wailsapp/runtime';
|
||||
|
||||
Bridge.Start(() => {
|
||||
Wails.Init(() => {
|
||||
ReactDOM.render(<App />, document.getElementById('app'));
|
||||
});
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^2.6.4",
|
||||
"vue": "^2.5.22"
|
||||
"vue": "^2.5.22",
|
||||
"@wailsapp/runtime": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "^3.4.0",
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import Vue from "vue";
|
||||
import App from "./App.vue";
|
||||
import Vue from 'vue';
|
||||
import App from './App.vue';
|
||||
|
||||
Vue.config.productionTip = false;
|
||||
Vue.config.devtools = true;
|
||||
|
||||
import Bridge from "./wailsbridge";
|
||||
import * as Wails from '@wailsapp/runtime';
|
||||
|
||||
Bridge.Start(() => {
|
||||
new Vue({
|
||||
render: h => h(App)
|
||||
}).$mount("#app");
|
||||
Wails.Init(() => {
|
||||
new Vue({
|
||||
render: h => h(App)
|
||||
}).$mount('#app');
|
||||
});
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
/*
|
||||
Wails Bridge (c) 2019-present Lea Anthony
|
||||
|
||||
This prod version is to get around having to rewrite your code
|
||||
for production. When doing a release build, this file will be used
|
||||
instead of the full version.
|
||||
*/
|
||||
|
||||
export default {
|
||||
// The main function
|
||||
// Passes the main Wails object to the callback if given.
|
||||
Start: function (callback) {
|
||||
if (callback) {
|
||||
window.wails.Events.On("wails:ready", callback);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -12,7 +12,8 @@
|
||||
"core-js": "^2.6.4",
|
||||
"material-design-icons-iconfont": "^5.0.1",
|
||||
"vue": "^2.5.22",
|
||||
"vuetify": "^1.5.14"
|
||||
"vuetify": "^1.5.14",
|
||||
"@wailsapp/runtime": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "^3.4.0",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'babel-polyfill';
|
||||
import Vue from "vue";
|
||||
import Vue from 'vue';
|
||||
|
||||
// Setup Vuetify
|
||||
import Vuetify from 'vuetify';
|
||||
@@ -7,15 +7,15 @@ Vue.use(Vuetify);
|
||||
import 'vuetify/dist/vuetify.min.css';
|
||||
import 'material-design-icons-iconfont';
|
||||
|
||||
import App from "./App.vue";
|
||||
import App from './App.vue';
|
||||
|
||||
Vue.config.productionTip = false;
|
||||
Vue.config.devtools = true;
|
||||
|
||||
import Bridge from "./wailsbridge";
|
||||
import * as Wails from '@wailsapp/runtime';
|
||||
|
||||
Bridge.Start(() => {
|
||||
new Vue({
|
||||
render: h => h(App)
|
||||
}).$mount("#app");
|
||||
Wails.Init(() => {
|
||||
new Vue({
|
||||
render: h => h(App)
|
||||
}).$mount('#app');
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package cmd
|
||||
|
||||
// Version - Wails version
|
||||
const Version = "v0.17.4-pre"
|
||||
const Version = "v0.18.7-pre"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/wailsapp/wails/cmd"
|
||||
@@ -24,7 +23,7 @@ func init() {
|
||||
|
||||
system := cmd.NewSystemHelper()
|
||||
err = system.Initialise()
|
||||
if err == nil {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -33,23 +32,9 @@ Create your first project by running 'wails init'.`
|
||||
if runtime.GOOS != "windows" {
|
||||
successMessage = "🚀 " + successMessage
|
||||
}
|
||||
// Platform check
|
||||
err = platformCheck()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check we have a cgo capable environment
|
||||
logger.Yellow("Checking for prerequisites...")
|
||||
var requiredProgramErrors bool
|
||||
requiredProgramErrors, err = checkRequiredPrograms()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Linux has library deps
|
||||
var libraryErrors bool
|
||||
libraryErrors, err = checkLibraries()
|
||||
// Chrck for programs and libraries dependencies
|
||||
errors, err := cmd.CheckDependencies(logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -60,76 +45,14 @@ Create your first project by running 'wails init'.`
|
||||
return err
|
||||
}
|
||||
|
||||
logger.White("")
|
||||
|
||||
// Check for errors
|
||||
var errors = libraryErrors || requiredProgramErrors
|
||||
if !errors {
|
||||
// CheckDependencies() returns !errors
|
||||
// so to get the right message in this
|
||||
// check we have to do it in reversed
|
||||
if errors {
|
||||
logger.Yellow(successMessage)
|
||||
}
|
||||
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
func platformCheck() error {
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
logger.Yellow("Detected Platform: OSX")
|
||||
case "windows":
|
||||
logger.Yellow("Detected Platform: Windows")
|
||||
case "linux":
|
||||
logger.Yellow("Detected Platform: Linux")
|
||||
default:
|
||||
return fmt.Errorf("Platform %s is currently not supported", runtime.GOOS)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkLibraries() (errors bool, err error) {
|
||||
if runtime.GOOS == "linux" {
|
||||
// Check library prerequisites
|
||||
requiredLibraries, err := cmd.GetRequiredLibraries()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
distroInfo := cmd.GetLinuxDistroInfo()
|
||||
for _, library := range *requiredLibraries {
|
||||
switch distroInfo.Distribution {
|
||||
case cmd.Ubuntu, cmd.Zorin, cmd.Debian:
|
||||
installed, err := cmd.DpkgInstalled(library.Name)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !installed {
|
||||
errors = true
|
||||
logger.Red("Library '%s' not found. %s", library.Name, library.Help)
|
||||
} else {
|
||||
logger.Green("Library '%s' installed.", library.Name)
|
||||
}
|
||||
default:
|
||||
return false, cmd.RequestSupportForDistribution(distroInfo, library.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func checkRequiredPrograms() (errors bool, err error) {
|
||||
requiredPrograms, err := cmd.GetRequiredPrograms()
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
errors = false
|
||||
programHelper := cmd.NewProgramHelper()
|
||||
for _, program := range *requiredPrograms {
|
||||
bin := programHelper.FindProgram(program.Name)
|
||||
if bin == nil {
|
||||
errors = true
|
||||
logger.Red("Program '%s' not found. %s", program.Name, program.Help)
|
||||
} else {
|
||||
logger.Green("Program '%s' found: %s", program.Name, bin.Path)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
408
cmd/wails/15_migrate.go
Normal file
408
cmd/wails/15_migrate.go
Normal file
@@ -0,0 +1,408 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/Masterminds/semver"
|
||||
"github.com/leaanthony/spinner"
|
||||
"github.com/wailsapp/wails/cmd"
|
||||
)
|
||||
|
||||
// Constants
|
||||
var checkSpinner = spinner.NewSpinner()
|
||||
var migrateProjectOptions = &cmd.ProjectOptions{}
|
||||
var migrateFS = cmd.NewFSHelper()
|
||||
var migrateGithub = cmd.NewGitHubHelper()
|
||||
var programHelper = cmd.NewProgramHelper()
|
||||
var lessThanV1 *semver.Constraints
|
||||
|
||||
// The user's go.mod
|
||||
var goMod string
|
||||
var goModFile string
|
||||
|
||||
// The user's main.js
|
||||
var mainJSFile string
|
||||
var mainJSContents string
|
||||
|
||||
// Frontend directory
|
||||
var frontEndDir string
|
||||
|
||||
func init() {
|
||||
|
||||
var dryrun bool
|
||||
var err error
|
||||
|
||||
lessThanV1, err = semver.NewConstraint("< v1.0.0")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// var forceRebuild = false
|
||||
checkSpinner.SetSpinSpeed(50)
|
||||
|
||||
commandDescription := `EXPERIMENTAL - This command attempts to migrate projects to the latest Wails version.`
|
||||
updateCmd := app.Command("migrate", "Migrate projects to latest Wails release").
|
||||
LongDescription(commandDescription).
|
||||
BoolFlag("dryrun", "Only display what would be done", &dryrun)
|
||||
|
||||
updateCmd.Action(func() error {
|
||||
|
||||
message := "Migrate Project"
|
||||
logger.PrintSmallBanner(message)
|
||||
logger.Red("WARNING: This is an experimental command. Ensure you have backups of your project!")
|
||||
logger.Red("It currently only supports npm based projects.")
|
||||
fmt.Println()
|
||||
|
||||
// Check project directory
|
||||
err := checkProjectDirectory()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Find Wails version from go.mod
|
||||
wailsVersion, err := getWailsVersion()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get latest stable version
|
||||
var latestVersion *semver.Version
|
||||
latestVersion, err = getLatestWailsVersion()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var canMigrate bool
|
||||
canMigrate, err = canMigrateVersion(wailsVersion, latestVersion)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !canMigrate {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check for wailsbridge
|
||||
wailsBridge, err := checkWailsBridge()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Is main.js using bridge.Init()
|
||||
canUpdateMainJS, err := checkMainJS()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: Check if we are using legacy js runtime
|
||||
|
||||
// Operations
|
||||
logger.Yellow("Operations to perform:")
|
||||
|
||||
logger.Yellowf(" - Update to Wails v%s\n", latestVersion)
|
||||
|
||||
if len(wailsBridge) > 0 {
|
||||
logger.Yellow(" - Delete wailsbridge.js")
|
||||
}
|
||||
|
||||
if canUpdateMainJS {
|
||||
logger.Yellow(" - Patch main.js")
|
||||
}
|
||||
|
||||
logger.Yellow(" - Ensure '@wailsapp/runtime` module is installed")
|
||||
|
||||
if dryrun {
|
||||
logger.White("Exiting: Dry Run")
|
||||
return nil
|
||||
}
|
||||
|
||||
logger.Red("*WARNING* About to modify your project!")
|
||||
logger.Red("Type 'YES' to continue: ")
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
scanner.Scan()
|
||||
input := scanner.Text()
|
||||
if input != "YES" {
|
||||
logger.Red("ABORTED!")
|
||||
return nil
|
||||
}
|
||||
|
||||
logger.Yellow("Let's do this!")
|
||||
|
||||
err = updateWailsVersion(wailsVersion, latestVersion)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(wailsBridge) > 0 {
|
||||
err = deleteWailsBridge(wailsBridge)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if canUpdateMainJS {
|
||||
err = patchMainJS()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Install runtime
|
||||
err = installWailsRuntime()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
logger.Yellow("Migration complete! Check project by running `wails build`.")
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func checkProjectDirectory() error {
|
||||
// Get versions
|
||||
checkSpinner.Start("Check Project Directory")
|
||||
|
||||
// Check we are in project directory
|
||||
err := migrateProjectOptions.LoadConfig(migrateFS.Cwd())
|
||||
if err != nil {
|
||||
checkSpinner.Error()
|
||||
return fmt.Errorf("Unable to find 'project.json'. Please check you are in a Wails project directory")
|
||||
}
|
||||
|
||||
checkSpinner.Success()
|
||||
return nil
|
||||
}
|
||||
|
||||
func getWailsVersion() (*semver.Version, error) {
|
||||
checkSpinner.Start("Get Wails Version")
|
||||
var result *semver.Version
|
||||
|
||||
// Load file
|
||||
var err error
|
||||
goModFile, err = filepath.Abs(filepath.Join(".", "go.mod"))
|
||||
if err != nil {
|
||||
checkSpinner.Error()
|
||||
return nil, fmt.Errorf("Unable to load go.mod at %s", goModFile)
|
||||
}
|
||||
goMod, err = migrateFS.LoadAsString(goModFile)
|
||||
if err != nil {
|
||||
checkSpinner.Error()
|
||||
return nil, fmt.Errorf("Unable to load go.mod")
|
||||
}
|
||||
|
||||
// Find wails version
|
||||
versionRegexp := regexp.MustCompile(`.*github.com/wailsapp/wails.*(v\d+.\d+.\d+)`)
|
||||
versions := versionRegexp.FindStringSubmatch(goMod)
|
||||
|
||||
if len(versions) != 2 {
|
||||
return nil, fmt.Errorf("Unable to determine Wails version")
|
||||
}
|
||||
|
||||
version := versions[1]
|
||||
result, err = semver.NewVersion(version)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Unable to parse Wails version: %s", version)
|
||||
}
|
||||
checkSpinner.Success("Found Wails Version: " + version)
|
||||
return result, nil
|
||||
|
||||
}
|
||||
|
||||
func canMigrateVersion(wailsVersion *semver.Version, latestVersion *semver.Version) (bool, error) {
|
||||
checkSpinner.Start("Checking ability to Migrate")
|
||||
|
||||
// Check if we are at the latest version!!!!
|
||||
if wailsVersion.Equal(latestVersion) || wailsVersion.GreaterThan(latestVersion) {
|
||||
checkSpinner.Errorf("Checking ability to Migrate: No! (v%s >= v%s)", wailsVersion, latestVersion)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Check for < v1.0.0
|
||||
if lessThanV1.Check(wailsVersion) {
|
||||
checkSpinner.Successf("Checking ability to Migrate: Yes! (v%s < v1.0.0)", wailsVersion)
|
||||
return true, nil
|
||||
}
|
||||
checkSpinner.Error("Unable to migrate")
|
||||
return false, fmt.Errorf("No migration rules for version %s", wailsVersion)
|
||||
}
|
||||
|
||||
func checkWailsBridge() (string, error) {
|
||||
checkSpinner.Start("Checking if legacy Wails Bridge present")
|
||||
|
||||
// Check frontend dir is available
|
||||
if migrateProjectOptions.FrontEnd == nil ||
|
||||
len(migrateProjectOptions.FrontEnd.Dir) == 0 ||
|
||||
!migrateFS.DirExists(migrateProjectOptions.FrontEnd.Dir) {
|
||||
checkSpinner.Error("Unable to determine frontend directory")
|
||||
return "", fmt.Errorf("Unable to determine frontend directory")
|
||||
}
|
||||
|
||||
frontEndDir = migrateProjectOptions.FrontEnd.Dir
|
||||
|
||||
wailsBridgePath, err := filepath.Abs(filepath.Join(".", frontEndDir, "src", "wailsbridge.js"))
|
||||
if err != nil {
|
||||
checkSpinner.Error(err.Error())
|
||||
return "", err
|
||||
}
|
||||
|
||||
// If it doesn't exist, return blank string
|
||||
if !migrateFS.FileExists(wailsBridgePath) {
|
||||
checkSpinner.Success("Checking if legacy Wails Bridge present: No")
|
||||
return "", nil
|
||||
}
|
||||
|
||||
checkSpinner.Success("Checking if legacy Wails Bridge present: Yes")
|
||||
return wailsBridgePath, nil
|
||||
|
||||
}
|
||||
|
||||
// This function determines if the main.js file using wailsbridge can be auto-updated
|
||||
func checkMainJS() (bool, error) {
|
||||
|
||||
checkSpinner.Start("Checking if main.js can be migrated")
|
||||
var err error
|
||||
|
||||
// Check main.js is there
|
||||
if migrateProjectOptions.FrontEnd == nil ||
|
||||
len(migrateProjectOptions.FrontEnd.Dir) == 0 ||
|
||||
!migrateFS.DirExists(migrateProjectOptions.FrontEnd.Dir) {
|
||||
checkSpinner.Error("Unable to determine frontend directory")
|
||||
return false, fmt.Errorf("Unable to determine frontend directory")
|
||||
}
|
||||
|
||||
frontEndDir = migrateProjectOptions.FrontEnd.Dir
|
||||
|
||||
mainJSFile, err = filepath.Abs(filepath.Join(".", frontEndDir, "src", "main.js"))
|
||||
if err != nil {
|
||||
checkSpinner.Error("Unable to find main.js")
|
||||
return false, err
|
||||
}
|
||||
|
||||
mainJSContents, err = migrateFS.LoadAsString(mainJSFile)
|
||||
if err != nil {
|
||||
checkSpinner.Error("Unable to load main.js")
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Check we have a line like: import Bridge from "./wailsbridge";
|
||||
if strings.Index(mainJSContents, `import Bridge from "./wailsbridge";`) == -1 {
|
||||
checkSpinner.Success("Checking if main.js can be migrated: No - Cannot find `import Bridge`")
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Check we have a line like: Bridge.Start(() => {
|
||||
if strings.Index(mainJSContents, `Bridge.Start(`) == -1 {
|
||||
checkSpinner.Success("Checking if main.js can be migrated: No - Cannot find `Bridge.Start`")
|
||||
return false, nil
|
||||
}
|
||||
checkSpinner.Success("Checking if main.js can be migrated: Yes")
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func getLatestWailsVersion() (*semver.Version, error) {
|
||||
checkSpinner.Start("Checking GitHub for latest Wails version")
|
||||
version, err := migrateGithub.GetLatestStableRelease()
|
||||
if err != nil {
|
||||
checkSpinner.Error("Checking GitHub for latest Wails version: Failed")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
checkSpinner.Successf("Checking GitHub for latest Wails version: v%s", version)
|
||||
return version.Version, nil
|
||||
}
|
||||
|
||||
func updateWailsVersion(currentVersion, latestVersion *semver.Version) error {
|
||||
// Patch go.mod
|
||||
checkSpinner.Start("Patching go.mod")
|
||||
|
||||
wailsModule := "github.com/wailsapp/wails"
|
||||
old := fmt.Sprintf("%s v%s", wailsModule, currentVersion)
|
||||
new := fmt.Sprintf("%s v%s", wailsModule, latestVersion)
|
||||
|
||||
goMod = strings.Replace(goMod, old, new, -1)
|
||||
err := ioutil.WriteFile(goModFile, []byte(goMod), 0600)
|
||||
if err != nil {
|
||||
checkSpinner.Error()
|
||||
return err
|
||||
}
|
||||
|
||||
checkSpinner.Success()
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteWailsBridge(bridgeFilename string) error {
|
||||
// Patch go.mod
|
||||
checkSpinner.Start("Delete legacy wailsbridge.js")
|
||||
|
||||
err := migrateFS.RemoveFile(bridgeFilename)
|
||||
if err != nil {
|
||||
checkSpinner.Error()
|
||||
return err
|
||||
}
|
||||
|
||||
checkSpinner.Success()
|
||||
return nil
|
||||
}
|
||||
|
||||
func patchMainJS() error {
|
||||
// Patch main.js
|
||||
checkSpinner.Start("Patching main.js")
|
||||
|
||||
// Patch import line
|
||||
oldImportLine := `import Bridge from "./wailsbridge";`
|
||||
newImportLine := `import * as Wails from "@wailsapp/runtime";`
|
||||
mainJSContents = strings.Replace(mainJSContents, oldImportLine, newImportLine, -1)
|
||||
|
||||
// Patch Start line
|
||||
oldStartLine := `Bridge.Start`
|
||||
newStartLine := `Wails.Init`
|
||||
mainJSContents = strings.Replace(mainJSContents, oldStartLine, newStartLine, -1)
|
||||
|
||||
err := ioutil.WriteFile(mainJSFile, []byte(mainJSContents), 0600)
|
||||
if err != nil {
|
||||
checkSpinner.Error()
|
||||
return err
|
||||
}
|
||||
|
||||
checkSpinner.Success()
|
||||
return nil
|
||||
}
|
||||
|
||||
func installWailsRuntime() error {
|
||||
|
||||
checkSpinner.Start("Installing @wailsapp/runtime module")
|
||||
|
||||
// Change to the frontend directory
|
||||
err := os.Chdir(frontEndDir)
|
||||
if err != nil {
|
||||
checkSpinner.Error()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Determine package manager
|
||||
packageManager, err := migrateProjectOptions.GetNPMBinaryName()
|
||||
if err != nil {
|
||||
checkSpinner.Error()
|
||||
return nil
|
||||
}
|
||||
|
||||
switch packageManager {
|
||||
case cmd.NPM:
|
||||
// npm install --save @wailsapp/runtime
|
||||
programHelper.InstallNPMPackage("@wailsapp/runtime", true)
|
||||
default:
|
||||
checkSpinner.Error()
|
||||
return fmt.Errorf("Unknown package manager")
|
||||
}
|
||||
|
||||
checkSpinner.Success()
|
||||
return nil
|
||||
}
|
||||
@@ -72,8 +72,17 @@ func init() {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Ensure that runtime init.js is the production version
|
||||
err = cmd.InstallProdRuntime(projectDir, projectOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Move to project directory
|
||||
err = os.Chdir(projectDir)
|
||||
if err != nil {
|
||||
|
||||
@@ -45,7 +45,7 @@ func init() {
|
||||
projectDir := fs.Cwd()
|
||||
|
||||
// Install the bridge library
|
||||
err = cmd.InstallBridge("serve", projectDir, projectOptions)
|
||||
err = cmd.InstallBridge(projectDir, projectOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -42,12 +42,64 @@ To help you in this process, we will ask for some information, add Go/Wails deta
|
||||
gomodule = "(Not Set)"
|
||||
}
|
||||
|
||||
// get version numbers for GCC, node & npm
|
||||
program := cmd.NewProgramHelper()
|
||||
// string helpers
|
||||
var gccVersion, nodeVersion, npmVersion string
|
||||
|
||||
// choose between OS (mac,linux,win)
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
gcc := program.FindProgram("gcc")
|
||||
if gcc != nil {
|
||||
stdout, _, _, _ := gcc.Run("-dumpversion")
|
||||
gccVersion = strings.TrimSpace(stdout)
|
||||
}
|
||||
case "linux":
|
||||
// for linux we have to collect
|
||||
// the distribution name
|
||||
distroInfo := cmd.GetLinuxDistroInfo()
|
||||
linuxDB := cmd.NewLinuxDB()
|
||||
distro := linuxDB.GetDistro(distroInfo.ID)
|
||||
release := distro.GetRelease(distroInfo.Release)
|
||||
gccVersionCommand := release.GccVersionCommand
|
||||
|
||||
gcc := program.FindProgram("gcc")
|
||||
if gcc != nil {
|
||||
stdout, _, _, _ := gcc.Run(gccVersionCommand)
|
||||
gccVersion = strings.TrimSpace(stdout)
|
||||
}
|
||||
case "windows":
|
||||
gcc := program.FindProgram("gcc")
|
||||
if gcc != nil {
|
||||
stdout, _, _, _ := gcc.Run("-dumpversion")
|
||||
gccVersion = strings.TrimSpace(stdout)
|
||||
}
|
||||
}
|
||||
|
||||
npm := program.FindProgram("npm")
|
||||
if npm != nil {
|
||||
stdout, _, _, _ := npm.Run("--version")
|
||||
nodeVersion = stdout
|
||||
nodeVersion = nodeVersion[:len(nodeVersion)-1]
|
||||
}
|
||||
|
||||
node := program.FindProgram("node")
|
||||
if node != nil {
|
||||
stdout, _, _, _ := node.Run("--version")
|
||||
npmVersion = stdout
|
||||
npmVersion = npmVersion[:len(npmVersion)-1]
|
||||
}
|
||||
|
||||
str.WriteString("\n| Name | Value |\n| ----- | ----- |\n")
|
||||
str.WriteString(fmt.Sprintf("| Wails Version | %s |\n", cmd.Version))
|
||||
str.WriteString(fmt.Sprintf("| Go Version | %s |\n", runtime.Version()))
|
||||
str.WriteString(fmt.Sprintf("| Platform | %s |\n", runtime.GOOS))
|
||||
str.WriteString(fmt.Sprintf("| Arch | %s |\n", runtime.GOARCH))
|
||||
str.WriteString(fmt.Sprintf("| GO111MODULE | %s |\n", gomodule))
|
||||
str.WriteString(fmt.Sprintf("| GCC | %s |\n", gccVersion))
|
||||
str.WriteString(fmt.Sprintf("| Npm | %s |\n", npmVersion))
|
||||
str.WriteString(fmt.Sprintf("| Node | %s |\n", nodeVersion))
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println("Processing template and preparing for upload.")
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/wailsapp/wails/cmd"
|
||||
)
|
||||
|
||||
@@ -15,5 +18,9 @@ func main() {
|
||||
err := app.Run()
|
||||
if err != nil {
|
||||
logger.Error(err.Error())
|
||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||
os.Exit(exitErr.ExitCode())
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package wails
|
||||
|
||||
import (
|
||||
"github.com/leaanthony/mewn"
|
||||
"github.com/wailsapp/wails/runtime"
|
||||
)
|
||||
|
||||
// AppConfig is the configuration structure used when creating a Wails App object
|
||||
type AppConfig struct {
|
||||
@@ -29,7 +33,7 @@ func (a *AppConfig) GetTitle() string {
|
||||
return a.Title
|
||||
}
|
||||
|
||||
// GetDefaultHTML returns the desired window title
|
||||
// GetDefaultHTML returns the default HTML
|
||||
func (a *AppConfig) GetDefaultHTML() string {
|
||||
return a.defaultHTML
|
||||
}
|
||||
@@ -64,7 +68,7 @@ func (a *AppConfig) merge(in *AppConfig) error {
|
||||
a.CSS = in.CSS
|
||||
}
|
||||
if in.Title != "" {
|
||||
a.Title = in.Title
|
||||
a.Title = runtime.ProcessEncoding(in.Title)
|
||||
}
|
||||
|
||||
if in.Colour != "" {
|
||||
@@ -95,6 +99,7 @@ func newConfig(userConfig *AppConfig) (*AppConfig, error) {
|
||||
Resizable: true,
|
||||
Title: "My Wails App",
|
||||
Colour: "#FFF", // White by default
|
||||
HTML: mewn.String("./runtime/assets/default.html"),
|
||||
}
|
||||
|
||||
if userConfig != nil {
|
||||
|
||||
10
go.mod
10
go.mod
@@ -1,7 +1,8 @@
|
||||
module github.com/wailsapp/wails
|
||||
|
||||
require (
|
||||
github.com/Masterminds/semver v1.4.2 // indirect
|
||||
github.com/Masterminds/semver v1.4.2
|
||||
github.com/abadojack/whatlanggo v1.0.1
|
||||
github.com/dchest/cssmin v0.0.0-20151210170030-fb8d9b44afdc // indirect
|
||||
github.com/dchest/htmlmin v0.0.0-20150526090704-e254725e81ac
|
||||
github.com/dchest/jsmin v0.0.0-20160823214000-faeced883947 // indirect
|
||||
@@ -14,7 +15,6 @@ require (
|
||||
github.com/leaanthony/mewn v0.10.7
|
||||
github.com/leaanthony/slicer v1.3.2
|
||||
github.com/leaanthony/spinner v0.5.3
|
||||
github.com/masterminds/semver v1.4.2
|
||||
github.com/mattn/go-colorable v0.1.1 // indirect
|
||||
github.com/mattn/go-isatty v0.0.7 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
@@ -23,9 +23,11 @@ require (
|
||||
github.com/pkg/errors v0.8.1 // indirect
|
||||
github.com/sirupsen/logrus v1.4.1
|
||||
github.com/stretchr/testify v1.3.0 // indirect
|
||||
github.com/wailsapp/webview v0.2.7
|
||||
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 // indirect
|
||||
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5 // indirect
|
||||
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862
|
||||
golang.org/x/text v0.3.0
|
||||
gopkg.in/AlecAivazis/survey.v1 v1.8.4
|
||||
)
|
||||
gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22
|
||||
)
|
||||
20
go.sum
20
go.sum
@@ -2,6 +2,8 @@ github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITg
|
||||
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
|
||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
|
||||
github.com/abadojack/whatlanggo v1.0.1 h1:19N6YogDnf71CTHm3Mp2qhYfkRdyvbgwWdd2EPxJRG4=
|
||||
github.com/abadojack/whatlanggo v1.0.1/go.mod h1:66WiQbSbJBIlOZMsvbKe5m6pzQovxCH9B/K8tQB2uoc=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -25,7 +27,6 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/kennygrant/sanitize v1.2.4 h1:gN25/otpP5vAsO2djbMhF/LQX6R7+O1TB4yv8NzpJ3o=
|
||||
github.com/kennygrant/sanitize v1.2.4/go.mod h1:LGsjYYtgxbetdg5owWB2mpgUL6e2nfw2eObZ0u0qvak=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
@@ -41,14 +42,10 @@ github.com/leaanthony/synx v0.1.0 h1:R0lmg2w6VMb8XcotOwAe5DLyzwjLrskNkwU7LLWsyL8
|
||||
github.com/leaanthony/synx v0.1.0/go.mod h1:Iz7eybeeG8bdq640iR+CwYb8p+9EOsgMWghkSRyZcqs=
|
||||
github.com/leaanthony/wincursor v0.1.0 h1:Dsyp68QcF5cCs65AMBmxoYNEm0n8K7mMchG6a8fYxf8=
|
||||
github.com/leaanthony/wincursor v0.1.0/go.mod h1:7TVwwrzSH/2Y9gLOGH+VhA+bZhoWXBRgbGNTMk+yimE=
|
||||
github.com/masterminds/semver v1.4.2 h1:BgrAYDjlAebjtOwS7C/1QZoh5WgyXx4b59ydc+Ph8xI=
|
||||
github.com/masterminds/semver v1.4.2/go.mod h1:s7KNT9fnd7edGzwwP7RBX4H0v/CYd5qdOLfkL1V75yg=
|
||||
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc=
|
||||
@@ -73,11 +70,9 @@ github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/wailsapp/webview v0.2.7 h1:fN5L5H9Oivg9IJPk7uaXQnjqB68Fny11ZWkIaTIZHmk=
|
||||
github.com/wailsapp/webview v0.2.7/go.mod h1:XO9HJbKWokDxUYTWQEBCYg95n/To1v7PxvanDNVf8hY=
|
||||
github.com/zserge/webview v0.0.0-20190123072648-16c93bcaeaeb/go.mod h1:a1CV8KR4Dd1eP2g+mEijGOp+HKczwdKHWyx0aPHKvo4=
|
||||
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=
|
||||
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
@@ -86,14 +81,17 @@ golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5 h1:6M3SDHlHHDCx2PcQw3S4KsR17
|
||||
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
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 h1:pf3XwC90UUdNPYWZdFjhGBE7DUFuK3Ct1zWmZ65QN30=
|
||||
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862 h1:rM0ROo5vb9AdYJi1110yjWGMej9ITfKddS89P3Fkhug=
|
||||
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862/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=
|
||||
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=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22 h1:0efs3hwEZhFKsCoP8l6dDB1AZWMgnEl3yWXWRZTOaEA=
|
||||
gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
|
||||
"github.com/wailsapp/wails/lib/logger"
|
||||
"github.com/wailsapp/wails/lib/messages"
|
||||
"github.com/wailsapp/wails/runtime/go/runtime"
|
||||
"github.com/wailsapp/wails/runtime"
|
||||
)
|
||||
|
||||
type internalMethods struct {
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
"reflect"
|
||||
"unicode"
|
||||
|
||||
"github.com/wailsapp/wails/lib/interfaces"
|
||||
"github.com/wailsapp/wails/lib/logger"
|
||||
"github.com/wailsapp/wails/lib/messages"
|
||||
"github.com/wailsapp/wails/lib/interfaces"
|
||||
)
|
||||
|
||||
// Manager handles method binding
|
||||
@@ -16,6 +16,7 @@ type Manager struct {
|
||||
functions map[string]*boundFunction
|
||||
internalMethods *internalMethods
|
||||
initMethods []*boundMethod
|
||||
shutdownMethods []*boundMethod
|
||||
log *logger.CustomLogger
|
||||
renderer interfaces.Renderer
|
||||
runtime interfaces.Runtime // The runtime object to pass to bound structs
|
||||
@@ -127,6 +128,9 @@ func (b *Manager) bindMethod(object interface{}) error {
|
||||
if newMethod.isWailsInit {
|
||||
b.log.Debugf("Detected WailsInit function: %s", fullMethodName)
|
||||
b.initMethods = append(b.initMethods, newMethod)
|
||||
} else if newMethod.isWailsShutdown {
|
||||
b.log.Debugf("Detected WailsShutdown function: %s", fullMethodName)
|
||||
b.shutdownMethods = append(b.shutdownMethods, newMethod)
|
||||
} else {
|
||||
// Save boundMethod
|
||||
b.log.Infof("Bound Method: %s()", fullMethodName)
|
||||
@@ -195,7 +199,11 @@ func (b *Manager) processFunctionCall(callData *messages.CallData) (interface{},
|
||||
return nil, errorResult.Interface().(error)
|
||||
}
|
||||
}
|
||||
return result[0].Interface(), nil
|
||||
// fmt.Printf("result = '%+v'\n", result)
|
||||
if len(result) > 0 {
|
||||
return result[0].Interface(), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (b *Manager) processMethodCall(callData *messages.CallData) (interface{}, error) {
|
||||
@@ -288,3 +296,13 @@ func (b *Manager) callWailsInitMethods() error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Shutdown the binding manager
|
||||
func (b *Manager) Shutdown() {
|
||||
b.log.Debug("Shutdown called")
|
||||
for _, method := range b.shutdownMethods {
|
||||
b.log.Debugf("Calling Shutdown for method: %s", method.fullName)
|
||||
method.call("[]")
|
||||
}
|
||||
b.log.Debug("Shutdown complete")
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ type boundMethod struct {
|
||||
log *logger.CustomLogger
|
||||
hasErrorReturnType bool // Indicates if there is an error return type
|
||||
isWailsInit bool
|
||||
isWailsShutdown bool
|
||||
}
|
||||
|
||||
// Creates a new bound method based on the given method + type
|
||||
@@ -39,6 +40,11 @@ func newBoundMethod(name string, fullName string, method reflect.Value, objectTy
|
||||
err = result.processWailsInit()
|
||||
}
|
||||
|
||||
// Are we a WailsShutdown method?
|
||||
if result.Name == "WailsShutdown" {
|
||||
err = result.processWailsShutdown()
|
||||
}
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
@@ -211,3 +217,20 @@ func (b *boundMethod) processWailsInit() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *boundMethod) processWailsShutdown() error {
|
||||
// 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))
|
||||
}
|
||||
|
||||
// We must have only 1 output, it must be error
|
||||
if len(b.returnTypes) != 0 {
|
||||
return fmt.Errorf("Invalid WailsShutdown() definition. Expected 0 return types, but got %d", len(b.returnTypes))
|
||||
}
|
||||
|
||||
// We are indeed a wails Shutdown method
|
||||
b.isWailsShutdown = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,18 +3,21 @@ package event
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/wailsapp/wails/lib/interfaces"
|
||||
"github.com/wailsapp/wails/lib/logger"
|
||||
"github.com/wailsapp/wails/lib/messages"
|
||||
"github.com/wailsapp/wails/lib/interfaces"
|
||||
)
|
||||
|
||||
// Manager handles and processes events
|
||||
type Manager struct {
|
||||
incomingEvents chan *messages.EventData
|
||||
listeners map[string][]*eventListener
|
||||
exit bool
|
||||
running bool
|
||||
log *logger.CustomLogger
|
||||
renderer interfaces.Renderer // Messages will be dispatched to the frontend
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
// NewManager creates a new event manager with a 100 event buffer
|
||||
@@ -22,7 +25,7 @@ func NewManager() interfaces.EventManager {
|
||||
return &Manager{
|
||||
incomingEvents: make(chan *messages.EventData, 100),
|
||||
listeners: make(map[string][]*eventListener),
|
||||
exit: false,
|
||||
running: false,
|
||||
log: logger.NewCustomLogger("Events"),
|
||||
}
|
||||
}
|
||||
@@ -87,15 +90,14 @@ func (e *Manager) Start(renderer interfaces.Renderer) {
|
||||
// Store renderer
|
||||
e.renderer = renderer
|
||||
|
||||
// Set up waitgroup so we can wait for goroutine to start
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
// Set up waitgroup so we can wait for goroutine to quit
|
||||
e.running = true
|
||||
e.wg.Add(1)
|
||||
|
||||
// Run main loop in separate goroutine
|
||||
go func() {
|
||||
wg.Done()
|
||||
e.log.Info("Listening")
|
||||
for e.exit == false {
|
||||
for e.running {
|
||||
// TODO: Listen for application exit
|
||||
select {
|
||||
case event := <-e.incomingEvents:
|
||||
@@ -139,14 +141,18 @@ func (e *Manager) Start(renderer interfaces.Renderer) {
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
e.wg.Done()
|
||||
}()
|
||||
|
||||
// Wait for goroutine to start
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func (e *Manager) stop() {
|
||||
e.exit = true
|
||||
// Shutdown is called when exiting the Application
|
||||
func (e *Manager) Shutdown() {
|
||||
e.log.Debug("Shutting Down")
|
||||
e.running = false
|
||||
e.log.Debug("Waiting for main loop to exit")
|
||||
e.wg.Wait()
|
||||
}
|
||||
|
||||
@@ -7,4 +7,5 @@ type BindingManager interface {
|
||||
Bind(object interface{})
|
||||
Start(renderer Renderer, runtime Runtime) error
|
||||
ProcessCall(callData *messages.CallData) (result interface{}, err error)
|
||||
Shutdown()
|
||||
}
|
||||
|
||||
@@ -8,4 +8,5 @@ type EventManager interface {
|
||||
Emit(eventName string, optionalData ...interface{})
|
||||
On(eventName string, callback func(...interface{}))
|
||||
Start(Renderer)
|
||||
Shutdown()
|
||||
}
|
||||
|
||||
@@ -5,4 +5,5 @@ type IPCManager interface {
|
||||
BindRenderer(Renderer)
|
||||
Dispatch(message string)
|
||||
Start(eventManager EventManager, bindingManager BindingManager)
|
||||
Shutdown()
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package ipc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/wailsapp/wails/lib/interfaces"
|
||||
"github.com/wailsapp/wails/lib/logger"
|
||||
@@ -12,18 +14,20 @@ import (
|
||||
type Manager struct {
|
||||
renderer interfaces.Renderer // The renderer
|
||||
messageQueue chan *ipcMessage
|
||||
// quitChannel chan struct{}
|
||||
quitChannel chan struct{}
|
||||
// signals chan os.Signal
|
||||
log *logger.CustomLogger
|
||||
eventManager interfaces.EventManager
|
||||
bindingManager interfaces.BindingManager
|
||||
running bool
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
// NewManager creates a new IPC Manager
|
||||
func NewManager() interfaces.IPCManager {
|
||||
result := &Manager{
|
||||
messageQueue: make(chan *ipcMessage, 100),
|
||||
// quitChannel: make(chan struct{}),
|
||||
quitChannel: make(chan struct{}),
|
||||
// signals: make(chan os.Signal, 1),
|
||||
log: logger.NewCustomLogger("IPC"),
|
||||
}
|
||||
@@ -44,9 +48,12 @@ func (i *Manager) Start(eventManager interfaces.EventManager, bindingManager int
|
||||
|
||||
i.log.Info("Starting")
|
||||
// signal.Notify(manager.signals, os.Interrupt)
|
||||
i.running = true
|
||||
|
||||
// Keep track of this goroutine
|
||||
i.wg.Add(1)
|
||||
go func() {
|
||||
running := true
|
||||
for running {
|
||||
for i.running {
|
||||
select {
|
||||
case incomingMessage := <-i.messageQueue:
|
||||
i.log.DebugFields("Processing message", logger.Fields{
|
||||
@@ -94,17 +101,17 @@ func (i *Manager) Start(eventManager interfaces.EventManager, bindingManager int
|
||||
logdata := incomingMessage.Payload.(*messages.LogData)
|
||||
switch logdata.Level {
|
||||
case "info":
|
||||
i.log.Info(logdata.Message)
|
||||
logger.GlobalLogger.Info(logdata.Message)
|
||||
case "debug":
|
||||
i.log.Debug(logdata.Message)
|
||||
logger.GlobalLogger.Debug(logdata.Message)
|
||||
case "warning":
|
||||
i.log.Warn(logdata.Message)
|
||||
logger.GlobalLogger.Warn(logdata.Message)
|
||||
case "error":
|
||||
i.log.Error(logdata.Message)
|
||||
logger.GlobalLogger.Error(logdata.Message)
|
||||
case "fatal":
|
||||
i.log.Fatal(logdata.Message)
|
||||
logger.GlobalLogger.Fatal(logdata.Message)
|
||||
default:
|
||||
i.log.ErrorFields("Invalid log level sent", logger.Fields{
|
||||
logger.ErrorFields("Invalid log level sent", logger.Fields{
|
||||
"level": logdata.Level,
|
||||
"message": logdata.Message,
|
||||
})
|
||||
@@ -117,15 +124,12 @@ func (i *Manager) Start(eventManager interfaces.EventManager, bindingManager int
|
||||
i.log.DebugFields("Finished processing message", logger.Fields{
|
||||
"1D": &incomingMessage,
|
||||
})
|
||||
// case <-manager.quitChannel:
|
||||
// Debug("[MessageQueue] Quit caught")
|
||||
// running = false
|
||||
// case <-manager.signals:
|
||||
// Debug("[MessageQueue] Signal caught")
|
||||
// running = false
|
||||
default:
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
i.log.Debug("Stopping")
|
||||
i.wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -167,3 +171,11 @@ func (i *Manager) SendResponse(response *ipcResponse) error {
|
||||
// Call back to the front end
|
||||
return i.renderer.Callback(data)
|
||||
}
|
||||
|
||||
// Shutdown is called when exiting the Application
|
||||
func (i *Manager) Shutdown() {
|
||||
i.log.Debug("Shutdown called")
|
||||
i.running = false
|
||||
i.log.Debug("Waiting of main loop shutdown")
|
||||
i.wg.Wait()
|
||||
}
|
||||
|
||||
@@ -15,90 +15,90 @@ func NewCustomLogger(prefix string) *CustomLogger {
|
||||
|
||||
// Info level message
|
||||
func (c *CustomLogger) Info(message string) {
|
||||
logger.Info(c.prefix + message)
|
||||
GlobalLogger.Info(c.prefix + message)
|
||||
}
|
||||
|
||||
// Infof - formatted message
|
||||
func (c *CustomLogger) Infof(message string, args ...interface{}) {
|
||||
logger.Infof(c.prefix+message, args...)
|
||||
GlobalLogger.Infof(c.prefix+message, args...)
|
||||
}
|
||||
|
||||
// InfoFields - message with fields
|
||||
func (c *CustomLogger) InfoFields(message string, fields Fields) {
|
||||
logger.WithFields(map[string]interface{}(fields)).Info(c.prefix + message)
|
||||
GlobalLogger.WithFields(map[string]interface{}(fields)).Info(c.prefix + message)
|
||||
}
|
||||
|
||||
// Debug level message
|
||||
func (c *CustomLogger) Debug(message string) {
|
||||
logger.Debug(c.prefix + message)
|
||||
GlobalLogger.Debug(c.prefix + message)
|
||||
}
|
||||
|
||||
// Debugf - formatted message
|
||||
func (c *CustomLogger) Debugf(message string, args ...interface{}) {
|
||||
logger.Debugf(c.prefix+message, args...)
|
||||
GlobalLogger.Debugf(c.prefix+message, args...)
|
||||
}
|
||||
|
||||
// DebugFields - message with fields
|
||||
func (c *CustomLogger) DebugFields(message string, fields Fields) {
|
||||
logger.WithFields(map[string]interface{}(fields)).Debug(c.prefix + message)
|
||||
GlobalLogger.WithFields(map[string]interface{}(fields)).Debug(c.prefix + message)
|
||||
}
|
||||
|
||||
// Warn level message
|
||||
func (c *CustomLogger) Warn(message string) {
|
||||
logger.Warn(c.prefix + message)
|
||||
GlobalLogger.Warn(c.prefix + message)
|
||||
}
|
||||
|
||||
// Warnf - formatted message
|
||||
func (c *CustomLogger) Warnf(message string, args ...interface{}) {
|
||||
logger.Warnf(c.prefix+message, args...)
|
||||
GlobalLogger.Warnf(c.prefix+message, args...)
|
||||
}
|
||||
|
||||
// WarnFields - message with fields
|
||||
func (c *CustomLogger) WarnFields(message string, fields Fields) {
|
||||
logger.WithFields(map[string]interface{}(fields)).Warn(c.prefix + message)
|
||||
GlobalLogger.WithFields(map[string]interface{}(fields)).Warn(c.prefix + message)
|
||||
}
|
||||
|
||||
// Error level message
|
||||
func (c *CustomLogger) Error(message string) {
|
||||
logger.Error(c.prefix + message)
|
||||
GlobalLogger.Error(c.prefix + message)
|
||||
}
|
||||
|
||||
// Errorf - formatted message
|
||||
func (c *CustomLogger) Errorf(message string, args ...interface{}) {
|
||||
logger.Errorf(c.prefix+message, args...)
|
||||
GlobalLogger.Errorf(c.prefix+message, args...)
|
||||
}
|
||||
|
||||
// ErrorFields - message with fields
|
||||
func (c *CustomLogger) ErrorFields(message string, fields Fields) {
|
||||
logger.WithFields(map[string]interface{}(fields)).Error(c.prefix + message)
|
||||
GlobalLogger.WithFields(map[string]interface{}(fields)).Error(c.prefix + message)
|
||||
}
|
||||
|
||||
// Fatal level message
|
||||
func (c *CustomLogger) Fatal(message string) {
|
||||
logger.Fatal(c.prefix + message)
|
||||
GlobalLogger.Fatal(c.prefix + message)
|
||||
}
|
||||
|
||||
// Fatalf - formatted message
|
||||
func (c *CustomLogger) Fatalf(message string, args ...interface{}) {
|
||||
logger.Fatalf(c.prefix+message, args...)
|
||||
GlobalLogger.Fatalf(c.prefix+message, args...)
|
||||
}
|
||||
|
||||
// FatalFields - message with fields
|
||||
func (c *CustomLogger) FatalFields(message string, fields Fields) {
|
||||
logger.WithFields(map[string]interface{}(fields)).Fatal(c.prefix + message)
|
||||
GlobalLogger.WithFields(map[string]interface{}(fields)).Fatal(c.prefix + message)
|
||||
}
|
||||
|
||||
// Panic level message
|
||||
func (c *CustomLogger) Panic(message string) {
|
||||
logger.Panic(c.prefix + message)
|
||||
GlobalLogger.Panic(c.prefix + message)
|
||||
}
|
||||
|
||||
// Panicf - formatted message
|
||||
func (c *CustomLogger) Panicf(message string, args ...interface{}) {
|
||||
logger.Panicf(c.prefix+message, args...)
|
||||
GlobalLogger.Panicf(c.prefix+message, args...)
|
||||
}
|
||||
|
||||
// PanicFields - message with fields
|
||||
func (c *CustomLogger) PanicFields(message string, fields Fields) {
|
||||
logger.WithFields(map[string]interface{}(fields)).Panic(c.prefix + message)
|
||||
GlobalLogger.WithFields(map[string]interface{}(fields)).Panic(c.prefix + message)
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Global logger reference
|
||||
var logger = logrus.New()
|
||||
// GlobalLogger is the global logger
|
||||
var GlobalLogger = logrus.New()
|
||||
|
||||
// Fields is used by the customLogger object to output
|
||||
// fields along with a message
|
||||
@@ -16,27 +16,32 @@ type Fields map[string]interface{}
|
||||
|
||||
// Default options for the global logger
|
||||
func init() {
|
||||
logger.SetOutput(os.Stdout)
|
||||
logger.SetLevel(logrus.DebugLevel)
|
||||
GlobalLogger.SetOutput(os.Stdout)
|
||||
GlobalLogger.SetLevel(logrus.DebugLevel)
|
||||
}
|
||||
|
||||
// ErrorFields is a helper for logging fields to the global logger
|
||||
func ErrorFields(message string, fields Fields) {
|
||||
GlobalLogger.WithFields(map[string]interface{}(fields)).Error(message)
|
||||
}
|
||||
|
||||
// SetLogLevel sets the log level to the given level
|
||||
func SetLogLevel(level string) {
|
||||
switch strings.ToLower(level) {
|
||||
case "info":
|
||||
logger.SetLevel(logrus.InfoLevel)
|
||||
GlobalLogger.SetLevel(logrus.InfoLevel)
|
||||
case "debug":
|
||||
logger.SetLevel(logrus.DebugLevel)
|
||||
GlobalLogger.SetLevel(logrus.DebugLevel)
|
||||
case "warn":
|
||||
logger.SetLevel(logrus.WarnLevel)
|
||||
GlobalLogger.SetLevel(logrus.WarnLevel)
|
||||
case "error":
|
||||
logger.SetLevel(logrus.ErrorLevel)
|
||||
GlobalLogger.SetLevel(logrus.ErrorLevel)
|
||||
case "fatal":
|
||||
logger.SetLevel(logrus.FatalLevel)
|
||||
GlobalLogger.SetLevel(logrus.FatalLevel)
|
||||
case "panic":
|
||||
logger.SetLevel(logrus.PanicLevel)
|
||||
GlobalLogger.SetLevel(logrus.PanicLevel)
|
||||
default:
|
||||
logger.SetLevel(logrus.DebugLevel)
|
||||
logger.Warnf("Log level '%s' not recognised. Setting to Debug.", level)
|
||||
GlobalLogger.SetLevel(logrus.DebugLevel)
|
||||
GlobalLogger.Warnf("Log level '%s' not recognised. Setting to Debug.", level)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,9 +31,9 @@ func (m messageType) toString() string {
|
||||
return [...]string{"j", "s", "h", "n", "b", "c", "w"}[m]
|
||||
}
|
||||
|
||||
// Headless is a backend that opens a local web server
|
||||
// Bridge is a backend that opens a local web server
|
||||
// and renders the files over a websocket
|
||||
type Headless struct {
|
||||
type Bridge struct {
|
||||
// Common
|
||||
log *logger.CustomLogger
|
||||
ipcManager interfaces.IPCManager
|
||||
@@ -41,7 +41,7 @@ type Headless struct {
|
||||
eventManager interfaces.EventManager
|
||||
bindingCache []string
|
||||
|
||||
// Headless specific
|
||||
// Bridge specific
|
||||
initialisationJS []string
|
||||
server *http.Server
|
||||
theConnection *websocket.Conn
|
||||
@@ -50,8 +50,8 @@ type Headless struct {
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
// Initialise the Headless Renderer
|
||||
func (h *Headless) Initialise(appConfig interfaces.AppConfig, ipcManager interfaces.IPCManager, eventManager interfaces.EventManager) error {
|
||||
// Initialise the Bridge Renderer
|
||||
func (h *Bridge) Initialise(appConfig interfaces.AppConfig, ipcManager interfaces.IPCManager, eventManager interfaces.EventManager) error {
|
||||
h.ipcManager = ipcManager
|
||||
h.appConfig = appConfig
|
||||
h.eventManager = eventManager
|
||||
@@ -60,7 +60,7 @@ func (h *Headless) Initialise(appConfig interfaces.AppConfig, ipcManager interfa
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Headless) evalJS(js string, mtype messageType) error {
|
||||
func (h *Bridge) evalJS(js string, mtype messageType) error {
|
||||
|
||||
message := mtype.toString() + js
|
||||
|
||||
@@ -74,7 +74,7 @@ func (h *Headless) evalJS(js string, mtype messageType) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Headless) injectCSS(css string) {
|
||||
func (h *Bridge) injectCSS(css string) {
|
||||
// Minify css to overcome issues in the browser with carriage returns
|
||||
minified, err := htmlmin.Minify([]byte(css), &htmlmin.Options{
|
||||
MinifyStyles: true,
|
||||
@@ -90,7 +90,7 @@ func (h *Headless) injectCSS(css string) {
|
||||
h.evalJS(inject, cssMessage)
|
||||
}
|
||||
|
||||
func (h *Headless) wsBridgeHandler(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *Bridge) wsBridgeHandler(w http.ResponseWriter, r *http.Request) {
|
||||
conn, err := websocket.Upgrade(w, r, w.Header(), 1024, 1024)
|
||||
if err != nil {
|
||||
http.Error(w, "Could not open websocket connection", http.StatusBadRequest)
|
||||
@@ -105,7 +105,7 @@ func (h *Headless) wsBridgeHandler(w http.ResponseWriter, r *http.Request) {
|
||||
go h.start(conn)
|
||||
}
|
||||
|
||||
func (h *Headless) sendMessage(conn *websocket.Conn, msg string) {
|
||||
func (h *Bridge) sendMessage(conn *websocket.Conn, msg string) {
|
||||
|
||||
h.lock.Lock()
|
||||
defer h.lock.Unlock()
|
||||
@@ -115,12 +115,12 @@ func (h *Headless) sendMessage(conn *websocket.Conn, msg string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Headless) start(conn *websocket.Conn) {
|
||||
func (h *Bridge) start(conn *websocket.Conn) {
|
||||
|
||||
// set external.invoke
|
||||
h.log.Infof("Connected to frontend.")
|
||||
|
||||
wailsRuntime := mewn.String("../../runtime/js/dist/wails.js")
|
||||
wailsRuntime := mewn.String("../../runtime/assets/wails.js")
|
||||
h.evalJS(wailsRuntime, wailsRuntimeMessage)
|
||||
|
||||
// Inject bindings
|
||||
@@ -147,8 +147,8 @@ func (h *Headless) start(conn *websocket.Conn) {
|
||||
}
|
||||
}
|
||||
|
||||
// Run the app in headless mode!
|
||||
func (h *Headless) Run() error {
|
||||
// Run the app in Bridge mode!
|
||||
func (h *Bridge) Run() error {
|
||||
h.server = &http.Server{Addr: ":34115"}
|
||||
http.HandleFunc("/bridge", h.wsBridgeHandler)
|
||||
|
||||
@@ -156,46 +156,46 @@ func (h *Headless) Run() error {
|
||||
h.log.Info("The frontend will connect automatically.")
|
||||
|
||||
err := h.server.ListenAndServe()
|
||||
if err != nil {
|
||||
if err != nil && err != http.ErrServerClosed {
|
||||
h.log.Fatal(err.Error())
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// NewBinding creates a new binding with the frontend
|
||||
func (h *Headless) NewBinding(methodName string) error {
|
||||
func (h *Bridge) NewBinding(methodName string) error {
|
||||
h.bindingCache = append(h.bindingCache, methodName)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SelectFile is unsupported for Headless but required
|
||||
// SelectFile is unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Headless) SelectFile() string {
|
||||
func (h *Bridge) SelectFile() string {
|
||||
h.log.Warn("SelectFile() unsupported in bridge mode")
|
||||
return ""
|
||||
}
|
||||
|
||||
// SelectDirectory is unsupported for Headless but required
|
||||
// SelectDirectory is unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Headless) SelectDirectory() string {
|
||||
func (h *Bridge) SelectDirectory() string {
|
||||
h.log.Warn("SelectDirectory() unsupported in bridge mode")
|
||||
return ""
|
||||
}
|
||||
|
||||
// SelectSaveFile is unsupported for Headless but required
|
||||
// SelectSaveFile is unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Headless) SelectSaveFile() string {
|
||||
func (h *Bridge) SelectSaveFile() string {
|
||||
h.log.Warn("SelectSaveFile() unsupported in bridge mode")
|
||||
return ""
|
||||
}
|
||||
|
||||
// Callback sends a callback to the frontend
|
||||
func (h *Headless) Callback(data string) error {
|
||||
func (h *Bridge) Callback(data string) error {
|
||||
return h.evalJS(data, callbackMessage)
|
||||
}
|
||||
|
||||
// NotifyEvent notifies the frontend of an event
|
||||
func (h *Headless) NotifyEvent(event *messages.EventData) error {
|
||||
func (h *Bridge) NotifyEvent(event *messages.EventData) error {
|
||||
|
||||
// Look out! Nils about!
|
||||
var err error
|
||||
@@ -222,33 +222,37 @@ func (h *Headless) NotifyEvent(event *messages.EventData) error {
|
||||
return h.evalJS(message, notifyMessage)
|
||||
}
|
||||
|
||||
// SetColour is unsupported for Headless but required
|
||||
// SetColour is unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Headless) SetColour(colour string) error {
|
||||
h.log.WarnFields("SetColour ignored for headless more", logger.Fields{"col": colour})
|
||||
func (h *Bridge) SetColour(colour string) error {
|
||||
h.log.WarnFields("SetColour ignored for Bridge more", logger.Fields{"col": colour})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Fullscreen is unsupported for Headless but required
|
||||
// Fullscreen is unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Headless) Fullscreen() {
|
||||
func (h *Bridge) Fullscreen() {
|
||||
h.log.Warn("Fullscreen() unsupported in bridge mode")
|
||||
}
|
||||
|
||||
// UnFullscreen is unsupported for Headless but required
|
||||
// UnFullscreen is unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Headless) UnFullscreen() {
|
||||
func (h *Bridge) UnFullscreen() {
|
||||
h.log.Warn("UnFullscreen() unsupported in bridge mode")
|
||||
}
|
||||
|
||||
// SetTitle is currently unsupported for Headless but required
|
||||
// SetTitle is currently unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Headless) SetTitle(title string) {
|
||||
func (h *Bridge) SetTitle(title string) {
|
||||
h.log.WarnFields("SetTitle() unsupported in bridge mode", logger.Fields{"title": title})
|
||||
}
|
||||
|
||||
// Close is unsupported for Headless but required
|
||||
// Close is unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Headless) Close() {
|
||||
h.log.Warn("Close() unsupported in bridge mode")
|
||||
func (h *Bridge) Close() {
|
||||
h.log.Debug("Shutting down")
|
||||
err := h.server.Close()
|
||||
if err != nil {
|
||||
h.log.Errorf(err.Error())
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -10,16 +10,16 @@ import (
|
||||
|
||||
"github.com/go-playground/colors"
|
||||
"github.com/leaanthony/mewn"
|
||||
"github.com/wailsapp/wails/lib/interfaces"
|
||||
"github.com/wailsapp/wails/lib/logger"
|
||||
"github.com/wailsapp/wails/lib/messages"
|
||||
"github.com/wailsapp/wails/lib/interfaces"
|
||||
"github.com/wailsapp/webview"
|
||||
wv "github.com/wailsapp/wails/lib/renderer/webview"
|
||||
)
|
||||
|
||||
// WebView defines the main webview application window
|
||||
// Default values in []
|
||||
type WebView struct {
|
||||
window webview.WebView // The webview object
|
||||
window wv.WebView // The webview object
|
||||
ipc interfaces.IPCManager
|
||||
log *logger.CustomLogger
|
||||
config interfaces.AppConfig
|
||||
@@ -29,7 +29,7 @@ type WebView struct {
|
||||
|
||||
// NewWebView returns a new WebView struct
|
||||
func NewWebView() *WebView {
|
||||
return &WebView{};
|
||||
return &WebView{}
|
||||
}
|
||||
|
||||
// Initialise sets up the WebView
|
||||
@@ -49,14 +49,14 @@ func (w *WebView) Initialise(config interfaces.AppConfig, ipc interfaces.IPCMana
|
||||
w.config = config
|
||||
|
||||
// Create the WebView instance
|
||||
w.window = webview.NewWebview(webview.Settings{
|
||||
w.window = wv.NewWebview(wv.Settings{
|
||||
Width: config.GetWidth(),
|
||||
Height: config.GetHeight(),
|
||||
Title: config.GetTitle(),
|
||||
Resizable: config.GetResizable(),
|
||||
URL: config.GetDefaultHTML(),
|
||||
Debug: !config.GetDisableInspector(),
|
||||
ExternalInvokeCallback: func(_ webview.WebView, message string) {
|
||||
ExternalInvokeCallback: func(_ wv.WebView, message string) {
|
||||
w.ipc.Dispatch(message)
|
||||
},
|
||||
})
|
||||
@@ -170,10 +170,10 @@ func (w *WebView) Exit() {
|
||||
// Run the window main loop
|
||||
func (w *WebView) Run() error {
|
||||
|
||||
w.log.Info("Run()")
|
||||
w.log.Info("Running...")
|
||||
|
||||
// Runtime assets
|
||||
wailsRuntime := mewn.String("../../runtime/js/dist/wails.js")
|
||||
wailsRuntime := mewn.String("../../runtime/assets/wails.js")
|
||||
w.evalJS(wailsRuntime)
|
||||
|
||||
// Ping the wait channel when the wails runtime is loaded
|
||||
@@ -242,7 +242,7 @@ func (w *WebView) SelectFile() string {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
w.window.Dispatch(func() {
|
||||
result = w.window.Dialog(webview.DialogTypeOpen, 0, "Select File", "")
|
||||
result = w.window.Dialog(wv.DialogTypeOpen, 0, "Select File", "")
|
||||
wg.Done()
|
||||
})
|
||||
}()
|
||||
@@ -260,7 +260,7 @@ func (w *WebView) SelectDirectory() string {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
w.window.Dispatch(func() {
|
||||
result = w.window.Dialog(webview.DialogTypeOpen, webview.DialogFlagDirectory, "Select Directory", "")
|
||||
result = w.window.Dialog(wv.DialogTypeOpen, wv.DialogFlagDirectory, "Select Directory", "")
|
||||
wg.Done()
|
||||
})
|
||||
}()
|
||||
@@ -278,7 +278,7 @@ func (w *WebView) SelectSaveFile() string {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
w.window.Dispatch(func() {
|
||||
result = w.window.Dialog(webview.DialogTypeSave, 0, "Save file", "")
|
||||
result = w.window.Dialog(wv.DialogTypeSave, 0, "Save file", "")
|
||||
wg.Done()
|
||||
})
|
||||
}()
|
||||
|
||||
21
lib/renderer/webview/LICENSE
Normal file
21
lib/renderer/webview/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Serge Zaitsev
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
372
lib/renderer/webview/webview.go
Executable file
372
lib/renderer/webview/webview.go
Executable file
@@ -0,0 +1,372 @@
|
||||
// Package wails implements Go bindings to https://github.com/zserge/webview C library.
|
||||
// It is a modified version of webview.go from that repository
|
||||
|
||||
// Bindings closely repeat the C APIs and include both, a simplified
|
||||
// single-function API to just open a full-screen webview window, and a more
|
||||
// advanced and featureful set of APIs, including Go-to-JavaScript bindings.
|
||||
//
|
||||
// The library uses gtk-webkit, Cocoa/Webkit and MSHTML (IE8..11) as a browser
|
||||
// engine and supports Linux, MacOS and Windows 7..10 respectively.
|
||||
//
|
||||
package webview
|
||||
|
||||
/*
|
||||
#cgo linux openbsd freebsd CFLAGS: -DWEBVIEW_GTK=1 -Wno-deprecated-declarations
|
||||
#cgo linux openbsd freebsd pkg-config: gtk+-3.0 webkit2gtk-4.0
|
||||
|
||||
#cgo windows CFLAGS: -DWEBVIEW_WINAPI=1
|
||||
#cgo windows LDFLAGS: -lole32 -lcomctl32 -loleaut32 -luuid -lgdi32
|
||||
|
||||
#cgo darwin CFLAGS: -DWEBVIEW_COCOA=1 -x objective-c
|
||||
#cgo darwin LDFLAGS: -framework Cocoa -framework WebKit
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#define WEBVIEW_STATIC
|
||||
#define WEBVIEW_IMPLEMENTATION
|
||||
#include "webview.h"
|
||||
|
||||
extern void _webviewExternalInvokeCallback(void *, void *);
|
||||
|
||||
static inline void CgoWebViewFree(void *w) {
|
||||
free((void *)((struct webview *)w)->title);
|
||||
free((void *)((struct webview *)w)->url);
|
||||
free(w);
|
||||
}
|
||||
|
||||
static inline void *CgoWebViewCreate(int width, int height, char *title, char *url, int resizable, int debug) {
|
||||
struct webview *w = (struct webview *) calloc(1, sizeof(*w));
|
||||
w->width = width;
|
||||
w->height = height;
|
||||
w->title = title;
|
||||
w->url = url;
|
||||
w->resizable = resizable;
|
||||
w->debug = debug;
|
||||
w->external_invoke_cb = (webview_external_invoke_cb_t) _webviewExternalInvokeCallback;
|
||||
if (webview_init(w) != 0) {
|
||||
CgoWebViewFree(w);
|
||||
return NULL;
|
||||
}
|
||||
return (void *)w;
|
||||
}
|
||||
|
||||
static inline int CgoWebViewLoop(void *w, int blocking) {
|
||||
return webview_loop((struct webview *)w, blocking);
|
||||
}
|
||||
|
||||
static inline void CgoWebViewTerminate(void *w) {
|
||||
webview_terminate((struct webview *)w);
|
||||
}
|
||||
|
||||
static inline void CgoWebViewExit(void *w) {
|
||||
webview_exit((struct webview *)w);
|
||||
}
|
||||
|
||||
static inline void CgoWebViewSetTitle(void *w, char *title) {
|
||||
webview_set_title((struct webview *)w, title);
|
||||
}
|
||||
|
||||
static inline void CgoWebViewSetFullscreen(void *w, int fullscreen) {
|
||||
webview_set_fullscreen((struct webview *)w, fullscreen);
|
||||
}
|
||||
|
||||
static inline void CgoWebViewSetColor(void *w, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
|
||||
webview_set_color((struct webview *)w, r, g, b, a);
|
||||
}
|
||||
|
||||
static inline void CgoDialog(void *w, int dlgtype, int flags,
|
||||
char *title, char *arg, char *res, size_t ressz) {
|
||||
webview_dialog(w, dlgtype, flags,
|
||||
(const char*)title, (const char*) arg, res, ressz);
|
||||
}
|
||||
|
||||
static inline int CgoWebViewEval(void *w, char *js) {
|
||||
return webview_eval((struct webview *)w, js);
|
||||
}
|
||||
|
||||
static inline void CgoWebViewInjectCSS(void *w, char *css) {
|
||||
webview_inject_css((struct webview *)w, css);
|
||||
}
|
||||
|
||||
extern void _webviewDispatchGoCallback(void *);
|
||||
static inline void _webview_dispatch_cb(struct webview *w, void *arg) {
|
||||
_webviewDispatchGoCallback(arg);
|
||||
}
|
||||
static inline void CgoWebViewDispatch(void *w, uintptr_t arg) {
|
||||
webview_dispatch((struct webview *)w, _webview_dispatch_cb, (void *)arg);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"errors"
|
||||
"runtime"
|
||||
"sync"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Ensure that main.main is called from the main thread
|
||||
runtime.LockOSThread()
|
||||
}
|
||||
|
||||
// Open is a simplified API to open a single native window with a full-size webview in
|
||||
// it. It can be helpful if you want to communicate with the core app using XHR
|
||||
// or WebSockets (as opposed to using JavaScript bindings).
|
||||
//
|
||||
// Window appearance can be customized using title, width, height and resizable parameters.
|
||||
// URL must be provided and can user either a http or https protocol, or be a
|
||||
// local file:// URL. On some platforms "data:" URLs are also supported
|
||||
// (Linux/MacOS).
|
||||
func Open(title, url string, w, h int, resizable bool) error {
|
||||
titleStr := C.CString(title)
|
||||
defer C.free(unsafe.Pointer(titleStr))
|
||||
urlStr := C.CString(url)
|
||||
defer C.free(unsafe.Pointer(urlStr))
|
||||
resize := C.int(0)
|
||||
if resizable {
|
||||
resize = C.int(1)
|
||||
}
|
||||
|
||||
r := C.webview(titleStr, urlStr, C.int(w), C.int(h), resize)
|
||||
if r != 0 {
|
||||
return errors.New("failed to create webview")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExternalInvokeCallbackFunc is a function type that is called every time
|
||||
// "window.external.invoke()" is called from JavaScript. Data is the only
|
||||
// obligatory string parameter passed into the "invoke(data)" function from
|
||||
// JavaScript. To pass more complex data serialized JSON or base64 encoded
|
||||
// string can be used.
|
||||
type ExternalInvokeCallbackFunc func(w WebView, data string)
|
||||
|
||||
// Settings is a set of parameters to customize the initial WebView appearance
|
||||
// and behavior. It is passed into the webview.New() constructor.
|
||||
type Settings struct {
|
||||
// WebView main window title
|
||||
Title string
|
||||
// URL to open in a webview
|
||||
URL string
|
||||
// Window width in pixels
|
||||
Width int
|
||||
// Window height in pixels
|
||||
Height int
|
||||
// Allows/disallows window resizing
|
||||
Resizable bool
|
||||
// Enable debugging tools (Linux/BSD/MacOS, on Windows use Firebug)
|
||||
Debug bool
|
||||
// A callback that is executed when JavaScript calls "window.external.invoke()"
|
||||
ExternalInvokeCallback ExternalInvokeCallbackFunc
|
||||
}
|
||||
|
||||
// WebView is an interface that wraps the basic methods for controlling the UI
|
||||
// loop, handling multithreading and providing JavaScript bindings.
|
||||
type WebView interface {
|
||||
// Run() starts the main UI loop until the user closes the webview window or
|
||||
// Terminate() is called.
|
||||
Run()
|
||||
// Loop() runs a single iteration of the main UI.
|
||||
Loop(blocking bool) bool
|
||||
// SetTitle() changes window title. This method must be called from the main
|
||||
// thread only. See Dispatch() for more details.
|
||||
SetTitle(title string)
|
||||
// SetFullscreen() controls window full-screen mode. This method must be
|
||||
// called from the main thread only. See Dispatch() for more details.
|
||||
SetFullscreen(fullscreen bool)
|
||||
// SetColor() changes window background color. This method must be called from
|
||||
// the main thread only. See Dispatch() for more details.
|
||||
SetColor(r, g, b, a uint8)
|
||||
// Eval() evaluates an arbitrary JS code inside the webview. This method must
|
||||
// be called from the main thread only. See Dispatch() for more details.
|
||||
Eval(js string) error
|
||||
// InjectJS() injects an arbitrary block of CSS code using the JS API. This
|
||||
// method must be called from the main thread only. See Dispatch() for more
|
||||
// details.
|
||||
InjectCSS(css string)
|
||||
// Dialog() opens a system dialog of the given type and title. String
|
||||
// argument can be provided for certain dialogs, such as alert boxes. For
|
||||
// alert boxes argument is a message inside the dialog box.
|
||||
Dialog(dlgType DialogType, flags int, title string, arg string) string
|
||||
// Terminate() breaks the main UI loop. This method must be called from the main thread
|
||||
// only. See Dispatch() for more details.
|
||||
Terminate()
|
||||
// Dispatch() schedules some arbitrary function to be executed on the main UI
|
||||
// thread. This may be helpful if you want to run some JavaScript from
|
||||
// background threads/goroutines, or to terminate the app.
|
||||
Dispatch(func())
|
||||
// Exit() closes the window and cleans up the resources. Use Terminate() to
|
||||
// forcefully break out of the main UI loop.
|
||||
Exit()
|
||||
}
|
||||
|
||||
// DialogType is an enumeration of all supported system dialog types
|
||||
type DialogType int
|
||||
|
||||
const (
|
||||
// DialogTypeOpen is a system file open dialog
|
||||
DialogTypeOpen DialogType = iota
|
||||
// DialogTypeSave is a system file save dialog
|
||||
DialogTypeSave
|
||||
// DialogTypeAlert is a system alert dialog (message box)
|
||||
DialogTypeAlert
|
||||
)
|
||||
|
||||
const (
|
||||
// DialogFlagFile is a normal file picker dialog
|
||||
DialogFlagFile = C.WEBVIEW_DIALOG_FLAG_FILE
|
||||
// DialogFlagDirectory is an open directory dialog
|
||||
DialogFlagDirectory = C.WEBVIEW_DIALOG_FLAG_DIRECTORY
|
||||
// DialogFlagInfo is an info alert dialog
|
||||
DialogFlagInfo = C.WEBVIEW_DIALOG_FLAG_INFO
|
||||
// DialogFlagWarning is a warning alert dialog
|
||||
DialogFlagWarning = C.WEBVIEW_DIALOG_FLAG_WARNING
|
||||
// DialogFlagError is an error dialog
|
||||
DialogFlagError = C.WEBVIEW_DIALOG_FLAG_ERROR
|
||||
)
|
||||
|
||||
var (
|
||||
m sync.Mutex
|
||||
index uintptr
|
||||
fns = map[uintptr]func(){}
|
||||
cbs = map[WebView]ExternalInvokeCallbackFunc{}
|
||||
)
|
||||
|
||||
type webview struct {
|
||||
w unsafe.Pointer
|
||||
}
|
||||
|
||||
var _ WebView = &webview{}
|
||||
|
||||
func boolToInt(b bool) int {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// NewWebview creates and opens a new webview window using the given settings. The
|
||||
// returned object implements the WebView interface. This function returns nil
|
||||
// if a window can not be created.
|
||||
func NewWebview(settings Settings) WebView {
|
||||
if settings.Width == 0 {
|
||||
settings.Width = 640
|
||||
}
|
||||
if settings.Height == 0 {
|
||||
settings.Height = 480
|
||||
}
|
||||
if settings.Title == "" {
|
||||
settings.Title = "WebView"
|
||||
}
|
||||
w := &webview{}
|
||||
w.w = C.CgoWebViewCreate(C.int(settings.Width), C.int(settings.Height),
|
||||
C.CString(settings.Title), C.CString(settings.URL),
|
||||
C.int(boolToInt(settings.Resizable)), C.int(boolToInt(settings.Debug)))
|
||||
m.Lock()
|
||||
if settings.ExternalInvokeCallback != nil {
|
||||
cbs[w] = settings.ExternalInvokeCallback
|
||||
} else {
|
||||
cbs[w] = func(w WebView, data string) {}
|
||||
}
|
||||
m.Unlock()
|
||||
return w
|
||||
}
|
||||
|
||||
func (w *webview) Loop(blocking bool) bool {
|
||||
block := C.int(0)
|
||||
if blocking {
|
||||
block = 1
|
||||
}
|
||||
return C.CgoWebViewLoop(w.w, block) == 0
|
||||
}
|
||||
|
||||
func (w *webview) Run() {
|
||||
for w.Loop(true) {
|
||||
}
|
||||
}
|
||||
|
||||
func (w *webview) Exit() {
|
||||
C.CgoWebViewExit(w.w)
|
||||
}
|
||||
|
||||
func (w *webview) Dispatch(f func()) {
|
||||
m.Lock()
|
||||
for ; fns[index] != nil; index++ {
|
||||
}
|
||||
fns[index] = f
|
||||
m.Unlock()
|
||||
C.CgoWebViewDispatch(w.w, C.uintptr_t(index))
|
||||
}
|
||||
|
||||
func (w *webview) SetTitle(title string) {
|
||||
p := C.CString(title)
|
||||
defer C.free(unsafe.Pointer(p))
|
||||
C.CgoWebViewSetTitle(w.w, p)
|
||||
}
|
||||
|
||||
func (w *webview) SetColor(r, g, b, a uint8) {
|
||||
C.CgoWebViewSetColor(w.w, C.uint8_t(r), C.uint8_t(g), C.uint8_t(b), C.uint8_t(a))
|
||||
}
|
||||
|
||||
func (w *webview) SetFullscreen(fullscreen bool) {
|
||||
C.CgoWebViewSetFullscreen(w.w, C.int(boolToInt(fullscreen)))
|
||||
}
|
||||
|
||||
func (w *webview) Dialog(dlgType DialogType, flags int, title string, arg string) string {
|
||||
const maxPath = 4096
|
||||
titlePtr := C.CString(title)
|
||||
defer C.free(unsafe.Pointer(titlePtr))
|
||||
argPtr := C.CString(arg)
|
||||
defer C.free(unsafe.Pointer(argPtr))
|
||||
resultPtr := (*C.char)(C.calloc((C.size_t)(unsafe.Sizeof((*C.char)(nil))), (C.size_t)(maxPath)))
|
||||
defer C.free(unsafe.Pointer(resultPtr))
|
||||
C.CgoDialog(w.w, C.int(dlgType), C.int(flags), titlePtr,
|
||||
argPtr, resultPtr, C.size_t(maxPath))
|
||||
return C.GoString(resultPtr)
|
||||
}
|
||||
|
||||
func (w *webview) Eval(js string) error {
|
||||
p := C.CString(js)
|
||||
defer C.free(unsafe.Pointer(p))
|
||||
switch C.CgoWebViewEval(w.w, p) {
|
||||
case -1:
|
||||
return errors.New("evaluation failed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *webview) InjectCSS(css string) {
|
||||
p := C.CString(css)
|
||||
defer C.free(unsafe.Pointer(p))
|
||||
C.CgoWebViewInjectCSS(w.w, p)
|
||||
}
|
||||
|
||||
func (w *webview) Terminate() {
|
||||
C.CgoWebViewTerminate(w.w)
|
||||
}
|
||||
|
||||
//export _webviewDispatchGoCallback
|
||||
func _webviewDispatchGoCallback(index unsafe.Pointer) {
|
||||
var f func()
|
||||
m.Lock()
|
||||
f = fns[uintptr(index)]
|
||||
delete(fns, uintptr(index))
|
||||
m.Unlock()
|
||||
f()
|
||||
}
|
||||
|
||||
//export _webviewExternalInvokeCallback
|
||||
func _webviewExternalInvokeCallback(w unsafe.Pointer, data unsafe.Pointer) {
|
||||
m.Lock()
|
||||
var (
|
||||
cb ExternalInvokeCallbackFunc
|
||||
wv WebView
|
||||
)
|
||||
for wv, cb = range cbs {
|
||||
if wv.(*webview).w == w {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.Unlock()
|
||||
cb(wv, C.GoString((*C.char)(data)))
|
||||
}
|
||||
2266
lib/renderer/webview/webview.h
Normal file
2266
lib/renderer/webview/webview.h
Normal file
File diff suppressed because it is too large
Load Diff
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(),
|
||||
}
|
||||
}
|
||||
@@ -1,43 +1,38 @@
|
||||
/*
|
||||
Wails Bridge (c) 2019-present Lea Anthony
|
||||
|
||||
This library creates a bridge between your application
|
||||
and the frontend, allowing you to develop your app using
|
||||
standard tooling (browser extensions, live reload, etc).
|
||||
|
||||
Usage:
|
||||
```
|
||||
import Bridge from "./wailsbridge";
|
||||
Bridge.Start(startApp);
|
||||
```
|
||||
|
||||
The given callback (startApp in the example) will be called
|
||||
when the bridge has successfully initialised. It passes the
|
||||
window.wails object back, in case it is not accessible directly.
|
||||
_ __ _ __
|
||||
| | / /___ _(_) /____
|
||||
| | /| / / __ `/ / / ___/
|
||||
| |/ |/ / /_/ / / (__ )
|
||||
|__/|__/\__,_/_/_/____/
|
||||
The lightweight framework for web-like apps
|
||||
(c) Lea Anthony 2019-present
|
||||
*/
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
// Bridge object
|
||||
window.wailsbridge = {
|
||||
reconnectOverlay: null,
|
||||
reconnectTimer: 300,
|
||||
wsURL: 'ws://localhost:34115/bridge',
|
||||
connectionState: null,
|
||||
config: {},
|
||||
websocket: null,
|
||||
callback: null,
|
||||
overlayHTML:
|
||||
'<div class="wails-reconnect-overlay"><div class="wails-reconnect-overlay-content"><div class="wails-reconnect-overlay-title">Wails Bridge</div><br><div class="wails-reconnect-overlay-loadingspinner"></div><br><div id="wails-reconnect-overlay-message">Waiting for backend</div></div></div>',
|
||||
overlayCSS:
|
||||
'.wails-reconnect-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.6);font-family:sans-serif;display:none;z-index:999999}.wails-reconnect-overlay-content{padding:20px 30px;text-align:center;width:20em;position:relative;height:14em;border-radius:1em;margin:5% auto 0;background-color:#fff;box-shadow:1px 1px 20px 3px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC8AAAAuCAMAAACPpbA7AAAAqFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQAAAAAAAAEBAQAAAAAAAAAAAAEBAQEBAQDAwMBAQEAAAABAQEAAAAAAAAAAAABAQEAAAAAAAACAgICAgIBAQEAAAAAAAAAAAAAAAAAAAAAAAABAQEAAAACAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBQWKCj6oAAAAN3RSTlMALiIqDhkGBAswJjP0GxP6NR4W9/ztjRDMhWU50G9g5eHXvbZ9XEI9xZTcqZl2aldKo55QwoCvZUgzhAAAAs9JREFUSMeNleeWqjAUhU0BCaH3Itiw9zKT93+zG02QK1hm/5HF+jzZJ6fQe6cyXE+jg9X7o9wxuylIIf4Tv2V3+bOrEXnf8dwQ/KQIGDN2/S+4OmVCVXL/ScBnfibxURqIByP/hONE8r8T+bDMlQ98KSl7Y8hzjpS8v1qtDh8u5f8KQpGpfnPPhqG8JeogN37Hq9eaN2xRhIwAaGnvws8F1ShxqK5ob2twYi1FAMD4rXsYtnC/JEiRbl4cUrCWhnMCLRFemXezXbb59QK4WASOsm6n2W1+4CBT2JmtzQ6fsrbGubR/NFbd2g5Y179+5w/GEHaKsHjYCet7CgrXU3txarNC7YxOVJtIj4/ERzMdZfzc31hp+8cD6eGILgarZY9uZ12hAs03vfBD9C171gS5Omz7OcvxALQIn4u8RRBBBcsi9WW2woO9ipLgfzpYlggg3ZRdROUC8KT7QLqq3W9KB5BbdFVg4929kdwp6+qaZnMCCNBdj+NyN1W885Ry/AL3D4AQbsVV4noCiM/C83kyYq80XlDAYQtralOiDzoRAHlotWl8q2tjvYlOgcg1A8jEApZa+C06TBdAz2Qv0wu11I/zZOyJQ6EwGez2P2b8PIQr1hwwnAZsAxwA4UAYOyXUxM/xp6tHAn4GUmPGM9R28oVxgC0e/zQJJI6DyhyZ1r7uzRQhpcW7x7vTaWSzKSG6aep77kroTEl3U81uSVaUTtgEINfC8epx+Q4F9SpplHG84Ek6m4RAq9/TLkOBrxyeuddZhHvGIp1XXfFy3Z3vtwNblKGiDn+J+92vwwABHghj7HnzlS1H5kB49AZvdGCFgiBPq69qfXPr3y++yilF0ON4R8eR7spAsLpZ95NqAW5tab1c4vkZm6aleajchMwYTdILQQTwE2OV411ZM9WztDjPql12caBi6gDpUKmDd4U1XNdQxZ4LIXQ5/Tr4P7I9tYcFrDK3AAAAAElFTkSuQmCC);background-repeat:no-repeat;background-position:center}.wails-reconnect-overlay-title{font-size:2em}.wails-reconnect-overlay-message{font-size:1.3em}.wails-reconnect-overlay-loadingspinner{pointer-events:none;width:2.5em;height:2.5em;border:.4em solid transparent;border-color:#3E67EC #eee #eee;border-radius:50%;animation:loadingspin 1s linear infinite;margin:auto;padding:2.5em}@keyframes loadingspin{100%{transform:rotate(360deg)}}',
|
||||
log: function (message) {
|
||||
// eslint-disable-next-line
|
||||
console.log(
|
||||
'%c wails bridge %c ' + message + ' ',
|
||||
'background: #aa0000; color: #fff; border-radius: 3px 0px 0px 3px; padding: 1px; font-size: 0.7rem',
|
||||
'background: #009900; color: #fff; border-radius: 0px 3px 3px 0px; padding: 1px; font-size: 0.7rem'
|
||||
);
|
||||
}
|
||||
};
|
||||
function init() {
|
||||
// Bridge object
|
||||
window.wailsbridge = {
|
||||
reconnectOverlay: null,
|
||||
reconnectTimer: 300,
|
||||
wsURL: 'ws://localhost:34115/bridge',
|
||||
connectionState: null,
|
||||
config: {},
|
||||
websocket: null,
|
||||
callback: null,
|
||||
overlayHTML:
|
||||
'<div class="wails-reconnect-overlay"><div class="wails-reconnect-overlay-content"><div class="wails-reconnect-overlay-title">Wails Bridge</div><br><div class="wails-reconnect-overlay-loadingspinner"></div><br><div id="wails-reconnect-overlay-message">Waiting for backend</div></div></div>',
|
||||
overlayCSS:
|
||||
'.wails-reconnect-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.6);font-family:sans-serif;display:none;z-index:999999}.wails-reconnect-overlay-content{padding:20px 30px;text-align:center;width:20em;position:relative;height:14em;border-radius:1em;margin:5% auto 0;background-color:#fff;box-shadow:1px 1px 20px 3px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC8AAAAuCAMAAACPpbA7AAAAqFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQAAAAAAAAEBAQAAAAAAAAAAAAEBAQEBAQDAwMBAQEAAAABAQEAAAAAAAAAAAABAQEAAAAAAAACAgICAgIBAQEAAAAAAAAAAAAAAAAAAAAAAAABAQEAAAACAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBQWKCj6oAAAAN3RSTlMALiIqDhkGBAswJjP0GxP6NR4W9/ztjRDMhWU50G9g5eHXvbZ9XEI9xZTcqZl2aldKo55QwoCvZUgzhAAAAs9JREFUSMeNleeWqjAUhU0BCaH3Itiw9zKT93+zG02QK1hm/5HF+jzZJ6fQe6cyXE+jg9X7o9wxuylIIf4Tv2V3+bOrEXnf8dwQ/KQIGDN2/S+4OmVCVXL/ScBnfibxURqIByP/hONE8r8T+bDMlQ98KSl7Y8hzjpS8v1qtDh8u5f8KQpGpfnPPhqG8JeogN37Hq9eaN2xRhIwAaGnvws8F1ShxqK5ob2twYi1FAMD4rXsYtnC/JEiRbl4cUrCWhnMCLRFemXezXbb59QK4WASOsm6n2W1+4CBT2JmtzQ6fsrbGubR/NFbd2g5Y179+5w/GEHaKsHjYCet7CgrXU3txarNC7YxOVJtIj4/ERzMdZfzc31hp+8cD6eGILgarZY9uZ12hAs03vfBD9C171gS5Omz7OcvxALQIn4u8RRBBBcsi9WW2woO9ipLgfzpYlggg3ZRdROUC8KT7QLqq3W9KB5BbdFVg4929kdwp6+qaZnMCCNBdj+NyN1W885Ry/AL3D4AQbsVV4noCiM/C83kyYq80XlDAYQtralOiDzoRAHlotWl8q2tjvYlOgcg1A8jEApZa+C06TBdAz2Qv0wu11I/zZOyJQ6EwGez2P2b8PIQr1hwwnAZsAxwA4UAYOyXUxM/xp6tHAn4GUmPGM9R28oVxgC0e/zQJJI6DyhyZ1r7uzRQhpcW7x7vTaWSzKSG6aep77kroTEl3U81uSVaUTtgEINfC8epx+Q4F9SpplHG84Ek6m4RAq9/TLkOBrxyeuddZhHvGIp1XXfFy3Z3vtwNblKGiDn+J+92vwwABHghj7HnzlS1H5kB49AZvdGCFgiBPq69qfXPr3y++yilF0ON4R8eR7spAsLpZ95NqAW5tab1c4vkZm6aleajchMwYTdILQQTwE2OV411ZM9WztDjPql12caBi6gDpUKmDd4U1XNdQxZ4LIXQ5/Tr4P7I9tYcFrDK3AAAAAElFTkSuQmCC);background-repeat:no-repeat;background-position:center}.wails-reconnect-overlay-title{font-size:2em}.wails-reconnect-overlay-message{font-size:1.3em}.wails-reconnect-overlay-loadingspinner{pointer-events:none;width:2.5em;height:2.5em;border:.4em solid transparent;border-color:#3E67EC #eee #eee;border-radius:50%;animation:loadingspin 1s linear infinite;margin:auto;padding:2.5em}@keyframes loadingspin{100%{transform:rotate(360deg)}}',
|
||||
log: function (message) {
|
||||
// eslint-disable-next-line
|
||||
console.log(
|
||||
'%c wails bridge %c ' + message + ' ',
|
||||
'background: #aa0000; color: #fff; border-radius: 3px 0px 0px 3px; padding: 1px; font-size: 0.7rem',
|
||||
'background: #009900; color: #fff; border-radius: 0px 3px 3px 0px; padding: 1px; font-size: 0.7rem'
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Adapted from webview - thanks zserge!
|
||||
function injectCSS(css) {
|
||||
@@ -203,14 +198,20 @@ function startBridge() {
|
||||
connect();
|
||||
}
|
||||
|
||||
export default {
|
||||
// The main function
|
||||
// Passes the main Wails object to the callback if given.
|
||||
Start: function (callback) {
|
||||
// Save the callback
|
||||
window.wailsbridge.callback = callback;
|
||||
function start(callback) {
|
||||
|
||||
// Start Bridge
|
||||
startBridge();
|
||||
}
|
||||
};
|
||||
// Set up the bridge
|
||||
init();
|
||||
|
||||
// Save the callback
|
||||
window.wailsbridge.callback = callback;
|
||||
|
||||
// Start Bridge
|
||||
startBridge();
|
||||
}
|
||||
|
||||
function Init(callback) {
|
||||
start(callback);
|
||||
}
|
||||
|
||||
module.exports = Init;
|
||||
@@ -1,5 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"></head>
|
||||
<body><div id="app"></div><script type="text/javascript"></script></body>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="text/javascript">function AddScript(js, callbackID) {
|
||||
var script = document.createElement('script');
|
||||
script.text = js;
|
||||
document.body.appendChild(script);
|
||||
}</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
1
runtime/assets/wails.js
Normal file
1
runtime/assets/wails.js
Normal file
@@ -0,0 +1 @@
|
||||
!function(n){var t={};function e(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return n[r].call(o.exports,o,o.exports,e),o.l=!0,o.exports}e.m=n,e.c=t,e.d=function(n,t,r){e.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:r})},e.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},e.t=function(n,t){if(1&t&&(n=e(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var r=Object.create(null);if(e.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var o in n)e.d(r,o,function(t){return n[t]}.bind(null,o));return r},e.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return e.d(t,"a",t),t},e.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},e.p="",e(e.s=0)}([function(n,t,e){"use strict";e.r(t);var r={};e.r(r),e.d(r,"Debug",function(){return c}),e.d(r,"Info",function(){return u}),e.d(r,"Warning",function(){return l}),e.d(r,"Error",function(){return f}),e.d(r,"Fatal",function(){return d});var o={};function i(n,t,e){var r={type:n,callbackID:e,payload:t};!function(n){window.external.invoke(n)}(JSON.stringify(r))}function a(n,t){i("log",{level:n,message:t})}function c(n){a("debug",n)}function u(n){a("info",n)}function l(n){a("warning",n)}function f(n){a("error",n)}function d(n){a("fatal",n)}e.r(o),e.d(o,"OpenURL",function(){return y}),e.d(o,"OpenFile",function(){return g});var s,p={};function v(n,t,e){return null!=e&&null!=e||(e=0),new Promise(function(r,o){var a;do{a=n+"-"+s()}while(p[a]);if(e>0)var c=setTimeout(function(){o(Error("Call to "+n+" timed out. Request ID: "+a))},e);p[a]={timeoutHandle:c,reject:o,resolve:r};try{i("call",{bindingName:n,data:JSON.stringify(t)},a)}catch(n){console.error(n)}})}function w(n,t){return v(".wails."+n,t)}function y(n){return w("Browser.OpenURL",n)}function g(n){return w("Browser.OpenFile",n)}s=window.crypto?function(){var n=new Uint32Array(1);return window.crypto.getRandomValues(n)[0]}:function(){return 9007199254740991*Math.random()};var m=function n(t,e){!function(n,t){if(!(n instanceof t))throw new TypeError("Cannot call a class as a function")}(this,n),e=e||-1,this.Callback=function(n){return t.apply(null,n),-1!==e&&0===(e-=1)}},b={};function h(n,t,e){b[n]=b[n]||[];var r=new m(t,e);b[n].push(r)}function O(n){i("event",{name:n,data:JSON.stringify([].slice.apply(arguments).slice(1))})}var S={};function j(n){try{return new Function("var "+n),!0}catch(n){return!1}}function k(){return(k=Object.assign||function(n){for(var t=1;t<arguments.length;t++){var e=arguments[t];for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r])}return n}).apply(this,arguments)}window.backend={},e.d(t,"Init",function(){return N}),window.wails=window.wails||{},window.backend={};var E={NewBinding:function(n){var t=[].concat(n.split(".").splice(1)),e=window.backend;if(t.length>1)for(var r=0;r<t.length-1;r+=1){var o=t[r];if(!j(o))return new Error("".concat(o," is not a valid javascript identifier."));e[o]||(e[o]={}),e=e[o]}var i=t.pop();if(!j(i))return new Error("".concat(i," is not a valid javascript identifier."));e[i]=function(){var t=0;function e(){var e=[].slice.call(arguments);return v(n,e,t)}return e.setTimeout=function(n){t=n},e.getTimeout=function(){return t},e}()},Callback:function(n){var t;n=decodeURIComponent(n.replace(/\s+/g,"").replace(/[0-9a-f]{2}/g,"%$&"));try{t=JSON.parse(n)}catch(t){var e="Invalid JSON passed to callback: ".concat(t.message,". Message: ").concat(n);throw c(e),new Error(e)}var r=t.callbackid,o=p[r];if(!o){var i="Callback '".concat(r,"' not registed!!!");throw console.error(i),new Error(i)}clearTimeout(o.timeoutHandle),delete p[r],t.error?o.reject(t.error):o.resolve(t.data)},Notify:function(n,t){if(b[n]){for(var e=b[n].slice(),r=0;r<b[n].length;r+=1){var o=b[n][r],i=[];if(t)try{i=JSON.parse(t)}catch(t){f("Invalid JSON data sent to notify. Event name = "+n)}o.Callback(i)&&e.splice(r,1)}b[n]=e}},AddScript:function(n,t){var e=document.createElement("script");e.text=n,document.body.appendChild(e),t&&O(t)},InjectCSS:function(n){var t=document.createElement("style");t.setAttribute("type","text/css"),t.styleSheet?t.styleSheet.cssText=n:t.appendChild(document.createTextNode(n)),(document.head||document.getElementsByTagName("head")[0]).appendChild(t)},Init:N},C={Log:r,Browser:o,Events:{On:function(n,t){h(n,t)},OnMultiple:h,Emit:O,Heartbeat:function(n,t,e){var r=null;S[n]=function(){clearInterval(r),e()},r=setInterval(function(){O(n)},t)},Acknowledge:function(n){if(!S[n])throw new f("Cannot acknowledge unknown heartbeat '".concat(n,"'"));S[n]()}},_:E};function N(n){n()}k(window.wails,C),O("wails:loaded")}]);
|
||||
@@ -1,17 +0,0 @@
|
||||
/*
|
||||
Wails Bridge (c) 2019-present Lea Anthony
|
||||
|
||||
This prod version is to get around having to rewrite your code
|
||||
for production. When doing a release build, this file will be used
|
||||
instead of the full version.
|
||||
*/
|
||||
|
||||
export default {
|
||||
// The main function
|
||||
// Passes the main Wails object to the callback if given.
|
||||
Start: function (callback) {
|
||||
if (callback) {
|
||||
window.wails.Events.On('wails:ready', callback);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -7,8 +7,8 @@ type Dialog struct {
|
||||
renderer interfaces.Renderer
|
||||
}
|
||||
|
||||
// newDialog creates a new Dialog struct
|
||||
func newDialog(renderer interfaces.Renderer) *Dialog {
|
||||
// NewDialog creates a new Dialog struct
|
||||
func NewDialog(renderer interfaces.Renderer) *Dialog {
|
||||
return &Dialog{
|
||||
renderer: renderer,
|
||||
}
|
||||
@@ -7,7 +7,8 @@ type Events struct {
|
||||
eventManager interfaces.EventManager
|
||||
}
|
||||
|
||||
func newEvents(eventManager interfaces.EventManager) *Events {
|
||||
// NewEvents creates a new Events struct
|
||||
func NewEvents(eventManager interfaces.EventManager) *Events {
|
||||
return &Events{
|
||||
eventManager: eventManager,
|
||||
}
|
||||
@@ -5,8 +5,8 @@ import homedir "github.com/mitchellh/go-homedir"
|
||||
// FileSystem exposes file system utilities to the runtime
|
||||
type FileSystem struct {}
|
||||
|
||||
// Creates a new FileSystem struct
|
||||
func newFileSystem() *FileSystem {
|
||||
// NewFileSystem creates a new FileSystem struct
|
||||
func NewFileSystem() *FileSystem {
|
||||
return &FileSystem{}
|
||||
}
|
||||
|
||||
@@ -1,25 +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
|
||||
}
|
||||
|
||||
// NewRuntime creates a new Runtime struct
|
||||
func NewRuntime(eventManager interfaces.EventManager, renderer interfaces.Renderer) *Runtime {
|
||||
return &Runtime{
|
||||
Events: newEvents(eventManager),
|
||||
Log: newLog(),
|
||||
Dialog: newDialog(renderer),
|
||||
Window: newWindow(renderer),
|
||||
Browser: NewBrowser(),
|
||||
FileSystem: newFileSystem(),
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package runtime
|
||||
|
||||
import "github.com/wailsapp/wails/lib/interfaces"
|
||||
|
||||
// Window exposes an interface for manipulating the window
|
||||
type Window struct {
|
||||
renderer interfaces.Renderer
|
||||
}
|
||||
|
||||
func newWindow(renderer interfaces.Renderer) *Window {
|
||||
return &Window{
|
||||
renderer: renderer,
|
||||
}
|
||||
}
|
||||
|
||||
// SetColour sets the the window colour
|
||||
func (r *Window) SetColour(colour string) error {
|
||||
return r.renderer.SetColour(colour)
|
||||
}
|
||||
|
||||
// Fullscreen makes the window fullscreen
|
||||
func (r *Window) Fullscreen() {
|
||||
r.renderer.Fullscreen()
|
||||
}
|
||||
|
||||
// UnFullscreen attempts to restore the window to the size/position before fullscreen
|
||||
func (r *Window) UnFullscreen() {
|
||||
r.renderer.UnFullscreen()
|
||||
}
|
||||
|
||||
// SetTitle sets the the window title
|
||||
func (r *Window) SetTitle(title string) {
|
||||
r.renderer.SetTitle(title)
|
||||
}
|
||||
|
||||
// Close shuts down the window and therefore the app
|
||||
func (r *Window) Close() {
|
||||
r.renderer.Close()
|
||||
}
|
||||
@@ -1,280 +1,31 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true
|
||||
"es6": true,
|
||||
"amd": true,
|
||||
"node": true,
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2015,
|
||||
"sourceType": "module"
|
||||
"ecmaVersion": 2016,
|
||||
"sourceType": "module",
|
||||
},
|
||||
"rules": {
|
||||
"accessor-pairs": "error",
|
||||
"array-bracket-newline": "error",
|
||||
"array-bracket-spacing": [
|
||||
"indent": [
|
||||
"error",
|
||||
"never"
|
||||
"tab"
|
||||
],
|
||||
"array-callback-return": "error",
|
||||
"array-element-newline": "off",
|
||||
"arrow-body-style": "error",
|
||||
"arrow-parens": "error",
|
||||
"arrow-spacing": "error",
|
||||
"block-scoped-var": "off",
|
||||
"block-spacing": "error",
|
||||
"brace-style": [
|
||||
"error",
|
||||
"1tbs"
|
||||
],
|
||||
"callback-return": "error",
|
||||
"camelcase": "error",
|
||||
"capitalized-comments": "off",
|
||||
"class-methods-use-this": "error",
|
||||
"comma-dangle": "off",
|
||||
"comma-spacing": [
|
||||
"error",
|
||||
{
|
||||
"after": true,
|
||||
"before": false
|
||||
}
|
||||
],
|
||||
"comma-style": [
|
||||
"error",
|
||||
"last"
|
||||
],
|
||||
"complexity": "error",
|
||||
"computed-property-spacing": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"consistent-return": "off",
|
||||
"consistent-this": "error",
|
||||
"curly": "error",
|
||||
"default-case": "error",
|
||||
"dot-location": "error",
|
||||
"dot-notation": "error",
|
||||
"eol-last": "off",
|
||||
"eqeqeq": "off",
|
||||
"func-call-spacing": "error",
|
||||
"func-name-matching": "error",
|
||||
"func-names": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"func-style": [
|
||||
"error",
|
||||
"declaration"
|
||||
],
|
||||
"function-paren-newline": "error",
|
||||
"generator-star-spacing": "error",
|
||||
"global-require": "error",
|
||||
"guard-for-in": "off",
|
||||
"handle-callback-err": "error",
|
||||
"id-blacklist": "error",
|
||||
"id-length": "off",
|
||||
"id-match": "error",
|
||||
"implicit-arrow-linebreak": "error",
|
||||
"indent": "off",
|
||||
"indent-legacy": "off",
|
||||
"init-declarations": "off",
|
||||
"jsx-quotes": "error",
|
||||
"key-spacing": "error",
|
||||
"keyword-spacing": [
|
||||
"error",
|
||||
{
|
||||
"after": true,
|
||||
"before": true
|
||||
}
|
||||
],
|
||||
"line-comment-position": "error",
|
||||
"linebreak-style": [
|
||||
"error",
|
||||
"unix"
|
||||
],
|
||||
"lines-around-comment": "error",
|
||||
"lines-around-directive": "error",
|
||||
"lines-between-class-members": "error",
|
||||
"max-classes-per-file": "error",
|
||||
"max-depth": "error",
|
||||
"max-len": "off",
|
||||
"max-lines": "error",
|
||||
"max-lines-per-function": "error",
|
||||
"max-nested-callbacks": "error",
|
||||
"max-params": "error",
|
||||
"max-statements": "off",
|
||||
"max-statements-per-line": "error",
|
||||
"multiline-comment-style": "off",
|
||||
"multiline-ternary": "error",
|
||||
"new-parens": "error",
|
||||
"newline-after-var": "off",
|
||||
"newline-before-return": "off",
|
||||
"newline-per-chained-call": "error",
|
||||
"no-alert": "error",
|
||||
"no-array-constructor": "error",
|
||||
"no-await-in-loop": "error",
|
||||
"no-bitwise": "error",
|
||||
"no-buffer-constructor": "error",
|
||||
"no-caller": "error",
|
||||
"no-catch-shadow": "error",
|
||||
"no-confusing-arrow": "error",
|
||||
"no-continue": "error",
|
||||
"no-div-regex": "error",
|
||||
"no-duplicate-imports": "error",
|
||||
"no-else-return": "error",
|
||||
"no-empty-function": "error",
|
||||
"no-eq-null": "off",
|
||||
"no-eval": "error",
|
||||
"no-extend-native": "error",
|
||||
"no-extra-bind": "error",
|
||||
"no-extra-label": "error",
|
||||
"no-extra-parens": "error",
|
||||
"no-floating-decimal": "error",
|
||||
"no-implicit-coercion": "error",
|
||||
"no-implicit-globals": "error",
|
||||
"no-implied-eval": "error",
|
||||
"no-inline-comments": "error",
|
||||
"no-inner-declarations": [
|
||||
"error",
|
||||
"functions"
|
||||
],
|
||||
"no-invalid-this": "error",
|
||||
"no-iterator": "error",
|
||||
"no-label-var": "error",
|
||||
"no-labels": "error",
|
||||
"no-lone-blocks": "error",
|
||||
"no-lonely-if": "error",
|
||||
"no-loop-func": "error",
|
||||
"no-magic-numbers": "off",
|
||||
"no-mixed-operators": "error",
|
||||
"no-mixed-requires": "error",
|
||||
"no-multi-assign": "error",
|
||||
"no-multi-spaces": "error",
|
||||
"no-multi-str": "error",
|
||||
"no-multiple-empty-lines": "error",
|
||||
"no-native-reassign": "error",
|
||||
"no-negated-condition": "error",
|
||||
"no-negated-in-lhs": "error",
|
||||
"no-nested-ternary": "error",
|
||||
"no-new": "off",
|
||||
"no-new-func": "off",
|
||||
"no-new-object": "error",
|
||||
"no-new-require": "error",
|
||||
"no-new-wrappers": "error",
|
||||
"no-octal-escape": "error",
|
||||
"no-param-reassign": "off",
|
||||
"no-path-concat": "error",
|
||||
"no-plusplus": "error",
|
||||
"no-process-env": "error",
|
||||
"no-process-exit": "error",
|
||||
"no-proto": "error",
|
||||
"no-prototype-builtins": "error",
|
||||
"no-restricted-globals": "error",
|
||||
"no-restricted-imports": "error",
|
||||
"no-restricted-modules": "error",
|
||||
"no-restricted-properties": "error",
|
||||
"no-restricted-syntax": "error",
|
||||
"no-return-assign": "error",
|
||||
"no-return-await": "error",
|
||||
"no-script-url": "error",
|
||||
"no-self-compare": "error",
|
||||
"no-sequences": "error",
|
||||
"no-shadow": "error",
|
||||
"no-shadow-restricted-names": "error",
|
||||
"no-spaced-func": "error",
|
||||
"no-sync": "error",
|
||||
"no-tabs": "error",
|
||||
"no-template-curly-in-string": "error",
|
||||
"no-ternary": "error",
|
||||
"no-throw-literal": "error",
|
||||
"no-undef-init": "error",
|
||||
"no-undefined": "off",
|
||||
"no-underscore-dangle": "error",
|
||||
"no-unmodified-loop-condition": "error",
|
||||
"no-unneeded-ternary": "error",
|
||||
"no-unused-expressions": "error",
|
||||
"no-use-before-define": "error",
|
||||
"no-useless-call": "error",
|
||||
"no-useless-computed-key": "error",
|
||||
"no-useless-concat": "error",
|
||||
"no-useless-constructor": "error",
|
||||
"no-useless-rename": "error",
|
||||
"no-useless-return": "error",
|
||||
"no-var": "off",
|
||||
"no-void": "error",
|
||||
"no-warning-comments": "error",
|
||||
"no-whitespace-before-property": "error",
|
||||
"no-with": "error",
|
||||
"nonblock-statement-body-position": "error",
|
||||
"object-curly-newline": "error",
|
||||
"object-curly-spacing": [
|
||||
"error",
|
||||
"always"
|
||||
],
|
||||
"object-property-newline": "error",
|
||||
"object-shorthand": "off",
|
||||
"one-var": "off",
|
||||
"one-var-declaration-per-line": "error",
|
||||
"operator-assignment": "error",
|
||||
"operator-linebreak": "error",
|
||||
"padded-blocks": "off",
|
||||
"padding-line-between-statements": "error",
|
||||
"prefer-arrow-callback": "off",
|
||||
"prefer-const": "error",
|
||||
"prefer-destructuring": "off",
|
||||
"prefer-numeric-literals": "error",
|
||||
"prefer-object-spread": "error",
|
||||
"prefer-promise-reject-errors": "error",
|
||||
"prefer-reflect": "off",
|
||||
"prefer-rest-params": "off",
|
||||
"prefer-spread": "off",
|
||||
"prefer-template": "off",
|
||||
"quote-props": "off",
|
||||
"quotes": [
|
||||
"error",
|
||||
"single"
|
||||
],
|
||||
"radix": "error",
|
||||
"require-await": "error",
|
||||
"require-jsdoc": "off",
|
||||
"rest-spread-spacing": "error",
|
||||
"semi": "off",
|
||||
"semi-spacing": "error",
|
||||
"semi-style": [
|
||||
"error",
|
||||
"last"
|
||||
],
|
||||
"sort-imports": "off",
|
||||
"sort-keys": "off",
|
||||
"sort-vars": "error",
|
||||
"space-before-blocks": "error",
|
||||
"space-before-function-paren": "off",
|
||||
"space-in-parens": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"space-infix-ops": "error",
|
||||
"space-unary-ops": "error",
|
||||
"spaced-comment": [
|
||||
"semi": [
|
||||
"error",
|
||||
"always"
|
||||
],
|
||||
"strict": "error",
|
||||
"switch-colon-spacing": "error",
|
||||
"symbol-description": "error",
|
||||
"template-curly-spacing": "error",
|
||||
"template-tag-spacing": "error",
|
||||
"unicode-bom": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"valid-jsdoc": "error",
|
||||
"vars-on-top": "off",
|
||||
"wrap-iife": "off",
|
||||
"wrap-regex": "error",
|
||||
"yield-star-spacing": "error",
|
||||
"yoda": [
|
||||
"error",
|
||||
"never"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,12 @@ import { Call } from './calls';
|
||||
|
||||
window.backend = {};
|
||||
|
||||
// Determines if the given identifier is valid Javascript
|
||||
/**
|
||||
* Determines if the given identifier is valid Javascript
|
||||
*
|
||||
* @param {boolean} name
|
||||
* @returns
|
||||
*/
|
||||
function isValidIdentifier(name) {
|
||||
// Don't xss yourself :-)
|
||||
try {
|
||||
@@ -24,6 +29,13 @@ function isValidIdentifier(name) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* NewBinding creates a new binding from the given binding name
|
||||
*
|
||||
* @export
|
||||
* @param {string} bindingName
|
||||
* @returns
|
||||
*/
|
||||
// eslint-disable-next-line max-lines-per-function
|
||||
export function NewBinding(bindingName) {
|
||||
|
||||
@@ -34,13 +46,15 @@ export function NewBinding(bindingName) {
|
||||
// Check if we have a path (IE Struct)
|
||||
if (bindingSections.length > 1) {
|
||||
// Iterate over binding sections, adding them to the window.backend object
|
||||
for (let index = 0; index < bindingSections.length - 1; index += 1) {
|
||||
for (let index = 0; index < bindingSections.length-1; index += 1) {
|
||||
const name = bindingSections[index];
|
||||
// Is name a valid javascript identifier?
|
||||
if (!isValidIdentifier(name)) {
|
||||
return new Error(`${name} is not a valid javascript identifier.`);
|
||||
}
|
||||
pathToBinding[name] = {};
|
||||
if (!pathToBinding[name]) {
|
||||
pathToBinding[name] = {};
|
||||
}
|
||||
pathToBinding = pathToBinding[name];
|
||||
}
|
||||
}
|
||||
@@ -11,10 +11,24 @@ The lightweight framework for web-like apps
|
||||
|
||||
import { SystemCall } from './calls';
|
||||
|
||||
/**
|
||||
* Opens the given URL in the system browser
|
||||
*
|
||||
* @export
|
||||
* @param {string} url
|
||||
* @returns
|
||||
*/
|
||||
export function OpenURL(url) {
|
||||
return SystemCall('Browser.OpenURL', url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the given filename using the system's default file handler
|
||||
*
|
||||
* @export
|
||||
* @param {sting} filename
|
||||
* @returns
|
||||
*/
|
||||
export function OpenFile(filename) {
|
||||
return SystemCall('Browser.OpenFile', filename);
|
||||
}
|
||||
@@ -14,18 +14,27 @@ import { SendMessage } from './ipc';
|
||||
|
||||
var callbacks = {};
|
||||
|
||||
// AwesomeRandom
|
||||
/**
|
||||
* Returns a number from the native browser random function
|
||||
*
|
||||
* @returns number
|
||||
*/
|
||||
function cryptoRandom() {
|
||||
var array = new Uint32Array(1);
|
||||
return window.crypto.getRandomValues(array)[0];
|
||||
}
|
||||
|
||||
// LOLRandom
|
||||
/**
|
||||
* Returns a number using da old-skool Math.Random
|
||||
* I likes to call it LOLRandom
|
||||
*
|
||||
* @returns number
|
||||
*/
|
||||
function basicRandom() {
|
||||
return Math.random() * 9007199254740991;
|
||||
}
|
||||
|
||||
// Pick one based on browser capability
|
||||
// Pick a random number function based on browser capability
|
||||
var randomFunc;
|
||||
if (window.crypto) {
|
||||
randomFunc = cryptoRandom;
|
||||
@@ -34,13 +43,22 @@ if (window.crypto) {
|
||||
}
|
||||
|
||||
|
||||
// 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.
|
||||
|
||||
|
||||
/**
|
||||
* 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} bindingName
|
||||
* @param {string} data
|
||||
* @param {number=} timeout
|
||||
* @returns
|
||||
*/
|
||||
export function Call(bindingName, data, timeout) {
|
||||
|
||||
// Timeout infinite by default
|
||||
@@ -87,8 +105,14 @@ export function Call(bindingName, data, timeout) {
|
||||
}
|
||||
|
||||
|
||||
// Called by the backend to return data to a previously called
|
||||
// binding invocation
|
||||
|
||||
/**
|
||||
* Called by the backend to return data to a previously called
|
||||
* binding invocation
|
||||
*
|
||||
* @export
|
||||
* @param {string} incomingMessage
|
||||
*/
|
||||
export function Callback(incomingMessage) {
|
||||
|
||||
// Decode the message - Credit: https://stackoverflow.com/a/13865680
|
||||
@@ -115,12 +139,20 @@ export function Callback(incomingMessage) {
|
||||
delete callbacks[callbackID];
|
||||
|
||||
if (message.error) {
|
||||
return callbackData.reject(message.error);
|
||||
callbackData.reject(message.error);
|
||||
} else {
|
||||
callbackData.resolve(message.data);
|
||||
}
|
||||
return callbackData.resolve(message.data);
|
||||
}
|
||||
|
||||
// systemCall is used to call wails methods from the frontend
|
||||
/**
|
||||
* SystemCall is used to call wails methods from the frontend
|
||||
*
|
||||
* @export
|
||||
* @param {string} method
|
||||
* @param {any[]=} data
|
||||
* @returns
|
||||
*/
|
||||
export function SystemCall(method, data) {
|
||||
return Call('.wails.' + method, data);
|
||||
}
|
||||
@@ -13,7 +13,18 @@ import { Error } from './log';
|
||||
import { SendMessage } from './ipc';
|
||||
|
||||
// Defines a single listener with a maximum number of times to callback
|
||||
/**
|
||||
* The Listener class defines a listener! :-)
|
||||
*
|
||||
* @class Listener
|
||||
*/
|
||||
class Listener {
|
||||
/**
|
||||
* Creates an instance of Listener.
|
||||
* @param {function} callback
|
||||
* @param {number} maxCallbacks
|
||||
* @memberof Listener
|
||||
*/
|
||||
constructor(callback, maxCallbacks) {
|
||||
// Default of -1 means infinite
|
||||
maxCallbacks = maxCallbacks || -1;
|
||||
@@ -34,24 +45,49 @@ class Listener {
|
||||
|
||||
var eventListeners = {};
|
||||
|
||||
// Registers an event listener that will be invoked `maxCallbacks` times before being destroyed
|
||||
/**
|
||||
* Registers an event listener that will be invoked `maxCallbacks` times before being destroyed
|
||||
*
|
||||
* @export
|
||||
* @param {string} eventName
|
||||
* @param {function} callback
|
||||
* @param {number} maxCallbacks
|
||||
*/
|
||||
export function OnMultiple(eventName, callback, maxCallbacks) {
|
||||
eventListeners[eventName] = eventListeners[eventName] || [];
|
||||
const thisListener = new Listener(callback, maxCallbacks);
|
||||
eventListeners[eventName].push(thisListener);
|
||||
}
|
||||
|
||||
// Registers an event listener that will be invoked every time the event is emitted
|
||||
/**
|
||||
* Registers an event listener that will be invoked every time the event is emitted
|
||||
*
|
||||
* @export
|
||||
* @param {string} eventName
|
||||
* @param {function} callback
|
||||
*/
|
||||
export function On(eventName, callback) {
|
||||
OnMultiple(eventName, callback);
|
||||
}
|
||||
|
||||
// Registers an event listener that will be invoked once then destroyed
|
||||
/**
|
||||
* Registers an event listener that will be invoked once then destroyed
|
||||
*
|
||||
* @export
|
||||
* @param {string} eventName
|
||||
* @param {function} callback
|
||||
*/
|
||||
export function Once(eventName, callback) {
|
||||
OnMultiple(eventName, callback, 1);
|
||||
}
|
||||
|
||||
// Notify informs frontend listeners that an event was emitted with the given data
|
||||
/**
|
||||
* Notify informs frontend listeners that an event was emitted with the given data
|
||||
*
|
||||
* @export
|
||||
* @param {string} eventName
|
||||
* @param {string} data
|
||||
*/
|
||||
export function Notify(eventName, data) {
|
||||
|
||||
// Check if we have any listeners for this event
|
||||
@@ -88,7 +124,12 @@ export function Notify(eventName, data) {
|
||||
}
|
||||
}
|
||||
|
||||
// Emit an event with the given name and data
|
||||
/**
|
||||
* Emit an event with the given name and data
|
||||
*
|
||||
* @export
|
||||
* @param {string} eventName
|
||||
*/
|
||||
export function Emit(eventName) {
|
||||
|
||||
// Calculate the data
|
||||
@@ -102,10 +143,18 @@ export function Emit(eventName) {
|
||||
SendMessage('event', payload);
|
||||
}
|
||||
|
||||
// Callbacks for the heartbeat calls
|
||||
const heartbeatCallbacks = {};
|
||||
|
||||
// Heartbeat emits the event `eventName`, every `timeInMilliseconds` milliseconds until
|
||||
// the event is acknowledged via `Event.Acknowledge`. Once this happens, `callback` is invoked ONCE
|
||||
/**
|
||||
* Heartbeat emits the event `eventName`, every `timeInMilliseconds` milliseconds until
|
||||
* the event is acknowledged via `Event.Acknowledge`. Once this happens, `callback` is invoked ONCE
|
||||
*
|
||||
* @export
|
||||
* @param {string} eventName
|
||||
* @param {number} timeInMilliseconds
|
||||
* @param {function} callback
|
||||
*/
|
||||
export function Heartbeat(eventName, timeInMilliseconds, callback) {
|
||||
|
||||
// Declare interval variable
|
||||
@@ -128,6 +177,12 @@ export function Heartbeat(eventName, timeInMilliseconds, callback) {
|
||||
}, timeInMilliseconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Acknowledges a heartbeat event by name
|
||||
*
|
||||
* @export
|
||||
* @param {string} eventName
|
||||
*/
|
||||
export function Acknowledge(eventName) {
|
||||
// If we are waiting for acknowledgement for this event type
|
||||
if (heartbeatCallbacks[eventName]) {
|
||||
@@ -9,14 +9,23 @@ The lightweight framework for web-like apps
|
||||
*/
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
/**
|
||||
* Invoke sends the given message to the backend
|
||||
*
|
||||
* @param {string} message
|
||||
*/
|
||||
function Invoke(message) {
|
||||
if (window && window.external && window.external.invoke) {
|
||||
window.external.invoke(message);
|
||||
} else {
|
||||
console.log(`[No external.invoke] ${message}`); // eslint-disable-line
|
||||
}
|
||||
window.external.invoke(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to the backend based on the given type, payload and callbackID
|
||||
*
|
||||
* @export
|
||||
* @param {string} type
|
||||
* @param {string} payload
|
||||
* @param {string=} callbackID
|
||||
*/
|
||||
export function SendMessage(type, payload, callbackID) {
|
||||
const message = {
|
||||
type,
|
||||
@@ -7,12 +7,17 @@
|
||||
The lightweight framework for web-like apps
|
||||
(c) Lea Anthony 2019-present
|
||||
*/
|
||||
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
import { SendMessage } from './ipc';
|
||||
|
||||
// Sends a log message to the backend with the given
|
||||
// level + message
|
||||
/**
|
||||
* Sends a log message to the backend with the given level + message
|
||||
*
|
||||
* @param {string} level
|
||||
* @param {string} message
|
||||
*/
|
||||
function sendLogMessage(level, message) {
|
||||
|
||||
// Log Message
|
||||
@@ -23,22 +28,52 @@ function sendLogMessage(level, message) {
|
||||
SendMessage('log', payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given debug message with the backend
|
||||
*
|
||||
* @export
|
||||
* @param {string} message
|
||||
*/
|
||||
export function Debug(message) {
|
||||
sendLogMessage('debug', message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given info message with the backend
|
||||
*
|
||||
* @export
|
||||
* @param {string} message
|
||||
*/
|
||||
export function Info(message) {
|
||||
sendLogMessage('info', message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given warning message with the backend
|
||||
*
|
||||
* @export
|
||||
* @param {string} message
|
||||
*/
|
||||
export function Warning(message) {
|
||||
sendLogMessage('warning', message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given error message with the backend
|
||||
*
|
||||
* @export
|
||||
* @param {string} message
|
||||
*/
|
||||
export function Error(message) {
|
||||
sendLogMessage('error', message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given fatal message with the backend
|
||||
*
|
||||
* @export
|
||||
* @param {string} message
|
||||
*/
|
||||
export function Fatal(message) {
|
||||
sendLogMessage('fatal', message);
|
||||
}
|
||||
@@ -9,7 +9,8 @@ The lightweight framework for web-like apps
|
||||
*/
|
||||
/* jshint esversion: 6 */
|
||||
import * as Log from './log';
|
||||
import { On, Emit, Notify, Heartbeat, Acknowledge } from './events';
|
||||
import * as Browser from './browser';
|
||||
import { On, OnMultiple, Emit, Notify, Heartbeat, Acknowledge } from './events';
|
||||
import { NewBinding } from './bindings';
|
||||
import { Callback } from './calls';
|
||||
import { AddScript, InjectCSS } from './utils';
|
||||
@@ -24,14 +25,17 @@ var internal = {
|
||||
Callback,
|
||||
Notify,
|
||||
AddScript,
|
||||
InjectCSS
|
||||
InjectCSS,
|
||||
Init,
|
||||
};
|
||||
|
||||
// Setup runtime structure
|
||||
var runtime = {
|
||||
Log,
|
||||
Browser,
|
||||
Events: {
|
||||
On,
|
||||
OnMultiple,
|
||||
Emit,
|
||||
Heartbeat,
|
||||
Acknowledge,
|
||||
@@ -43,4 +47,9 @@ var runtime = {
|
||||
Object.assign(window.wails, runtime);
|
||||
|
||||
// Emit loaded event
|
||||
Emit('wails:loaded');
|
||||
Emit('wails:loaded');
|
||||
|
||||
// Nothing to init in production
|
||||
export function Init(callback) {
|
||||
callback();
|
||||
}
|
||||
1
runtime/js/dist/wails.js
vendored
1
runtime/js/dist/wails.js
vendored
@@ -1 +0,0 @@
|
||||
!function(n){var e={};function t(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return n[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=n,t.c=e,t.d=function(n,e,r){t.o(n,e)||Object.defineProperty(n,e,{enumerable:!0,get:r})},t.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},t.t=function(n,e){if(1&e&&(n=t(n)),8&e)return n;if(4&e&&"object"==typeof n&&n&&n.__esModule)return n;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:n}),2&e&&"string"!=typeof n)for(var o in n)t.d(r,o,function(e){return n[e]}.bind(null,o));return r},t.n=function(n){var e=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(e,"a",e),e},t.o=function(n,e){return Object.prototype.hasOwnProperty.call(n,e)},t.p="",t(t.s=0)}([function(n,e,t){"use strict";t.r(e);var r={};function o(n,e,t){!function(n){window&&window.external&&window.external.invoke?window.external.invoke(n):console.log("[No external.invoke] ".concat(n))}(JSON.stringify({type:n,callbackID:t,payload:e}))}function a(n,e){o("log",{level:n,message:e})}function i(n){a("debug",n)}function c(n){a("info",n)}function u(n){a("warning",n)}function l(n){a("error",n)}function f(n){a("fatal",n)}t.r(r),t.d(r,"Debug",function(){return i}),t.d(r,"Info",function(){return c}),t.d(r,"Warning",function(){return u}),t.d(r,"Error",function(){return l}),t.d(r,"Fatal",function(){return f});var d=function n(e,t){(function(n,e){if(!(n instanceof e))throw new TypeError("Cannot call a class as a function")})(this,n),t=t||-1,this.Callback=function(n){return e.apply(null,n),-1!==t&&0===(t-=1)}},s={};function p(n,e,t){s[n]=s[n]||[];var r=new d(e,t);s[n].push(r)}function v(n){o("event",{name:n,data:JSON.stringify([].slice.apply(arguments).slice(1))})}var w={};var y={};var g=window.crypto?function(){var n=new Uint32Array(1);return window.crypto.getRandomValues(n)[0]}:function(){return 9007199254740991*Math.random()};function m(n,e,t){return(null==t||null==t)&&(t=0),new Promise(function(r,a){var i;do{i=n+"-"+g()}while(y[i]);if(0<t)var c=setTimeout(function(){a(Error("Call to "+n+" timed out. Request ID: "+i))},t);y[i]={timeoutHandle:c,reject:a,resolve:r};try{o("call",{bindingName:n,data:JSON.stringify(e)},i)}catch(n){console.error(n)}})}function b(n){try{return new Function("var "+n),!0}catch(n){return!1}}function h(){return(h=Object.assign||function(n){for(var e,t=1;t<arguments.length;t++)for(var r in e=arguments[t])Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}).apply(this,arguments)}window.backend={},window.wails=window.wails||{},window.backend={};var O={NewBinding:function(n){var e=[].concat(n.split(".").splice(1)),t=window.backend;if(1<e.length)for(var r,o=0;o<e.length-1;o+=1){if(!b(r=e[o]))return new Error("".concat(r," is not a valid javascript identifier."));t[r]={},t=t[r]}var a=e.pop();return b(a)?void(t[a]=function(){function e(){var e=[].slice.call(arguments);return m(n,e,t)}var t=0;return e.setTimeout=function(n){t=n},e.getTimeout=function(){return t},e}()):new Error("".concat(a," is not a valid javascript identifier."))},Callback:function(n){var e;n=decodeURIComponent(n.replace(/\s+/g,"").replace(/[0-9a-f]{2}/g,"%$&"));try{e=JSON.parse(n)}catch(e){return i("Invalid JSON passed to callback: "+e.message),void i("Message: "+n)}var t=e.callbackid,r=y[t];return r?(clearTimeout(r.timeoutHandle),delete y[t],e.error?r.reject(e.error):r.resolve(e.data)):void console.error("Callback '".concat(t,"' not registed!!!"))},Notify:function(n,e){if(s[n]){for(var t=s[n].slice(),r=0;r<s[n].length;r+=1){var o=s[n][r],a=[];if(e)try{a=JSON.parse(e)}catch(e){l("Invalid JSON data sent to notify. Event name = "+n)}o.Callback(a)&&t.splice(r,1)}s[n]=t}},AddScript:function(n,e){var t=document.createElement("script");t.text=n,document.body.appendChild(t),e&&v(e)},InjectCSS:function(n){var e=document.createElement("style");e.setAttribute("type","text/css"),e.styleSheet?e.styleSheet.cssText=n:e.appendChild(document.createTextNode(n)),(document.head||document.getElementsByTagName("head")[0]).appendChild(e)}},S={Log:r,Events:{On:function(n,e){p(n,e)},Emit:v,Heartbeat:function(n,e,t){var r=null;w[n]=function(){clearInterval(r),t()},r=setInterval(function(){v(n)},e)},Acknowledge:function(n){if(!w[n])throw new l("Cannot acknowledge unknown heartbeat '".concat(n,"'"));w[n]()}},_:O};h(window.wails,S),v("wails:loaded")}]);
|
||||
262
runtime/js/package-lock.json
generated
262
runtime/js/package-lock.json
generated
@@ -56,13 +56,15 @@
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
|
||||
"integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"braces": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
|
||||
"integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"arr-flatten": "^1.1.0",
|
||||
"array-unique": "^0.3.2",
|
||||
@@ -81,6 +83,7 @@
|
||||
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
|
||||
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"is-extendable": "^0.1.0"
|
||||
}
|
||||
@@ -253,6 +256,7 @@
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
|
||||
"integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"extend-shallow": "^2.0.1",
|
||||
"is-number": "^3.0.0",
|
||||
@@ -265,6 +269,7 @@
|
||||
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
|
||||
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"is-extendable": "^0.1.0"
|
||||
}
|
||||
@@ -330,7 +335,8 @@
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"is-glob": {
|
||||
"version": "4.0.1",
|
||||
@@ -347,6 +353,7 @@
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
|
||||
"integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"kind-of": "^3.0.2"
|
||||
},
|
||||
@@ -356,6 +363,7 @@
|
||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
|
||||
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"is-buffer": "^1.1.5"
|
||||
}
|
||||
@@ -366,13 +374,15 @@
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
|
||||
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"kind-of": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
|
||||
"integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"micromatch": {
|
||||
"version": "3.1.10",
|
||||
@@ -1640,9 +1650,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"acorn-jsx": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz",
|
||||
"integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==",
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.2.tgz",
|
||||
"integrity": "sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw==",
|
||||
"dev": true
|
||||
},
|
||||
"ajv": {
|
||||
@@ -2881,9 +2891,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"eslint": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-6.0.1.tgz",
|
||||
"integrity": "sha512-DyQRaMmORQ+JsWShYsSg4OPTjY56u1nCjAmICrE8vLWqyLKxhFXOthwMj1SA8xwfrv0CofLNVnqbfyhwCkaO0w==",
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-6.5.1.tgz",
|
||||
"integrity": "sha512-32h99BoLYStT1iq1v2P9uwpyznQ4M2jRiFB6acitKz52Gqn+vPaMDUTB1bYi1WN4Nquj2w+t+bimYUG83DC55A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
@@ -2892,36 +2902,37 @@
|
||||
"cross-spawn": "^6.0.5",
|
||||
"debug": "^4.0.1",
|
||||
"doctrine": "^3.0.0",
|
||||
"eslint-scope": "^4.0.3",
|
||||
"eslint-utils": "^1.3.1",
|
||||
"eslint-visitor-keys": "^1.0.0",
|
||||
"espree": "^6.0.0",
|
||||
"eslint-scope": "^5.0.0",
|
||||
"eslint-utils": "^1.4.2",
|
||||
"eslint-visitor-keys": "^1.1.0",
|
||||
"espree": "^6.1.1",
|
||||
"esquery": "^1.0.1",
|
||||
"esutils": "^2.0.2",
|
||||
"file-entry-cache": "^5.0.1",
|
||||
"functional-red-black-tree": "^1.0.1",
|
||||
"glob-parent": "^3.1.0",
|
||||
"glob-parent": "^5.0.0",
|
||||
"globals": "^11.7.0",
|
||||
"ignore": "^4.0.6",
|
||||
"import-fresh": "^3.0.0",
|
||||
"imurmurhash": "^0.1.4",
|
||||
"inquirer": "^6.2.2",
|
||||
"inquirer": "^6.4.1",
|
||||
"is-glob": "^4.0.0",
|
||||
"js-yaml": "^3.13.1",
|
||||
"json-stable-stringify-without-jsonify": "^1.0.1",
|
||||
"levn": "^0.3.0",
|
||||
"lodash": "^4.17.11",
|
||||
"lodash": "^4.17.14",
|
||||
"minimatch": "^3.0.4",
|
||||
"mkdirp": "^0.5.1",
|
||||
"natural-compare": "^1.4.0",
|
||||
"optionator": "^0.8.2",
|
||||
"progress": "^2.0.0",
|
||||
"regexpp": "^2.0.1",
|
||||
"semver": "^5.5.1",
|
||||
"strip-ansi": "^4.0.0",
|
||||
"strip-json-comments": "^2.0.1",
|
||||
"semver": "^6.1.2",
|
||||
"strip-ansi": "^5.2.0",
|
||||
"strip-json-comments": "^3.0.1",
|
||||
"table": "^5.2.3",
|
||||
"text-table": "^0.2.0"
|
||||
"text-table": "^0.2.0",
|
||||
"v8-compile-cache": "^2.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
@@ -2933,11 +2944,33 @@
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"eslint-scope": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz",
|
||||
"integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esrecurse": "^4.1.0",
|
||||
"estraverse": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
|
||||
"dev": true
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
},
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2952,26 +2985,37 @@
|
||||
}
|
||||
},
|
||||
"eslint-utils": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz",
|
||||
"integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==",
|
||||
"dev": true
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.2.tgz",
|
||||
"integrity": "sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"eslint-visitor-keys": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"eslint-visitor-keys": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
|
||||
"integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==",
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz",
|
||||
"integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==",
|
||||
"dev": true
|
||||
},
|
||||
"espree": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-6.0.0.tgz",
|
||||
"integrity": "sha512-lJvCS6YbCn3ImT3yKkPe0+tJ+mH6ljhGNjHQH9mRtiO6gjhVAOhVXW1yjnwqGwTkK3bGbye+hb00nFNmu0l/1Q==",
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-6.1.1.tgz",
|
||||
"integrity": "sha512-EYbr8XZUhWbYCqQRW0duU5LxzL5bETN6AjKBGy1302qqzPaCH10QbRg3Wvco79Z8x9WbiE8HYB4e75xl6qUYvQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"acorn": "^6.0.7",
|
||||
"acorn-jsx": "^5.0.0",
|
||||
"eslint-visitor-keys": "^1.0.0"
|
||||
"acorn": "^7.0.0",
|
||||
"acorn-jsx": "^5.0.2",
|
||||
"eslint-visitor-keys": "^1.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz",
|
||||
"integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"esprima": {
|
||||
@@ -3543,7 +3587,8 @@
|
||||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
@@ -3564,12 +3609,14 @@
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
@@ -3584,17 +3631,20 @@
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
@@ -3711,7 +3761,8 @@
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
@@ -3723,6 +3774,7 @@
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
@@ -3737,6 +3789,7 @@
|
||||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
@@ -3744,12 +3797,14 @@
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.3.5",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
@@ -3768,6 +3823,7 @@
|
||||
"version": "0.5.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
@@ -3848,7 +3904,8 @@
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
@@ -3860,6 +3917,7 @@
|
||||
"version": "1.4.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
@@ -3945,7 +4003,8 @@
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
@@ -3981,6 +4040,7 @@
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
@@ -4000,6 +4060,7 @@
|
||||
"version": "3.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
@@ -4043,12 +4104,14 @@
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.0.3",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -4100,24 +4163,12 @@
|
||||
}
|
||||
},
|
||||
"glob-parent": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
|
||||
"integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz",
|
||||
"integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-glob": "^3.1.0",
|
||||
"path-dirname": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"is-glob": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
|
||||
"integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-extglob": "^2.1.0"
|
||||
}
|
||||
}
|
||||
"is-glob": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"global-modules": {
|
||||
@@ -4375,9 +4426,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"inquirer": {
|
||||
"version": "6.4.1",
|
||||
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.4.1.tgz",
|
||||
"integrity": "sha512-/Jw+qPZx4EDYsaT6uz7F4GJRNFMRdKNeUZw3ZnKV8lyuUgz/YWRCSUAJMZSVhSq4Ec0R2oYnyi6b3d4JXcL5Nw==",
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz",
|
||||
"integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-escapes": "^3.2.0",
|
||||
@@ -4386,7 +4437,7 @@
|
||||
"cli-width": "^2.0.0",
|
||||
"external-editor": "^3.0.3",
|
||||
"figures": "^2.0.0",
|
||||
"lodash": "^4.17.11",
|
||||
"lodash": "^4.17.12",
|
||||
"mute-stream": "0.0.7",
|
||||
"run-async": "^2.2.0",
|
||||
"rxjs": "^6.4.0",
|
||||
@@ -4395,6 +4446,12 @@
|
||||
"through": "^2.3.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": {
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
|
||||
"dev": true
|
||||
},
|
||||
"string-width": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
|
||||
@@ -4415,23 +4472,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
|
||||
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^4.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
|
||||
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5961,9 +6001,9 @@
|
||||
}
|
||||
},
|
||||
"rxjs": {
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz",
|
||||
"integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==",
|
||||
"version": "6.5.3",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz",
|
||||
"integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tslib": "^1.9.0"
|
||||
@@ -6351,12 +6391,20 @@
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
|
||||
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
|
||||
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^3.0.0"
|
||||
"ansi-regex": "^4.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
|
||||
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"strip-eof": {
|
||||
@@ -6366,9 +6414,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"strip-json-comments": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz",
|
||||
"integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==",
|
||||
"dev": true
|
||||
},
|
||||
"supports-color": {
|
||||
@@ -6381,15 +6429,35 @@
|
||||
}
|
||||
},
|
||||
"table": {
|
||||
"version": "5.4.1",
|
||||
"resolved": "https://registry.npmjs.org/table/-/table-5.4.1.tgz",
|
||||
"integrity": "sha512-E6CK1/pZe2N75rGZQotFOdmzWQ1AILtgYbMAbAjvms0S1l5IDB47zG3nCnFGB/w+7nB3vKofbLXCH7HPBo864w==",
|
||||
"version": "5.4.6",
|
||||
"resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
|
||||
"integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^6.9.1",
|
||||
"lodash": "^4.17.11",
|
||||
"ajv": "^6.10.2",
|
||||
"lodash": "^4.17.14",
|
||||
"slice-ansi": "^2.1.0",
|
||||
"string-width": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ajv": {
|
||||
"version": "6.10.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
|
||||
"integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-deep-equal": "^2.0.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"tapable": {
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
"description": "The Javascript Wails Runtime",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "eslint src/ && webpack --config webpack.config.js",
|
||||
"build": "./node_modules/.bin/eslint core/ && npm run build:prod",
|
||||
"build:prod": "./node_modules/.bin/webpack --env prod --colors",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
@@ -35,7 +36,7 @@
|
||||
"babel-loader": "^8.0.6",
|
||||
"babel-preset-minify": "^0.5.0",
|
||||
"core-js": "^3.1.4",
|
||||
"eslint": "^6.0.1",
|
||||
"eslint": "^6.5.1",
|
||||
"webpack": "^4.35.3",
|
||||
"webpack-cli": "^3.3.5"
|
||||
}
|
||||
|
||||
1
runtime/js/runtime/.npmignore
Normal file
1
runtime/js/runtime/.npmignore
Normal file
@@ -0,0 +1 @@
|
||||
bridge.js
|
||||
3
runtime/js/runtime/README.md
Normal file
3
runtime/js/runtime/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Wails Runtime
|
||||
|
||||
This module is the Javascript runtime library for the [Wails](https://wails.app) framework. It is intended to be installed as part of a [Wails](https://wails.app) project, not a standalone module.
|
||||
37
runtime/js/runtime/browser.js
Normal file
37
runtime/js/runtime/browser.js
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
_ __ _ __
|
||||
| | / /___ _(_) /____
|
||||
| | /| / / __ `/ / / ___/
|
||||
| |/ |/ / /_/ / / (__ )
|
||||
|__/|__/\__,_/_/_/____/
|
||||
The lightweight framework for web-like apps
|
||||
(c) Lea Anthony 2019-present
|
||||
*/
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
/**
|
||||
* Opens the given URL in the system browser
|
||||
*
|
||||
* @export
|
||||
* @param {string} url
|
||||
* @returns
|
||||
*/
|
||||
function OpenURL(url) {
|
||||
return window.wails.Browser.OpenURL(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the given filename using the system's default file handler
|
||||
*
|
||||
* @export
|
||||
* @param {sting} filename
|
||||
* @returns
|
||||
*/
|
||||
function OpenFile(filename) {
|
||||
return window.wails.Browser.OpenFile(filename);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
OpenURL,
|
||||
OpenFile
|
||||
};
|
||||
89
runtime/js/runtime/events.js
Normal file
89
runtime/js/runtime/events.js
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
_ __ _ __
|
||||
| | / /___ _(_) /____
|
||||
| | /| / / __ `/ / / ___/
|
||||
| |/ |/ / /_/ / / (__ )
|
||||
|__/|__/\__,_/_/_/____/
|
||||
The lightweight framework for web-like apps
|
||||
(c) Lea Anthony 2019-present
|
||||
*/
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
|
||||
/**
|
||||
* Registers an event listener that will be invoked `maxCallbacks` times before being destroyed
|
||||
*
|
||||
* @export
|
||||
* @param {string} eventName
|
||||
* @param {function} callback
|
||||
* @param {number} maxCallbacks
|
||||
*/
|
||||
function OnMultiple(eventName, callback, maxCallbacks) {
|
||||
window.wails.Events.OnMultiple(eventName, callback, maxCallbacks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an event listener that will be invoked every time the event is emitted
|
||||
*
|
||||
* @export
|
||||
* @param {string} eventName
|
||||
* @param {function} callback
|
||||
*/
|
||||
function On(eventName, callback) {
|
||||
OnMultiple(eventName, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an event listener that will be invoked once then destroyed
|
||||
*
|
||||
* @export
|
||||
* @param {string} eventName
|
||||
* @param {function} callback
|
||||
*/
|
||||
function Once(eventName, callback) {
|
||||
OnMultiple(eventName, callback, 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Emit an event with the given name and data
|
||||
*
|
||||
* @export
|
||||
* @param {string} eventName
|
||||
*/
|
||||
function Emit(eventName) {
|
||||
return window.wails.Events.Emit(eventName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Heartbeat emits the event `eventName`, every `timeInMilliseconds` milliseconds until
|
||||
* the event is acknowledged via `Event.Acknowledge`. Once this happens, `callback` is invoked ONCE
|
||||
*
|
||||
* @export
|
||||
* @param {string} eventName
|
||||
* @param {number} timeInMilliseconds
|
||||
* @param {function} callback
|
||||
*/
|
||||
function Heartbeat(eventName, timeInMilliseconds, callback) {
|
||||
window.wails.Events.Heartbeat(eventName, timeInMilliseconds, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Acknowledges a heartbeat event by name
|
||||
*
|
||||
* @export
|
||||
* @param {string} eventName
|
||||
*/
|
||||
function Acknowledge(eventName) {
|
||||
return window.wails.Events.Acknowledge(eventName);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
OnMultiple,
|
||||
On,
|
||||
Once,
|
||||
Emit,
|
||||
Heartbeat,
|
||||
Acknowledge
|
||||
};
|
||||
21
runtime/js/runtime/init.js
Normal file
21
runtime/js/runtime/init.js
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
_ __ _ __
|
||||
| | / /___ _(_) /____
|
||||
| | /| / / __ `/ / / ___/
|
||||
| |/ |/ / /_/ / / (__ )
|
||||
|__/|__/\__,_/_/_/____/
|
||||
The lightweight framework for web-like apps
|
||||
(c) Lea Anthony 2019-present
|
||||
*/
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
/**
|
||||
* Initialises the Wails runtime
|
||||
*
|
||||
* @param {function} callback
|
||||
*/
|
||||
function Init(callback) {
|
||||
window.wails._.Init(callback);
|
||||
}
|
||||
|
||||
module.exports = Init;
|
||||
70
runtime/js/runtime/log.js
Normal file
70
runtime/js/runtime/log.js
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
_ __ _ __
|
||||
| | / /___ _(_) /____
|
||||
| | /| / / __ `/ / / ___/
|
||||
| |/ |/ / /_/ / / (__ )
|
||||
|__/|__/\__,_/_/_/____/
|
||||
The lightweight framework for web-like apps
|
||||
(c) Lea Anthony 2019-present
|
||||
*/
|
||||
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
|
||||
/**
|
||||
* Log the given debug message with the backend
|
||||
*
|
||||
* @export
|
||||
* @param {string} message
|
||||
*/
|
||||
function Debug(message) {
|
||||
window.wails.Log.Debug(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given info message with the backend
|
||||
*
|
||||
* @export
|
||||
* @param {string} message
|
||||
*/
|
||||
function Info(message) {
|
||||
window.wails.Log.Info(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given warning message with the backend
|
||||
*
|
||||
* @export
|
||||
* @param {string} message
|
||||
*/
|
||||
function Warning(message) {
|
||||
window.wails.Log.Warning(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given error message with the backend
|
||||
*
|
||||
* @export
|
||||
* @param {string} message
|
||||
*/
|
||||
function Error(message) {
|
||||
window.wails.Log.Error(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given fatal message with the backend
|
||||
*
|
||||
* @export
|
||||
* @param {string} message
|
||||
*/
|
||||
function Fatal(message) {
|
||||
window.wails.Log.Fatal(message);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Debug,
|
||||
Info,
|
||||
Warning,
|
||||
Error,
|
||||
Fatal
|
||||
};
|
||||
22
runtime/js/runtime/main.js
Normal file
22
runtime/js/runtime/main.js
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
_ __ _ __
|
||||
| | / /___ _(_) /____
|
||||
| | /| / / __ `/ / / ___/
|
||||
| |/ |/ / /_/ / / (__ )
|
||||
|__/|__/\__,_/_/_/____/
|
||||
The lightweight framework for web-like apps
|
||||
(c) Lea Anthony 2019-present
|
||||
*/
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
const Log = require('./log');
|
||||
const Browser = require('./browser');
|
||||
const Events = require('./events');
|
||||
const Init = require('./init');
|
||||
|
||||
module.exports = {
|
||||
Log,
|
||||
Browser,
|
||||
Events,
|
||||
Init
|
||||
};
|
||||
28
runtime/js/runtime/package.json
Normal file
28
runtime/js/runtime/package.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "@wailsapp/runtime",
|
||||
"version": "1.0.6",
|
||||
"description": "Wails Javascript runtime library",
|
||||
"main": "main.js",
|
||||
"types": "runtime.d.ts",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/wailsapp/wails.git"
|
||||
},
|
||||
"keywords": [
|
||||
"Wails",
|
||||
"Javascript",
|
||||
"Go"
|
||||
],
|
||||
"author": "Lea Anthony <lea.anthony@gmail.com>",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/wailsapp/wails/issues"
|
||||
},
|
||||
"homepage": "https://github.com/wailsapp/wails#readme",
|
||||
"devDependencies": {
|
||||
"dts-gen": "^0.5.8"
|
||||
}
|
||||
}
|
||||
26
runtime/js/runtime/runtime.d.ts
vendored
Normal file
26
runtime/js/runtime/runtime.d.ts
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
export = wailsapp__runtime;
|
||||
|
||||
declare const wailsapp__runtime: {
|
||||
Browser: {
|
||||
OpenFile(filename: string): Promise<any>;
|
||||
OpenURL(url: string): Promise<any>;
|
||||
};
|
||||
Events: {
|
||||
Acknowledge(eventName: string): void;
|
||||
Emit(eventName: string): void;
|
||||
Heartbeat(eventName: string, timeInMilliseconds: number, callback: () => void): void;
|
||||
On(eventName: string, callback: () => void): void;
|
||||
OnMultiple(eventName: string, callback: () => void, maxCallbacks: number): void;
|
||||
Once(eventName: string, callback: () => void): void;
|
||||
};
|
||||
Init(callback: () => void): void;
|
||||
Log: {
|
||||
Debug(message: string): void;
|
||||
Error(message: string): void;
|
||||
Fatal(message: string): void;
|
||||
Info(message: string): void;
|
||||
Warning(message: string): void;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,38 +1,4 @@
|
||||
/* eslint-disable */
|
||||
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
entry: './src/main',
|
||||
mode: 'production',
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: 'wails.js'
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.m?js$/,
|
||||
exclude: /(node_modules|bower_components)/,
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
plugins: ['@babel/plugin-transform-object-assign'],
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
'useBuiltIns': 'entry',
|
||||
'corejs': {
|
||||
'version': 3,
|
||||
'proposals': true
|
||||
}
|
||||
}
|
||||
], ['minify']
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
module.exports = (env) => {
|
||||
return require(`./webpack.${env}.js`);
|
||||
};
|
||||
38
runtime/js/webpack.prod.js
Normal file
38
runtime/js/webpack.prod.js
Normal file
@@ -0,0 +1,38 @@
|
||||
/* eslint-disable */
|
||||
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
entry: './core/main',
|
||||
mode: 'production',
|
||||
output: {
|
||||
path: path.resolve(__dirname, '..', 'assets'),
|
||||
filename: 'wails.js'
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.m?js$/,
|
||||
exclude: /(node_modules|bower_components)/,
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
plugins: ['@babel/plugin-transform-object-assign'],
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
'useBuiltIns': 'entry',
|
||||
'corejs': {
|
||||
'version': 3,
|
||||
'proposals': true
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
@@ -5,8 +5,8 @@ import "github.com/wailsapp/wails/lib/logger"
|
||||
// Log exposes the logging interface to the runtime
|
||||
type Log struct{}
|
||||
|
||||
// newLog creates a new Log struct
|
||||
func newLog() *Log {
|
||||
// NewLog creates a new Log struct
|
||||
func NewLog() *Log {
|
||||
return &Log{}
|
||||
}
|
||||
|
||||
89
runtime/window.go
Normal file
89
runtime/window.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"runtime"
|
||||
|
||||
"github.com/abadojack/whatlanggo"
|
||||
"github.com/wailsapp/wails/lib/interfaces"
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/japanese"
|
||||
"golang.org/x/text/encoding/korean"
|
||||
"golang.org/x/text/encoding/simplifiedchinese"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
func detectEncoding(text string) (encoding.Encoding, string) {
|
||||
// korean
|
||||
var enc encoding.Encoding
|
||||
info := whatlanggo.Detect(text)
|
||||
//fmt.Println("Language:", info.Lang.String(), " Script:", whatlanggo.Scripts[info.Script], " Confidence: ", info.Confidence)
|
||||
switch info.Lang.String() {
|
||||
case "Korean":
|
||||
enc = korean.EUCKR
|
||||
case "Mandarin":
|
||||
enc = simplifiedchinese.GBK
|
||||
case "Japanese":
|
||||
enc = japanese.EUCJP
|
||||
}
|
||||
return enc, info.Lang.String()
|
||||
}
|
||||
|
||||
// ProcessEncoding attempts to convert CKJ strings to UTF-8
|
||||
func ProcessEncoding(text string) string {
|
||||
if runtime.GOOS != "windows" {
|
||||
return text
|
||||
}
|
||||
|
||||
encoding, _ := detectEncoding(text)
|
||||
if encoding != nil {
|
||||
var bufs bytes.Buffer
|
||||
wr := transform.NewWriter(&bufs, encoding.NewEncoder())
|
||||
_, err := wr.Write([]byte(text))
|
||||
defer wr.Close()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return bufs.String()
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
// Window exposes an interface for manipulating the window
|
||||
type Window struct {
|
||||
renderer interfaces.Renderer
|
||||
}
|
||||
|
||||
// NewWindow creates a new Window struct
|
||||
func NewWindow(renderer interfaces.Renderer) *Window {
|
||||
return &Window{
|
||||
renderer: renderer,
|
||||
}
|
||||
}
|
||||
|
||||
// SetColour sets the the window colour
|
||||
func (r *Window) SetColour(colour string) error {
|
||||
return r.renderer.SetColour(colour)
|
||||
}
|
||||
|
||||
// Fullscreen makes the window fullscreen
|
||||
func (r *Window) Fullscreen() {
|
||||
r.renderer.Fullscreen()
|
||||
}
|
||||
|
||||
// UnFullscreen attempts to restore the window to the size/position before fullscreen
|
||||
func (r *Window) UnFullscreen() {
|
||||
r.renderer.UnFullscreen()
|
||||
}
|
||||
|
||||
// SetTitle sets the the window title
|
||||
func (r *Window) SetTitle(title string) {
|
||||
title = ProcessEncoding(title)
|
||||
r.renderer.SetTitle(title)
|
||||
}
|
||||
|
||||
// Close shuts down the window and therefore the app
|
||||
func (r *Window) Close() {
|
||||
r.renderer.Close()
|
||||
}
|
||||
@@ -1,9 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Build runtime
|
||||
echo "**** Building Runtime ****"
|
||||
cd runtime/js
|
||||
npm install
|
||||
npm run build
|
||||
|
||||
cd ../..
|
||||
mewn
|
||||
|
||||
echo "**** Packing Assets ****"
|
||||
cd cmd
|
||||
mewn
|
||||
cd ..
|
||||
cd lib/renderer
|
||||
mewn
|
||||
cd ../..
|
||||
|
||||
echo "**** Installing Wails locally ****"
|
||||
cd cmd/wails
|
||||
go install
|
||||
cd ../..
|
||||
|
||||
echo "**** Tidying the mods! ****"
|
||||
go mod tidy
|
||||
|
||||
echo "**** WE ARE DONE! ****"
|
||||
|
||||
Reference in New Issue
Block a user