Compare commits

..

58 Commits

Author SHA1 Message Date
Lea Anthony
288feee1d9 angular windows fixes 2019-11-27 22:30:27 +11:00
Lea Anthony
416bd7bfc4 Merge branch 'develop' of https://github.com/wailsapp/wails into develop 2019-11-27 22:22:38 +11:00
Lea Anthony
aca72d3f7a Hidpi fix (#297)
* Add global error handler for runtime

* Set DPI Aware on windows
2019-11-27 22:22:10 +11:00
Lea Anthony
ad20e2622b Add global error handler for runtime 2019-11-27 21:28:33 +11:00
Lea Anthony
daeda501f4 Merge branch 'master' into develop 2019-11-05 14:45:30 +11:00
lea
fb1e8647bc release v0.19.0 2019-11-05 14:43:37 +11:00
Lea Anthony
723236f348 chore: bump version 2019-11-04 04:06:47 +11:00
Lea Anthony
394a823d82 fix: remove unicode flag 2019-11-04 04:02:42 +11:00
Lea Anthony
afe57802ad v0.18.15-pre 2019-11-02 21:07:02 +11:00
Lea Anthony
914642bd1d Backport (#283)
* Develop (#265)


* Patch for file dialog on OSX

* Update CONTRIBUTORS.md

* 262 add wails shutdown method (#264)

* feat: support close in bridge mode

* feat: WailsShutdown callback

Now handles proper shutdown through:
  * runtime.Window.Close()
  * Killing the main window
  * Ctrl-C

* chore: version bump

* chore: version bump

* feat: adjust binary name for OS

* fix: allow spaces in gcc path

* feat: migrate command

* fix: npm/node versions

* fix: allow IE for serve

* feat: go build script

* fix: make runtime ES2015 compliant

* fix: remove invoke patch

* fix: allow any line endings

* chore: remove legacy bridge files

* chore: latest assets
2019-11-02 21:06:02 +11:00
Lea Anthony
dafd9bcb24 fix: make binary name more os specific 2019-10-29 10:24:05 +11:00
Lea Anthony
7f75f27f6b fix: debug build should use terminal 2019-10-29 07:57:29 +11:00
Lea Anthony
d77fa1ee74 fix: npm/node version reporting 2019-10-26 05:36:00 +11:00
Lea Anthony
82e00ff83a hotfix: build issue for windows 2019-10-25 18:21:18 +11:00
Lea Anthony
14f91ab109 release v0.18.12-pre 2019-10-25 18:13:57 +11:00
Lea Anthony
19706a12a4 261 korean fonts (#276)
* fix: linting

* chore: bump version

* fix: unicode text for Windows

* fix: re-add webview_set_title
2019-10-25 18:12:56 +11:00
Lea Anthony
52e6091f0f release v0.18.11-pre 2019-10-25 17:39:12 +11:00
Lea Anthony
2db1624faf 274 support spaces in windows paths (#275)
* fix: escape windows commands

* fix: allow spaces in path to windres

* Update go.mod
2019-10-25 17:37:36 +11:00
Lea Anthony
f5d3fb0848 release v0.18.10-pre 2019-10-25 12:34:43 +11:00
Lea Anthony
85a64914aa 261 korean fonts (#273)
* fix: linting

* chore: bump version

* fix: unicode text for Windows
2019-10-25 12:33:29 +11:00
Lea Anthony
0819207e33 Bump version to v0.18.9-pre 2019-10-25 12:05:51 +11:00
Lea Anthony
50a0bc7701 fix: add flag to fix windows builds (#272) 2019-10-25 12:04:08 +11:00
Lea Anthony
c51f0cad6f chore: version bump 2019-10-24 16:13:42 +11:00
Lea Anthony
6795f6c678 Migrate tool (#270)
Experimental migration tool for projects < v1.0.0
2019-10-24 16:11:50 +11:00
Lea Anthony
315ef5f7ea fix: detect encoding on windows (#266)
* fix: linting

* chore: bump version
2019-10-24 16:04:32 +11:00
Lea Anthony
24530d9da4 fix: force install when node_modules missing (#268) 2019-10-24 09:36:42 +11:00
Lea Anthony
d572418ec3 chore: version bump 2019-10-23 14:12:38 +11:00
Lea Anthony
8c7480d277 Develop (#265)
* Patch for file dialog on OSX

* Update CONTRIBUTORS.md

* 262 add wails shutdown method (#264)

* feat: support close in bridge mode

* feat: WailsShutdown callback

Now handles proper shutdown through:
  * runtime.Window.Close()
  * Killing the main window
  * Ctrl-C

* chore: version bump
2019-10-23 14:08:56 +11:00
Lea Anthony
96fc70df26 Merge branch 'master' into develop 2019-10-23 14:07:22 +11:00
Lea Anthony
1c8d4c902a Merge branch 'develop' of github.com:wailsapp/wails into develop 2019-10-23 14:06:19 +11:00
Lea Anthony
08fc1d53d0 chore: version bump 2019-10-23 14:06:14 +11:00
Lea Anthony
6c5d5e40f4 262 add wails shutdown method (#264)
* feat: support close in bridge mode

* feat: WailsShutdown callback

Now handles proper shutdown through:
  * runtime.Window.Close()
  * Killing the main window
  * Ctrl-C
2019-10-23 14:04:41 +11:00
Lea Anthony
3f1dfe931c Update CONTRIBUTORS.md 2019-10-14 09:37:01 +11:00
Kris Raney
cb850c9653 Patch for file dialog on OSX (#258)
* Patch for file dialog on OSX
2019-10-14 09:34:50 +11:00
Lea Anthony
8d8f47363a chore: supress warnings 2019-10-12 20:19:05 +11:00
Lea Anthony
d399b7580d Develop (#255)
Hotfix
2019-10-09 19:34:24 +11:00
Lea Anthony
1b04b71254 fix: importing runtime (#254) 2019-10-09 19:33:13 +11:00
Lea Anthony
0b19ad1427 chore: version bump 2019-10-09 19:30:53 +11:00
Lea Anthony
9aca99911e Update CONTRIBUTORS.md 2019-10-09 04:47:00 +11:00
Robin Eklind
a7f61e335e cmd/wails: report error status code to OS (#252)
Fixes #251.
2019-10-09 04:44:32 +11:00
Lea Anthony
9fff0a513e chore: merge master 2019-10-08 06:30:22 +11:00
Lea Anthony
f453be12c8 hotfix: version number 2019-10-08 06:20:30 +11:00
Lea Anthony
20428b0407 Develop (#250) 2019-10-08 06:12:08 +11:00
Lea Anthony
7fd5b77cbe chore: version bump 2019-10-08 06:06:02 +11:00
Lea Anthony
d2cac50f93 fix: update runtime 2019-10-07 22:16:29 +11:00
Lea Anthony
00f1f82520 Merge branch 'master' into develop 2019-10-07 21:35:52 +11:00
Lea Anthony
02fbb14e34 chore: version bump 2019-10-07 21:32:27 +11:00
Byron
f961659ada manjaro (#248)
* manjaro

* Update go.mod
2019-10-06 19:14:05 +11:00
Lea Anthony
93942111bc fix: multiple runtime fixes 2019-10-06 14:20:59 +11:00
Lea Anthony
dc5a68acce feat: add runtime typings 2019-10-06 13:36:20 +11:00
Lea Anthony
12ff0f8c97 fix: binding more than one struct method (#245) 2019-10-01 06:13:55 +10:00
Lea Anthony
694f80434a fix: revert fix
Masterminds have fixed it upstream
2019-09-05 08:50:40 +10:00
Lea Anthony
099967ae94 hotfix: semver changed api 2019-09-03 21:52:45 +10:00
Lea Anthony
718bb1b852 patch 2019-09-03 21:46:47 +10:00
Lea Anthony
3d9e9a1342 build: fix filename 2019-08-19 22:54:06 +10:00
Lea Anthony
1a82406d2b build: add azure-pipelines script 2019-08-19 22:53:05 +10:00
Lea Anthony
54b4b157b3 Update README.md 2019-08-19 22:30:25 +10:00
Lea Anthony
add7e89097 Update README.md 2019-08-19 22:29:04 +10:00
58 changed files with 1182 additions and 181 deletions

View File

@@ -18,3 +18,6 @@ Wails is what it is because of the time and effort given by these great people.
* [Florian Didran](https://github.com/fdidron) * [Florian Didran](https://github.com/fdidron)
* [Nikolai Zimmermann](https://github.com/Chronophylos) * [Nikolai Zimmermann](https://github.com/Chronophylos)
* [Toyam Cox](https://github.com/Vaelatern) * [Toyam Cox](https://github.com/Vaelatern)
* [Robin Eklind](https://github.com/mewmew)
* [Kris Raney](https://github.com/kraney)
* [Jack Mordaunt](https://github.com/JackMordaunt)

View File

@@ -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="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://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://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://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://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> </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! 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!
@@ -60,7 +61,7 @@ _Also succesfully tested on: Zorin 15, Parrot 4.7, Linuxmint 19, Elementary 5, K
`sudo pacman -S webkit2gtk gtk3` `sudo pacman -S webkit2gtk gtk3`
_Also succesfully test on: ArcoLinuxB_ _Also succesfully test on: Manjaro & ArcoLinux_
#### Centos #### Centos
@@ -143,3 +144,7 @@ This project was mainly coded to the following albums:
* [Bloc Party - Silent Alarm](https://open.spotify.com/album/6SsIdN05HQg2GwYLfXuzLB) * [Bloc Party - Silent Alarm](https://open.spotify.com/album/6SsIdN05HQg2GwYLfXuzLB)
* [Maxthor - Another World](https://open.spotify.com/album/3tklE2Fgw1hCIUstIwPBJF) * [Maxthor - Another World](https://open.spotify.com/album/3tklE2Fgw1hCIUstIwPBJF)
* [Alun Tan Lan - Y Distawrwydd](https://open.spotify.com/album/0c32OywcLpdJCWWMC6vB8v) * [Alun Tan Lan - Y Distawrwydd](https://open.spotify.com/album/0c32OywcLpdJCWWMC6vB8v)
## Licensing
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fwailsapp%2Fwails.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_large)

60
app.go
View File

@@ -1,6 +1,12 @@
package wails package wails
import ( import (
"fmt"
"os"
"runtime"
"syscall"
"github.com/syossan27/tebata"
"github.com/wailsapp/wails/cmd" "github.com/wailsapp/wails/cmd"
"github.com/wailsapp/wails/lib/binding" "github.com/wailsapp/wails/lib/binding"
"github.com/wailsapp/wails/lib/event" "github.com/wailsapp/wails/lib/event"
@@ -61,11 +67,31 @@ func CreateApp(optionalConfig ...*AppConfig) *App {
result.config.DisableInspector = true result.config.DisableInspector = true
} }
// If running windows, do a hidpi fix
if runtime.GOOS == "windows" {
err := SetProcessDPIAware()
if err != nil {
result.log.Fatalf(err.Error())
}
}
return result return result
} }
// SetProcessDPIAware via user32.dll
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setprocessdpiaware
// Also, thanks Jack Mordaunt! https://github.com/wailsapp/wails/issues/293
func SetProcessDPIAware() error {
status, r, err := syscall.NewLazyDLL("user32.dll").NewProc("SetProcessDPIAware").Call()
if status == 0 {
return fmt.Errorf("exit status %d: %v %v", status, r, err)
}
return nil
}
// Run the app // Run the app
func (a *App) Run() error { func (a *App) Run() error {
if BuildMode != cmd.BuildModeProd { if BuildMode != cmd.BuildModeProd {
return a.cli.Run() return a.cli.Run()
} }
@@ -97,6 +123,13 @@ func (a *App) start() error {
return err 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 // Start event manager and give it our renderer
a.eventManager.Start(a.renderer) a.eventManager.Start(a.renderer)
@@ -112,8 +145,33 @@ func (a *App) start() error {
return err return err
} }
// Defer the shutdown
defer a.shutdown()
// Run the renderer // 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 // Bind allows the user to bind the given object

138
azure-pipelines.yml Normal file
View 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'

File diff suppressed because one or more lines are too long

View File

@@ -7,6 +7,7 @@ import (
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings"
"time" "time"
"github.com/leaanthony/mewn" "github.com/leaanthony/mewn"
@@ -87,6 +88,17 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
buildCommand.Add("build") buildCommand.Add("build")
if binaryName != "" { if binaryName != "" {
// Alter binary name based on OS
switch runtime.GOOS {
case "windows":
if !strings.HasSuffix(binaryName, ".exe") {
binaryName += ".exe"
}
default:
if strings.HasSuffix(binaryName, ".exe") {
binaryName = strings.TrimSuffix(binaryName, ".exe")
}
}
buildCommand.Add("-o") buildCommand.Add("-o")
buildCommand.Add(binaryName) buildCommand.Add(binaryName)
} }
@@ -103,7 +115,7 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
} }
// Add windows flags // Add windows flags
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" && buildMode == BuildModeProd {
ldflags += "-H windowsgui " ldflags += "-H windowsgui "
} }
@@ -219,6 +231,15 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
const md5sumFile = "package.json.md5" 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 we aren't forcing the install and the md5sum file exists
if !forceRebuild && fs.FileExists(md5sumFile) { if !forceRebuild && fs.FileExists(md5sumFile) {
// Yes - read contents // Yes - read contents
@@ -275,7 +296,7 @@ func InstallRuntime(caller string, projectDir string, projectOptions *ProjectOpt
// InstallBridge installs the relevant bridge javascript library // InstallBridge installs the relevant bridge javascript library
func InstallBridge(projectDir string, projectOptions *ProjectOptions) error { func InstallBridge(projectDir string, projectOptions *ProjectOptions) error {
bridgeFileData := mewn.String("../runtime/assets/bridge.js") bridgeFileData := mewn.String("../runtime/assets/bridge.js")
bridgeFileTarget := filepath.Join(projectDir, projectOptions.FrontEnd.Dir, "node_modules", "@wailsapp", "runtime", "main.js") bridgeFileTarget := filepath.Join(projectDir, projectOptions.FrontEnd.Dir, "node_modules", "@wailsapp", "runtime", "init.js")
err := fs.CreateFile(bridgeFileTarget, []byte(bridgeFileData)) err := fs.CreateFile(bridgeFileTarget, []byte(bridgeFileData))
return err return err
} }
@@ -283,7 +304,7 @@ func InstallBridge(projectDir string, projectOptions *ProjectOptions) error {
// InstallProdRuntime installs the production runtime // InstallProdRuntime installs the production runtime
func InstallProdRuntime(projectDir string, projectOptions *ProjectOptions) error { func InstallProdRuntime(projectDir string, projectOptions *ProjectOptions) error {
prodInit := mewn.String("../runtime/js/runtime/init.js") prodInit := mewn.String("../runtime/js/runtime/init.js")
bridgeFileTarget := filepath.Join(projectDir, projectOptions.FrontEnd.Dir, "node_modules", "@wailsapp", "runtime", "main.js") bridgeFileTarget := filepath.Join(projectDir, projectOptions.FrontEnd.Dir, "node_modules", "@wailsapp", "runtime", "init.js")
err := fs.CreateFile(bridgeFileTarget, []byte(prodInit)) err := fs.CreateFile(bridgeFileTarget, []byte(prodInit))
return err return err
} }

View File

@@ -43,6 +43,8 @@ const (
Kali Kali
// Neon distribution // Neon distribution
Neon Neon
// Manjaro distribution
Manjaro
) )
// DistroInfo contains all the information relating to a linux distribution // DistroInfo contains all the information relating to a linux distribution
@@ -126,6 +128,8 @@ func parseOsRelease(osRelease string) *DistroInfo {
result.Distribution = Kali result.Distribution = Kali
case "neon": case "neon":
result.Distribution = Neon result.Distribution = Neon
case "manjaro":
result.Distribution = Manjaro
default: default:
result.Distribution = Unknown result.Distribution = Unknown
} }

View File

@@ -146,18 +146,27 @@ distributions:
version: default version: default
name: Arch Linux name: Arch Linux
gccversioncommand: *gccdumpversion gccversioncommand: *gccdumpversion
programs: programs: &archdefaultprograms
- name: gcc - name: gcc
help: Please install with `sudo pacman -S gcc` and try again help: Please install with `sudo pacman -S gcc` and try again
- name: pkgconf - name: pkgconf
help: Please install with `sudo pacman -S pkgconf` and try again help: Please install with `sudo pacman -S pkgconf` and try again
- name: npm - name: npm
help: Please install with `sudo pacman -S npm` and try again help: Please install with `sudo pacman -S npm` and try again
libraries: libraries: &archdefaultlibraries
- name: gtk3 - name: gtk3
help: Please install with `sudo pacman -S gtk3` and try again help: Please install with `sudo pacman -S gtk3` and try again
- name: webkit2gtk - name: webkit2gtk
help: Please install with `sudo pacman -S webkit2gtk` and try again 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: gentoo:
id: gentoo id: gentoo
releases: releases:

View File

@@ -191,8 +191,15 @@ func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
// Build syso // Build syso
sysofile := filepath.Join(b.fs.Cwd(), basename+"-res.syso") sysofile := filepath.Join(b.fs.Cwd(), basename+"-res.syso")
windresCommand := []string{"windres", "-o", sysofile, tgtRCFile}
err := NewProgramHelper().RunCommandArray(windresCommand) batfile, err := fs.LocalDir(".")
if err != nil {
return err
}
windresBatFile := filepath.Join(batfile.fullPath, "windres.bat")
windresCommand := []string{windresBatFile, sysofile, tgtRCFile}
err = NewProgramHelper().RunCommandArray(windresCommand)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -100,6 +100,19 @@ func (p *ProgramHelper) InstallGoPackage(packageName string) error {
return err 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 // RunCommand runs the given command
func (p *ProgramHelper) RunCommand(command string) error { func (p *ProgramHelper) RunCommand(command string) error {
args := strings.Split(command, " ") args := strings.Split(command, " ")
@@ -115,6 +128,7 @@ func (p *ProgramHelper) RunCommandArray(args []string, dir ...string) error {
fmt.Printf("ERROR: Looks like '%s' isn't installed. Please install and try again.", program) fmt.Printf("ERROR: Looks like '%s' isn't installed. Please install and try again.", program)
return err return err
} }
args = args[1:] args = args[1:]
var stderr string var stderr string
var stdout string var stdout string

View File

@@ -13,6 +13,18 @@ import (
"github.com/leaanthony/slicer" "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 { type author struct {
Name string `json:"name"` Name string `json:"name"`
Email string `json:"email"` Email string `json:"email"`
@@ -153,6 +165,23 @@ func (po *ProjectOptions) Defaults() {
po.WailsVersion = Version 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 // PromptForInputs asks the user to input project details
func (po *ProjectOptions) PromptForInputs() error { func (po *ProjectOptions) PromptForInputs() error {

View File

@@ -276,7 +276,7 @@ func CheckDependencies(logger *Logger) (bool, error) {
switch distroInfo.Distribution { switch distroInfo.Distribution {
case Ubuntu, Debian, Zorin, Parrot, Linuxmint, Elementary, Kali, Neon: case Ubuntu, Debian, Zorin, Parrot, Linuxmint, Elementary, Kali, Neon:
libraryChecker = DpkgInstalled libraryChecker = DpkgInstalled
case Arch: case Arch, Manjaro:
libraryChecker = PacmanInstalled libraryChecker = PacmanInstalled
case CentOS, Fedora: case CentOS, Fedora:
libraryChecker = RpmInstalled libraryChecker = RpmInstalled

View File

@@ -9,4 +9,4 @@
last 2 versions last 2 versions
Firefox ESR Firefox ESR
not dead not dead
not IE 9-11 # For IE 9-11 support, remove 'not'. IE 9-11 # For IE 9-11 support, remove 'not'.

View File

@@ -22,6 +22,7 @@
"@angular/platform-browser-dynamic": "~8.0.1", "@angular/platform-browser-dynamic": "~8.0.1",
"@angular/router": "~8.0.1", "@angular/router": "~8.0.1",
"@wailsapp/runtime": "^1.0.0", "@wailsapp/runtime": "^1.0.0",
"core-js": "^3.4.4",
"ngx-build-plus": "^8.0.3", "ngx-build-plus": "^8.0.3",
"rxjs": "~6.4.0", "rxjs": "~6.4.0",
"tslib": "^1.9.0", "tslib": "^1.9.0",

View File

@@ -1,3 +1,4 @@
import 'core-js/stable';
import { enableProdMode } from '@angular/core'; import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
@@ -6,7 +7,7 @@ import { environment } from './environments/environment';
import 'zone.js' import 'zone.js'
import Wails from '@wailsapp/runtime'; import * as Wails from '@wailsapp/runtime';
if (environment.production) { if (environment.production) {
enableProdMode(); enableProdMode();

View File

@@ -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);
}
}
};

View File

@@ -11,7 +11,7 @@
"module": "esnext", "module": "esnext",
"moduleResolution": "node", "moduleResolution": "node",
"importHelpers": true, "importHelpers": true,
"target": "es2015", "target": "es5",
"typeRoots": [ "typeRoots": [
"node_modules/@types" "node_modules/@types"
], ],
@@ -20,4 +20,4 @@
"dom" "dom"
] ]
} }
} }

View File

@@ -11,7 +11,7 @@ func basic() string {
func main() { func main() {
js := mewn.String("./frontend/dist/my-app/main-es2015.js") js := mewn.String("./frontend/dist/my-app/main.js")
css := mewn.String("./frontend/dist/my-app/styles.css") css := mewn.String("./frontend/dist/my-app/styles.css")
app := wails.CreateApp(&wails.AppConfig{ app := wails.CreateApp(&wails.AppConfig{

View File

@@ -4,7 +4,7 @@ import 'core-js/stable';
import './index.css'; import './index.css';
import App from './App'; import App from './App';
import Wails from '@wailsapp/runtime'; import * as Wails from '@wailsapp/runtime';
Wails.Init(() => { Wails.Init(() => {
ReactDOM.render(<App />, document.getElementById('app')); ReactDOM.render(<App />, document.getElementById('app'));

View File

@@ -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);
}
}
};

View File

@@ -4,7 +4,7 @@ import App from './App.vue';
Vue.config.productionTip = false; Vue.config.productionTip = false;
Vue.config.devtools = true; Vue.config.devtools = true;
import Wails from '@wailsapp/runtime'; import * as Wails from '@wailsapp/runtime';
Wails.Init(() => { Wails.Init(() => {
new Vue({ new Vue({

View File

@@ -12,7 +12,7 @@ import App from './App.vue';
Vue.config.productionTip = false; Vue.config.productionTip = false;
Vue.config.devtools = true; Vue.config.devtools = true;
import Wails from '@wailsapp/runtime'; import * as Wails from '@wailsapp/runtime';
Wails.Init(() => { Wails.Init(() => {
new Vue({ new Vue({

View File

@@ -1,4 +1,4 @@
package cmd package cmd
// Version - Wails version // Version - Wails version
const Version = "v0.17.15-pre" const Version = "v0.19.0"

408
cmd/wails/15_migrate.go Normal file
View 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
}

View File

@@ -80,15 +80,16 @@ To help you in this process, we will ask for some information, add Go/Wails deta
npm := program.FindProgram("npm") npm := program.FindProgram("npm")
if npm != nil { if npm != nil {
stdout, _, _, _ := npm.Run("--version") stdout, _, _, _ := npm.Run("--version")
nodeVersion = stdout npmVersion = stdout
nodeVersion = nodeVersion[:len(nodeVersion)-1] npmVersion = npmVersion[:len(npmVersion)-1]
npmVersion = strings.TrimSpace(npmVersion)
} }
node := program.FindProgram("node") node := program.FindProgram("node")
if node != nil { if node != nil {
stdout, _, _, _ := node.Run("--version") stdout, _, _, _ := node.Run("--version")
npmVersion = stdout nodeVersion = stdout
npmVersion = npmVersion[:len(npmVersion)-1] nodeVersion = nodeVersion[:len(nodeVersion)-1]
} }
str.WriteString("\n| Name | Value |\n| ----- | ----- |\n") str.WriteString("\n| Name | Value |\n| ----- | ----- |\n")

View File

@@ -1,6 +1,9 @@
package main package main
import ( import (
"os"
"os/exec"
"github.com/wailsapp/wails/cmd" "github.com/wailsapp/wails/cmd"
) )
@@ -15,5 +18,9 @@ func main() {
err := app.Run() err := app.Run()
if err != nil { if err != nil {
logger.Error(err.Error()) logger.Error(err.Error())
if exitErr, ok := err.(*exec.ExitError); ok {
os.Exit(exitErr.ExitCode())
}
os.Exit(1)
} }
} }

1
cmd/windres.bat Normal file
View File

@@ -0,0 +1 @@
windres.exe -o %1 %2

View File

@@ -1,6 +1,9 @@
package wails package wails
import "github.com/leaanthony/mewn" import (
"github.com/leaanthony/mewn"
"github.com/wailsapp/wails/runtime"
)
// AppConfig is the configuration structure used when creating a Wails App object // AppConfig is the configuration structure used when creating a Wails App object
type AppConfig struct { type AppConfig struct {
@@ -65,7 +68,7 @@ func (a *AppConfig) merge(in *AppConfig) error {
a.CSS = in.CSS a.CSS = in.CSS
} }
if in.Title != "" { if in.Title != "" {
a.Title = in.Title a.Title = runtime.ProcessEncoding(in.Title)
} }
if in.Colour != "" { if in.Colour != "" {

3
go.mod
View File

@@ -2,6 +2,7 @@ module github.com/wailsapp/wails
require ( require (
github.com/Masterminds/semver v1.4.2 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/cssmin v0.0.0-20151210170030-fb8d9b44afdc // indirect
github.com/dchest/htmlmin v0.0.0-20150526090704-e254725e81ac github.com/dchest/htmlmin v0.0.0-20150526090704-e254725e81ac
github.com/dchest/jsmin v0.0.0-20160823214000-faeced883947 // indirect github.com/dchest/jsmin v0.0.0-20160823214000-faeced883947 // indirect
@@ -22,9 +23,11 @@ require (
github.com/pkg/errors v0.8.1 // indirect github.com/pkg/errors v0.8.1 // indirect
github.com/sirupsen/logrus v1.4.1 github.com/sirupsen/logrus v1.4.1
github.com/stretchr/testify v1.3.0 // indirect github.com/stretchr/testify v1.3.0 // indirect
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 // indirect golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 // indirect
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5 // indirect golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5 // indirect
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862 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/AlecAivazis/survey.v1 v1.8.4
gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22 gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22
) )

5
go.sum
View File

@@ -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/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 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= 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.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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -68,6 +70,8 @@ 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.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba h1:2DHfQOxcpWdGf5q5IzCUFPNvRX9Icf+09RvQK2VnJq0=
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba/go.mod h1:iLnlXG2Pakcii2CU0cbY07DRCSvpWNa7nFxtevhOChk=
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-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 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk=
@@ -83,6 +87,7 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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 h1:rM0ROo5vb9AdYJi1110yjWGMej9ITfKddS89P3Fkhug=
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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= 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 h1:10xXXN3wgIhPheb5NI58zFgZv32Ana7P3Tl4shW+0Qc=
gopkg.in/AlecAivazis/survey.v1 v1.8.4/go.mod h1:iBNOmqKz/NUbZx3bA+4hAGLRC7fSK7tgtVDT4tB22XA= gopkg.in/AlecAivazis/survey.v1 v1.8.4/go.mod h1:iBNOmqKz/NUbZx3bA+4hAGLRC7fSK7tgtVDT4tB22XA=

View File

@@ -16,6 +16,7 @@ type Manager struct {
functions map[string]*boundFunction functions map[string]*boundFunction
internalMethods *internalMethods internalMethods *internalMethods
initMethods []*boundMethod initMethods []*boundMethod
shutdownMethods []*boundMethod
log *logger.CustomLogger log *logger.CustomLogger
renderer interfaces.Renderer renderer interfaces.Renderer
runtime interfaces.Runtime // The runtime object to pass to bound structs 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 { if newMethod.isWailsInit {
b.log.Debugf("Detected WailsInit function: %s", fullMethodName) b.log.Debugf("Detected WailsInit function: %s", fullMethodName)
b.initMethods = append(b.initMethods, newMethod) 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 { } else {
// Save boundMethod // Save boundMethod
b.log.Infof("Bound Method: %s()", fullMethodName) b.log.Infof("Bound Method: %s()", fullMethodName)
@@ -292,3 +296,13 @@ func (b *Manager) callWailsInitMethods() error {
} }
return nil 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")
}

View File

@@ -18,6 +18,7 @@ type boundMethod struct {
log *logger.CustomLogger log *logger.CustomLogger
hasErrorReturnType bool // Indicates if there is an error return type hasErrorReturnType bool // Indicates if there is an error return type
isWailsInit bool isWailsInit bool
isWailsShutdown bool
} }
// Creates a new bound method based on the given method + type // 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() err = result.processWailsInit()
} }
// Are we a WailsShutdown method?
if result.Name == "WailsShutdown" {
err = result.processWailsShutdown()
}
return result, err return result, err
} }
@@ -211,3 +217,20 @@ func (b *boundMethod) processWailsInit() error {
return nil 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
}

View File

@@ -3,18 +3,21 @@ package event
import ( import (
"fmt" "fmt"
"sync" "sync"
"time"
"github.com/wailsapp/wails/lib/interfaces"
"github.com/wailsapp/wails/lib/logger" "github.com/wailsapp/wails/lib/logger"
"github.com/wailsapp/wails/lib/messages" "github.com/wailsapp/wails/lib/messages"
"github.com/wailsapp/wails/lib/interfaces"
) )
// Manager handles and processes events // Manager handles and processes events
type Manager struct { type Manager struct {
incomingEvents chan *messages.EventData incomingEvents chan *messages.EventData
listeners map[string][]*eventListener listeners map[string][]*eventListener
exit bool running bool
log *logger.CustomLogger log *logger.CustomLogger
renderer interfaces.Renderer // Messages will be dispatched to the frontend renderer interfaces.Renderer // Messages will be dispatched to the frontend
wg sync.WaitGroup
} }
// NewManager creates a new event manager with a 100 event buffer // NewManager creates a new event manager with a 100 event buffer
@@ -22,7 +25,7 @@ func NewManager() interfaces.EventManager {
return &Manager{ return &Manager{
incomingEvents: make(chan *messages.EventData, 100), incomingEvents: make(chan *messages.EventData, 100),
listeners: make(map[string][]*eventListener), listeners: make(map[string][]*eventListener),
exit: false, running: false,
log: logger.NewCustomLogger("Events"), log: logger.NewCustomLogger("Events"),
} }
} }
@@ -87,15 +90,14 @@ func (e *Manager) Start(renderer interfaces.Renderer) {
// Store renderer // Store renderer
e.renderer = renderer e.renderer = renderer
// Set up waitgroup so we can wait for goroutine to start // Set up waitgroup so we can wait for goroutine to quit
var wg sync.WaitGroup e.running = true
wg.Add(1) e.wg.Add(1)
// Run main loop in separate goroutine // Run main loop in separate goroutine
go func() { go func() {
wg.Done()
e.log.Info("Listening") e.log.Info("Listening")
for e.exit == false { for e.running {
// TODO: Listen for application exit // TODO: Listen for application exit
select { select {
case event := <-e.incomingEvents: 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() { // Shutdown is called when exiting the Application
e.exit = true func (e *Manager) Shutdown() {
e.log.Debug("Shutting Down")
e.running = false
e.log.Debug("Waiting for main loop to exit")
e.wg.Wait()
} }

View File

@@ -7,4 +7,5 @@ type BindingManager interface {
Bind(object interface{}) Bind(object interface{})
Start(renderer Renderer, runtime Runtime) error Start(renderer Renderer, runtime Runtime) error
ProcessCall(callData *messages.CallData) (result interface{}, err error) ProcessCall(callData *messages.CallData) (result interface{}, err error)
Shutdown()
} }

View File

@@ -8,4 +8,5 @@ type EventManager interface {
Emit(eventName string, optionalData ...interface{}) Emit(eventName string, optionalData ...interface{})
On(eventName string, callback func(...interface{})) On(eventName string, callback func(...interface{}))
Start(Renderer) Start(Renderer)
Shutdown()
} }

View File

@@ -5,4 +5,5 @@ type IPCManager interface {
BindRenderer(Renderer) BindRenderer(Renderer)
Dispatch(message string) Dispatch(message string)
Start(eventManager EventManager, bindingManager BindingManager) Start(eventManager EventManager, bindingManager BindingManager)
Shutdown()
} }

View File

@@ -2,6 +2,8 @@ package ipc
import ( import (
"fmt" "fmt"
"sync"
"time"
"github.com/wailsapp/wails/lib/interfaces" "github.com/wailsapp/wails/lib/interfaces"
"github.com/wailsapp/wails/lib/logger" "github.com/wailsapp/wails/lib/logger"
@@ -12,18 +14,20 @@ import (
type Manager struct { type Manager struct {
renderer interfaces.Renderer // The renderer renderer interfaces.Renderer // The renderer
messageQueue chan *ipcMessage messageQueue chan *ipcMessage
// quitChannel chan struct{} quitChannel chan struct{}
// signals chan os.Signal // signals chan os.Signal
log *logger.CustomLogger log *logger.CustomLogger
eventManager interfaces.EventManager eventManager interfaces.EventManager
bindingManager interfaces.BindingManager bindingManager interfaces.BindingManager
running bool
wg sync.WaitGroup
} }
// NewManager creates a new IPC Manager // NewManager creates a new IPC Manager
func NewManager() interfaces.IPCManager { func NewManager() interfaces.IPCManager {
result := &Manager{ result := &Manager{
messageQueue: make(chan *ipcMessage, 100), messageQueue: make(chan *ipcMessage, 100),
// quitChannel: make(chan struct{}), quitChannel: make(chan struct{}),
// signals: make(chan os.Signal, 1), // signals: make(chan os.Signal, 1),
log: logger.NewCustomLogger("IPC"), log: logger.NewCustomLogger("IPC"),
} }
@@ -44,9 +48,12 @@ func (i *Manager) Start(eventManager interfaces.EventManager, bindingManager int
i.log.Info("Starting") i.log.Info("Starting")
// signal.Notify(manager.signals, os.Interrupt) // signal.Notify(manager.signals, os.Interrupt)
i.running = true
// Keep track of this goroutine
i.wg.Add(1)
go func() { go func() {
running := true for i.running {
for running {
select { select {
case incomingMessage := <-i.messageQueue: case incomingMessage := <-i.messageQueue:
i.log.DebugFields("Processing message", logger.Fields{ i.log.DebugFields("Processing message", logger.Fields{
@@ -117,15 +124,12 @@ func (i *Manager) Start(eventManager interfaces.EventManager, bindingManager int
i.log.DebugFields("Finished processing message", logger.Fields{ i.log.DebugFields("Finished processing message", logger.Fields{
"1D": &incomingMessage, "1D": &incomingMessage,
}) })
// case <-manager.quitChannel: default:
// Debug("[MessageQueue] Quit caught") time.Sleep(1 * time.Millisecond)
// running = false
// case <-manager.signals:
// Debug("[MessageQueue] Signal caught")
// running = false
} }
} }
i.log.Debug("Stopping") i.log.Debug("Stopping")
i.wg.Done()
}() }()
} }
@@ -167,3 +171,11 @@ func (i *Manager) SendResponse(response *ipcResponse) error {
// Call back to the front end // Call back to the front end
return i.renderer.Callback(data) 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()
}

View File

@@ -156,7 +156,7 @@ func (h *Bridge) Run() error {
h.log.Info("The frontend will connect automatically.") h.log.Info("The frontend will connect automatically.")
err := h.server.ListenAndServe() err := h.server.ListenAndServe()
if err != nil { if err != nil && err != http.ErrServerClosed {
h.log.Fatal(err.Error()) h.log.Fatal(err.Error())
} }
return err return err
@@ -250,5 +250,9 @@ func (h *Bridge) SetTitle(title string) {
// Close is unsupported for Bridge but required // Close is unsupported for Bridge but required
// for the Renderer interface // for the Renderer interface
func (h *Bridge) Close() { func (h *Bridge) Close() {
h.log.Warn("Close() unsupported in bridge mode") 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

View File

@@ -1,6 +1,5 @@
// Package wails implements Go bindings to https://github.com/zserge/webview C library. // Package webview implements Go bindings to https://github.com/zserge/webview C library.
// It is a modified version of webview.go from that repository // It is a modified version of webview.go from that repository
// Bindings closely repeat the C APIs and include both, a simplified // 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 // 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. // advanced and featureful set of APIs, including Go-to-JavaScript bindings.
@@ -11,10 +10,10 @@
package webview package webview
/* /*
#cgo linux openbsd freebsd CFLAGS: -DWEBVIEW_GTK=1 #cgo linux openbsd freebsd CFLAGS: -DWEBVIEW_GTK=1 -Wno-deprecated-declarations
#cgo linux openbsd freebsd pkg-config: gtk+-3.0 webkit2gtk-4.0 #cgo linux openbsd freebsd pkg-config: gtk+-3.0 webkit2gtk-4.0
#cgo windows CFLAGS: -DWEBVIEW_WINAPI=1 #cgo windows CFLAGS: -DWEBVIEW_WINAPI=1 -std=c99
#cgo windows LDFLAGS: -lole32 -lcomctl32 -loleaut32 -luuid -lgdi32 #cgo windows LDFLAGS: -lole32 -lcomctl32 -loleaut32 -luuid -lgdi32
#cgo darwin CFLAGS: -DWEBVIEW_COCOA=1 -x objective-c #cgo darwin CFLAGS: -DWEBVIEW_COCOA=1 -x objective-c

View File

@@ -86,7 +86,7 @@ struct webview_priv
NSAutoreleasePool *pool; NSAutoreleasePool *pool;
NSWindow *window; NSWindow *window;
WebView *webview; WebView *webview;
id windowDelegate; id delegate;
int should_exit; int should_exit;
}; };
#else #else
@@ -1038,7 +1038,7 @@ struct webview_priv
return S_FALSE; return S_FALSE;
} }
static const TCHAR *classname = "WebView"; static const TCHAR *classname = TEXT("WebView");
static const SAFEARRAYBOUND ArrayBound = {1, 0}; static const SAFEARRAYBOUND ArrayBound = {1, 0};
static IOleClientSiteVtbl MyIOleClientSiteTable = { static IOleClientSiteVtbl MyIOleClientSiteTable = {
@@ -1227,7 +1227,7 @@ struct webview_priv
} }
VariantInit(&myURL); VariantInit(&myURL);
myURL.vt = VT_BSTR; myURL.vt = VT_BSTR;
#ifndef UNICODE // #ifndef UNICODE
{ {
wchar_t *buffer = webview_to_utf16(webPageName); wchar_t *buffer = webview_to_utf16(webPageName);
if (buffer == NULL) if (buffer == NULL)
@@ -1237,9 +1237,9 @@ struct webview_priv
myURL.bstrVal = SysAllocString(buffer); myURL.bstrVal = SysAllocString(buffer);
GlobalFree(buffer); GlobalFree(buffer);
} }
#else // #else
myURL.bstrVal = SysAllocString(webPageName); // myURL.bstrVal = SysAllocString(webPageName);
#endif // #endif
if (!myURL.bstrVal) if (!myURL.bstrVal)
{ {
badalloc: badalloc:
@@ -1277,7 +1277,7 @@ struct webview_priv
if (!SafeArrayAccessData(sfArray, (void **)&pVar)) if (!SafeArrayAccessData(sfArray, (void **)&pVar))
{ {
pVar->vt = VT_BSTR; pVar->vt = VT_BSTR;
#ifndef UNICODE // #ifndef UNICODE
{ {
wchar_t *buffer = webview_to_utf16(url); wchar_t *buffer = webview_to_utf16(url);
if (buffer == NULL) if (buffer == NULL)
@@ -1287,9 +1287,9 @@ struct webview_priv
bstr = SysAllocString(buffer); bstr = SysAllocString(buffer);
GlobalFree(buffer); GlobalFree(buffer);
} }
#else // #else
bstr = SysAllocString(string); // bstr = SysAllocString(url);
#endif // #endif
if ((pVar->bstrVal = bstr)) if ((pVar->bstrVal = bstr))
{ {
htmlDoc2->lpVtbl->write(htmlDoc2, sfArray); htmlDoc2->lpVtbl->write(htmlDoc2, sfArray);
@@ -1404,6 +1404,7 @@ struct webview_priv
{ {
return -1; return -1;
} }
ZeroMemory(&wc, sizeof(WNDCLASSEX)); ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX); wc.cbSize = sizeof(WNDCLASSEX);
wc.hInstance = hInstance; wc.hInstance = hInstance;
@@ -1431,10 +1432,24 @@ struct webview_priv
rect.bottom = rect.bottom - rect.top + top; rect.bottom = rect.bottom - rect.top + top;
rect.top = top; rect.top = top;
#ifdef UNICODE
wchar_t *u16title = webview_to_utf16(w->title);
if (u16title == NULL)
{
return -1;
}
w->priv.hwnd = w->priv.hwnd =
CreateWindowEx(0, classname, u16title, style, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
HWND_DESKTOP, NULL, hInstance, (void *)w);
#else
w->priv.hwnd =
CreateWindowEx(0, classname, w->title, style, rect.left, rect.top, CreateWindowEx(0, classname, w->title, style, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top, rect.right - rect.left, rect.bottom - rect.top,
HWND_DESKTOP, NULL, hInstance, (void *)w); HWND_DESKTOP, NULL, hInstance, (void *)w);
#endif
if (w->priv.hwnd == 0) if (w->priv.hwnd == 0)
{ {
OleUninitialize(); OleUninitialize();
@@ -1445,7 +1460,14 @@ struct webview_priv
DisplayHTMLPage(w); DisplayHTMLPage(w);
#ifdef UNICODE
SetWindowText(w->priv.hwnd, u16title);
GlobalFree(u16title);
#else
SetWindowText(w->priv.hwnd, w->title); SetWindowText(w->priv.hwnd, w->title);
#endif
ShowWindow(w->priv.hwnd, SW_SHOWDEFAULT); ShowWindow(w->priv.hwnd, SW_SHOWDEFAULT);
UpdateWindow(w->priv.hwnd); UpdateWindow(w->priv.hwnd);
SetFocus(w->priv.hwnd); SetFocus(w->priv.hwnd);
@@ -1581,9 +1603,20 @@ struct webview_priv
WEBVIEW_API void webview_set_title(struct webview *w, const char *title) WEBVIEW_API void webview_set_title(struct webview *w, const char *title)
{ {
#ifdef UNICODE
wchar_t *u16title = webview_to_utf16(title);
if (u16title == NULL)
{
return;
}
SetWindowText(w->priv.hwnd, u16title);
GlobalFree(u16title);
#else
SetWindowText(w->priv.hwnd, title); SetWindowText(w->priv.hwnd, title);
#endif
} }
WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen) WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen)
{ {
if (w->priv.is_fullscreen == !!fullscreen) if (w->priv.is_fullscreen == !!fullscreen)
@@ -1894,6 +1927,22 @@ struct webview_priv
[script setValue:self forKey:@"external"]; [script setValue:self forKey:@"external"];
} }
static void webview_run_input_open_panel(id self, SEL cmd, id webview,
id listener, BOOL allowMultiple) {
char filename[256] = "";
struct webview *w =
(struct webview *)objc_getAssociatedObject(self, "webview");
webview_dialog(w, WEBVIEW_DIALOG_TYPE_OPEN, WEBVIEW_DIALOG_FLAG_FILE, "", "",
filename, 255);
if (strlen(filename)) {
[listener chooseFilename:[NSString stringWithUTF8String:filename]];
} else {
[listener cancel];
}
}
static void webview_external_invoke(id self, SEL cmd, id arg) static void webview_external_invoke(id self, SEL cmd, id arg)
{ {
struct webview *w = struct webview *w =
@@ -1927,12 +1976,17 @@ struct webview_priv
class_addMethod(webViewDelegateClass, class_addMethod(webViewDelegateClass,
sel_registerName("webView:didClearWindowObject:forFrame:"), sel_registerName("webView:didClearWindowObject:forFrame:"),
(IMP)webview_did_clear_window_object, "v@:@@@"); (IMP)webview_did_clear_window_object, "v@:@@@");
class_addMethod(
webViewDelegateClass,
sel_registerName("webView:runOpenPanelForFileButtonWithResultListener:"
"allowMultipleFiles:"),
(IMP)webview_run_input_open_panel, "v@:@@c");
class_addMethod(webViewDelegateClass, sel_registerName("invoke:"), class_addMethod(webViewDelegateClass, sel_registerName("invoke:"),
(IMP)webview_external_invoke, "v@:@"); (IMP)webview_external_invoke, "v@:@");
objc_registerClassPair(webViewDelegateClass); objc_registerClassPair(webViewDelegateClass);
w->priv.windowDelegate = [[webViewDelegateClass alloc] init]; w->priv.delegate = [[webViewDelegateClass alloc] init];
objc_setAssociatedObject(w->priv.windowDelegate, "webview", (id)(w), objc_setAssociatedObject(w->priv.delegate, "webview", (id)(w),
OBJC_ASSOCIATION_ASSIGN); OBJC_ASSOCIATION_ASSIGN);
NSRect r = NSMakeRect(0, 0, w->width, w->height); NSRect r = NSMakeRect(0, 0, w->width, w->height);
@@ -1960,7 +2014,7 @@ struct webview_priv
NSString *nsTitle = [NSString stringWithUTF8String:w->title]; NSString *nsTitle = [NSString stringWithUTF8String:w->title];
[w->priv.window setTitle:nsTitle]; [w->priv.window setTitle:nsTitle];
[w->priv.window setDelegate:w->priv.windowDelegate]; [w->priv.window setDelegate:w->priv.delegate];
[w->priv.window center]; [w->priv.window center];
// NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"wat"]; // NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"wat"];
@@ -1989,7 +2043,8 @@ struct webview_priv
[w->priv.webview setAutoresizesSubviews:YES]; [w->priv.webview setAutoresizesSubviews:YES];
[w->priv.webview [w->priv.webview
setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
w->priv.webview.frameLoadDelegate = w->priv.windowDelegate; w->priv.webview.frameLoadDelegate = w->priv.delegate;
w->priv.webview.UIDelegate = w->priv.delegate;
[[w->priv.window contentView] addSubview:w->priv.webview]; [[w->priv.window contentView] addSubview:w->priv.webview];
[w->priv.window orderFrontRegardless]; [w->priv.window orderFrontRegardless];

View File

@@ -95,13 +95,6 @@ function startBridge() {
window.wailsbridge.reconnectOverlay.style.display = 'none'; window.wailsbridge.reconnectOverlay.style.display = 'none';
} }
// Bridge external.invoke
window.external = {
invoke: function (msg) {
window.wailsbridge.websocket.send(msg);
}
};
// Adds a script to the Dom. // Adds a script to the Dom.
// Removes it if second parameter is true. // Removes it if second parameter is true.
function addScript(script, remove) { function addScript(script, remove) {
@@ -214,4 +207,4 @@ function Init(callback) {
start(callback); start(callback);
} }
module.exports = { Init }; module.exports = Init;

File diff suppressed because one or more lines are too long

View File

@@ -15,10 +15,7 @@
"error", "error",
"tab" "tab"
], ],
"linebreak-style": [ "linebreak-style": 0,
"error",
"unix"
],
"quotes": [ "quotes": [
"error", "error",
"single" "single"
@@ -28,4 +25,4 @@
"always" "always"
] ]
} }
} }

View File

@@ -15,7 +15,11 @@ The lightweight framework for web-like apps
* @param {string} message * @param {string} message
*/ */
function Invoke(message) { function Invoke(message) {
window.external.invoke(message); if ( window.wailsbridge ) {
window.wailsbridge.websocket.send(message);
} else {
window.external.invoke(message);
}
} }
/** /**

View File

@@ -10,7 +10,7 @@ The lightweight framework for web-like apps
/* jshint esversion: 6 */ /* jshint esversion: 6 */
import * as Log from './log'; import * as Log from './log';
import * as Browser from './browser'; import * as Browser from './browser';
import { On, Emit, Notify, Heartbeat, Acknowledge } from './events'; import { On, OnMultiple, Emit, Notify, Heartbeat, Acknowledge } from './events';
import { NewBinding } from './bindings'; import { NewBinding } from './bindings';
import { Callback } from './calls'; import { Callback } from './calls';
import { AddScript, InjectCSS } from './utils'; import { AddScript, InjectCSS } from './utils';
@@ -35,6 +35,7 @@ var runtime = {
Browser, Browser,
Events: { Events: {
On, On,
OnMultiple,
Emit, Emit,
Heartbeat, Heartbeat,
Acknowledge, Acknowledge,
@@ -45,6 +46,16 @@ var runtime = {
// Augment global // Augment global
Object.assign(window.wails, runtime); Object.assign(window.wails, runtime);
// Setup global error handler
window.onerror = function (msg, url, lineNo, columnNo, error) {
window.wails.Log.Error('**** Caught Unhandled Error ****');
window.wails.Log.Error('Message: ' + msg);
window.wails.Log.Error('URL: ' + url);
window.wails.Log.Error('Line No: ' + lineNo);
window.wails.Log.Error('Column No: ' + columnNo);
window.wails.Log.Error('error: ' + error);
};
// Emit loaded event // Emit loaded event
Emit('wails:loaded'); Emit('wails:loaded');

View File

@@ -56,13 +56,15 @@
"version": "0.3.2", "version": "0.3.2",
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
"integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
"dev": true "dev": true,
"optional": true
}, },
"braces": { "braces": {
"version": "2.3.2", "version": "2.3.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
"integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"arr-flatten": "^1.1.0", "arr-flatten": "^1.1.0",
"array-unique": "^0.3.2", "array-unique": "^0.3.2",
@@ -81,6 +83,7 @@
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"is-extendable": "^0.1.0" "is-extendable": "^0.1.0"
} }
@@ -253,6 +256,7 @@
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
"integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"extend-shallow": "^2.0.1", "extend-shallow": "^2.0.1",
"is-number": "^3.0.0", "is-number": "^3.0.0",
@@ -265,6 +269,7 @@
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"is-extendable": "^0.1.0" "is-extendable": "^0.1.0"
} }
@@ -330,7 +335,8 @@
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
"dev": true "dev": true,
"optional": true
}, },
"is-glob": { "is-glob": {
"version": "4.0.1", "version": "4.0.1",
@@ -347,6 +353,7 @@
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
"integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"kind-of": "^3.0.2" "kind-of": "^3.0.2"
}, },
@@ -356,6 +363,7 @@
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"is-buffer": "^1.1.5" "is-buffer": "^1.1.5"
} }
@@ -366,13 +374,15 @@
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
"dev": true "dev": true,
"optional": true
}, },
"kind-of": { "kind-of": {
"version": "6.0.2", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
"integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
"dev": true "dev": true,
"optional": true
}, },
"micromatch": { "micromatch": {
"version": "3.1.10", "version": "3.1.10",
@@ -2881,9 +2891,9 @@
"dev": true "dev": true
}, },
"eslint": { "eslint": {
"version": "6.2.2", "version": "6.5.1",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-6.2.2.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.5.1.tgz",
"integrity": "sha512-mf0elOkxHbdyGX1IJEUsNBzCDdyoUgljF3rRlgfyYh0pwGnreLc0jjD6ZuleOibjmnUWZLY2eXwSooeOgGJ2jw==", "integrity": "sha512-32h99BoLYStT1iq1v2P9uwpyznQ4M2jRiFB6acitKz52Gqn+vPaMDUTB1bYi1WN4Nquj2w+t+bimYUG83DC55A==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/code-frame": "^7.0.0", "@babel/code-frame": "^7.0.0",
@@ -3001,9 +3011,9 @@
}, },
"dependencies": { "dependencies": {
"acorn": { "acorn": {
"version": "7.0.0", "version": "7.1.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.0.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz",
"integrity": "sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ==", "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==",
"dev": true "dev": true
} }
} }
@@ -3577,7 +3587,8 @@
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
@@ -3598,12 +3609,14 @@
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@@ -3618,17 +3631,20 @@
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
@@ -3745,7 +3761,8 @@
"inherits": { "inherits": {
"version": "2.0.3", "version": "2.0.3",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
@@ -3757,6 +3774,7 @@
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
@@ -3771,6 +3789,7 @@
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
@@ -3778,12 +3797,14 @@
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"minipass": { "minipass": {
"version": "2.3.5", "version": "2.3.5",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"safe-buffer": "^5.1.2", "safe-buffer": "^5.1.2",
"yallist": "^3.0.0" "yallist": "^3.0.0"
@@ -3802,6 +3823,7 @@
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
} }
@@ -3882,7 +3904,8 @@
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
@@ -3894,6 +3917,7 @@
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
} }
@@ -3979,7 +4003,8 @@
"safe-buffer": { "safe-buffer": {
"version": "5.1.2", "version": "5.1.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"safer-buffer": { "safer-buffer": {
"version": "2.1.2", "version": "2.1.2",
@@ -4015,6 +4040,7 @@
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",
@@ -4034,6 +4060,7 @@
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
@@ -4077,12 +4104,14 @@
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"yallist": { "yallist": {
"version": "3.0.3", "version": "3.0.3",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
} }
} }
}, },
@@ -4134,9 +4163,9 @@
} }
}, },
"glob-parent": { "glob-parent": {
"version": "5.0.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.0.0.tgz", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz",
"integrity": "sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==", "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==",
"dev": true, "dev": true,
"requires": { "requires": {
"is-glob": "^4.0.1" "is-glob": "^4.0.1"
@@ -5972,9 +6001,9 @@
} }
}, },
"rxjs": { "rxjs": {
"version": "6.5.2", "version": "6.5.3",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz",
"integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==", "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==",
"dev": true, "dev": true,
"requires": { "requires": {
"tslib": "^1.9.0" "tslib": "^1.9.0"

View File

@@ -4,8 +4,8 @@
"description": "The Javascript Wails Runtime", "description": "The Javascript Wails Runtime",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"build": "eslint core/ && npm run build:prod", "build": "./node_modules/.bin/eslint core/ && npm run build:prod",
"build:prod": "webpack --env prod --colors", "build:prod": "./node_modules/.bin/webpack --env prod --colors",
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
"repository": { "repository": {
@@ -36,7 +36,7 @@
"babel-loader": "^8.0.6", "babel-loader": "^8.0.6",
"babel-preset-minify": "^0.5.0", "babel-preset-minify": "^0.5.0",
"core-js": "^3.1.4", "core-js": "^3.1.4",
"eslint": "^6.2.2", "eslint": "^6.5.1",
"webpack": "^4.35.3", "webpack": "^4.35.3",
"webpack-cli": "^3.3.5" "webpack-cli": "^3.3.5"
} }

View File

@@ -32,6 +32,6 @@ function OpenFile(filename) {
} }
module.exports = { module.exports = {
OpenURL, OpenURL: OpenURL,
OpenFile OpenFile: OpenFile
}; };

View File

@@ -61,9 +61,9 @@ function Emit(eventName) {
* the event is acknowledged via `Event.Acknowledge`. Once this happens, `callback` is invoked ONCE * the event is acknowledged via `Event.Acknowledge`. Once this happens, `callback` is invoked ONCE
* *
* @export * @export
* @param {*} eventName * @param {string} eventName
* @param {*} timeInMilliseconds * @param {number} timeInMilliseconds
* @param {*} callback * @param {function} callback
*/ */
function Heartbeat(eventName, timeInMilliseconds, callback) { function Heartbeat(eventName, timeInMilliseconds, callback) {
window.wails.Events.Heartbeat(eventName, timeInMilliseconds, callback); window.wails.Events.Heartbeat(eventName, timeInMilliseconds, callback);
@@ -80,10 +80,10 @@ function Acknowledge(eventName) {
} }
module.exports = { module.exports = {
OnMultiple, OnMultiple: OnMultiple,
On, On: On,
Once, Once: Once,
Emit, Emit: Emit,
Heartbeat, Heartbeat: Heartbeat,
Acknowledge Acknowledge: Acknowledge
}; };

View File

@@ -18,6 +18,4 @@ function Init(callback) {
window.wails._.Init(callback); window.wails._.Init(callback);
} }
module.exports = { module.exports = Init;
Init
};

View File

@@ -62,9 +62,9 @@ function Fatal(message) {
} }
module.exports = { module.exports = {
Debug, Debug: Debug,
Info, Info: Info,
Warning, Warning: Warning,
Error, Error: Error,
Fatal Fatal: Fatal
}; };

View File

@@ -15,8 +15,8 @@ const Events = require('./events');
const Init = require('./init'); const Init = require('./init');
module.exports = { module.exports = {
Log, Log: Log,
Browser, Browser: Browser,
Events, Events: Events,
Init Init: Init
}; };

View File

@@ -1,8 +1,9 @@
{ {
"name": "@wailsapp/runtime", "name": "@wailsapp/runtime",
"version": "1.0.2", "version": "1.0.9",
"description": "Wails Javascript runtime library", "description": "Wails Javascript runtime library",
"main": "main.js", "main": "main.js",
"types": "runtime.d.ts",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
@@ -20,5 +21,8 @@
"bugs": { "bugs": {
"url": "https://github.com/wailsapp/wails/issues" "url": "https://github.com/wailsapp/wails/issues"
}, },
"homepage": "https://github.com/wailsapp/wails#readme" "homepage": "https://github.com/wailsapp/wails#readme",
} "devDependencies": {
"dts-gen": "^0.5.8"
}
}

26
runtime/js/runtime/runtime.d.ts vendored Normal file
View 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;
};
};

View File

@@ -1,6 +1,54 @@
package runtime package runtime
import "github.com/wailsapp/wails/lib/interfaces" 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 // Window exposes an interface for manipulating the window
type Window struct { type Window struct {
@@ -31,6 +79,7 @@ func (r *Window) UnFullscreen() {
// SetTitle sets the the window title // SetTitle sets the the window title
func (r *Window) SetTitle(title string) { func (r *Window) SetTitle(title string) {
title = ProcessEncoding(title)
r.renderer.SetTitle(title) r.renderer.SetTitle(title)
} }

84
scripts/build.go Normal file
View File

@@ -0,0 +1,84 @@
package main
import (
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
)
// Default target to run when none is specified
// If not set, running mage will list available targets
// var Default = Build
/*
# Build runtime
echo "**** Building Runtime ****"
cd runtime/js
npm install
npm run build
cd ../..
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! ****"
*/
func runCommand(command string, args ...string) {
cmd := exec.Command(command, args...)
output, err := cmd.CombinedOutput()
if err != nil {
log.Println(string(output))
log.Fatal(err)
}
cmd.Run()
fmt.Println(string(output))
}
// A build step that requires additional params, or platform specific steps for example
func main() {
dir, _ := os.Getwd()
// Build Runtime
fmt.Println("**** Building Runtime ****")
runtimeDir, _ := filepath.Abs(filepath.Join(dir, "..", "runtime", "js"))
os.Chdir(runtimeDir)
runCommand("npm", "install")
runCommand("npm", "run", "build")
// Pack assets
fmt.Println("**** Packing Assets ****")
rendererDir, _ := filepath.Abs(filepath.Join(dir, "..", "lib", "renderer"))
os.Chdir(rendererDir)
runCommand("mewn")
cmdDir, _ := filepath.Abs(filepath.Join(dir, "..", "cmd"))
os.Chdir(cmdDir)
runCommand("mewn")
// Install Wails
fmt.Println("**** Installing Wails locally ****")
execDir, _ := filepath.Abs(filepath.Join(dir, "..", "cmd", "wails"))
os.Chdir(execDir)
runCommand("go", "install")
baseDir, _ := filepath.Abs(filepath.Join(dir, ".."))
os.Chdir(baseDir)
runCommand("go", "mod", "tidy")
}

View File

@@ -3,11 +3,17 @@
# Build runtime # Build runtime
echo "**** Building Runtime ****" echo "**** Building Runtime ****"
cd runtime/js cd runtime/js
npm install
npm run build npm run build
cd ../.. cd ../..
echo "**** Packing Assets ****" echo "**** Packing Assets ****"
cd cmd
mewn mewn
cd ..
cd lib/renderer
mewn
cd ../..
echo "**** Installing Wails locally ****" echo "**** Installing Wails locally ****"
cd cmd/wails cd cmd/wails