mirror of
https://github.com/taigrr/wails.git
synced 2026-04-02 13:19:00 -07:00
Compare commits
66 Commits
v0.18.10-p
...
fix-runtim
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
848a9ea260 | ||
|
|
0e7981cf87 | ||
|
|
ce3bd8f56f | ||
|
|
a3cc1de0a2 | ||
|
|
8d3c32c630 | ||
|
|
7ae2acac90 | ||
|
|
7d822dfe8d | ||
|
|
c0f5c28e3b | ||
|
|
bd6745bef0 | ||
|
|
8a14cc9a4c | ||
|
|
8a7c098041 | ||
|
|
030bd629df | ||
|
|
cad65f8f3f | ||
|
|
0c790bb08c | ||
|
|
fa1bc016fe | ||
|
|
5fc41949ae | ||
|
|
3d13368043 | ||
|
|
0bca7b57e0 | ||
|
|
332e9d66ea | ||
|
|
93884a5aeb | ||
|
|
c1fbca834b | ||
|
|
60fe2c0912 | ||
|
|
2e1e8b1513 | ||
|
|
dd49292b68 | ||
|
|
af30e5e6ba | ||
|
|
558cc9681c | ||
|
|
62f6bece57 | ||
|
|
084d412d86 | ||
|
|
788d22740b | ||
|
|
34ef3de737 | ||
|
|
8149cbc3c0 | ||
|
|
2032ef8225 | ||
|
|
38e897f646 | ||
|
|
de2f9a1e9e | ||
|
|
c506c95506 | ||
|
|
955cfbb689 | ||
|
|
aa698b993d | ||
|
|
a6fa5feb0c | ||
|
|
67a52b2a57 | ||
|
|
99d22fdcb7 | ||
|
|
7051ffd425 | ||
|
|
bac823566c | ||
|
|
401ebee719 | ||
|
|
b5b92c4afa | ||
|
|
2c2aee2d30 | ||
|
|
806b1aa8e0 | ||
|
|
416bd7bfc4 | ||
|
|
aca72d3f7a | ||
|
|
ad20e2622b | ||
|
|
94c56115a5 | ||
|
|
daeda501f4 | ||
|
|
fb1e8647bc | ||
|
|
723236f348 | ||
|
|
394a823d82 | ||
|
|
afe57802ad | ||
|
|
914642bd1d | ||
|
|
dafd9bcb24 | ||
|
|
7f75f27f6b | ||
|
|
d77fa1ee74 | ||
|
|
82e00ff83a | ||
|
|
14f91ab109 | ||
|
|
19706a12a4 | ||
|
|
52e6091f0f | ||
|
|
2db1624faf | ||
|
|
d572418ec3 | ||
|
|
8c7480d277 |
32
.github/workflows/latest-pre.yml
vendored
Normal file
32
.github/workflows/latest-pre.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: latest pre-release
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '**-pre**'
|
||||
jobs:
|
||||
|
||||
build:
|
||||
name: Test Build Latest Pre-Release
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
steps:
|
||||
|
||||
- name: Set up Go 1.12
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: 1.12
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v1
|
||||
|
||||
- name: Get dependencies
|
||||
run: |
|
||||
go get -v -d ./...
|
||||
- name: Build
|
||||
run: go build -v ./cmd/wails
|
||||
|
||||
- name: Test
|
||||
run: ./wails version
|
||||
32
.github/workflows/pr.yml
vendored
Normal file
32
.github/workflows/pr.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: pr
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- develop
|
||||
jobs:
|
||||
|
||||
build:
|
||||
name: Test Build PR
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
steps:
|
||||
|
||||
- name: Set up Go 1.12
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: 1.12
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v1
|
||||
|
||||
- name: Get dependencies
|
||||
run: |
|
||||
go get -v -d ./...
|
||||
- name: Build
|
||||
run: go build -v ./cmd/wails
|
||||
|
||||
- name: Test
|
||||
run: ./wails version
|
||||
34
.github/workflows/release.yml
vendored
Normal file
34
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
name: release
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
tags:
|
||||
- '!**pre**'
|
||||
jobs:
|
||||
|
||||
build:
|
||||
name: Test Build Latest Release
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
steps:
|
||||
|
||||
- name: Set up Go 1.12
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: 1.12
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v1
|
||||
|
||||
- name: Get dependencies
|
||||
run: |
|
||||
go get -v -d ./...
|
||||
- name: Build
|
||||
run: go build -v ./cmd/wails
|
||||
|
||||
- name: Test
|
||||
run: ./wails version
|
||||
@@ -2,21 +2,24 @@
|
||||
|
||||
Wails is what it is because of the time and effort given by these great people. A huge thank you to each and every one!
|
||||
|
||||
* [Dustin Krysak](https://wiki.ubuntu.com/bashfulrobot)
|
||||
* [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)
|
||||
* [intelwalk](https://github.com/intelwalk)
|
||||
* [Mark Stenglein](https://github.com/ocelotsloth)
|
||||
* [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)
|
||||
* [Dustin Krysak](https://wiki.ubuntu.com/bashfulrobot)
|
||||
* [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)
|
||||
* [intelwalk](https://github.com/intelwalk)
|
||||
* [Mark Stenglein](https://github.com/ocelotsloth)
|
||||
* [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)
|
||||
* [Jack Mordaunt](https://github.com/JackMordaunt)
|
||||
* [Michael Hipp](https://github.com/MichaelHipp)
|
||||
* [Travis McLane](https://github.com/tmclane)
|
||||
23
README.md
23
README.md
@@ -1,5 +1,5 @@
|
||||
<p align="center" style="text-align: center">
|
||||
<img src="https://github.com/wailsapp/docs/raw/master/.vuepress/public/media/logo_cropped.png" width="40%"><br/>
|
||||
<img src="logo_cropped.png" width="40%"><br/>
|
||||
</p>
|
||||
<p align="center">
|
||||
A framework for building desktop applications using Go & Web Technologies.<br/><br/>
|
||||
@@ -11,11 +11,14 @@
|
||||
<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://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>
|
||||
<a href="https://github.com/wailsapp/wails/workflows/release/badge.svg?branch=master" rel="nofollow"><img src="https://github.com/wailsapp/wails/workflows/release/badge.svg?branch=master" alt="Release Pipelines"></a>
|
||||
<a href="https://github.com/wailsapp/wails/workflows/latest-pre/badge.svg?branch=masterr" rel="nofollow"><img src="https://github.com/wailsapp/wails/workflows/latest-pre/badge.svg?branch=master" alt="Pre-Release 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!
|
||||
|
||||
The official docs can be found at [https://wails.app](https://wails.app).
|
||||
|
||||
## Features
|
||||
|
||||
- Use standard Go libraries/frameworks for the backend
|
||||
@@ -28,9 +31,6 @@ The traditional method of providing web interfaces to Go programs is via a built
|
||||
- Powerful cli tool
|
||||
- Multiplatform
|
||||
|
||||
## Project Status
|
||||
|
||||
Wails is currently in Beta. Please make sure you read the [Project Status](https://wails.app/project_status.html) if you are interested in using this project.
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -94,7 +94,7 @@ Windows requires gcc and related tooling. The recommended download is from [http
|
||||
Installation is as simple as running the following command:
|
||||
|
||||
<pre style='color:white'>
|
||||
go get github.com/wailsapp/wails/cmd/wails
|
||||
go get -u github.com/wailsapp/wails/cmd/wails
|
||||
</pre>
|
||||
|
||||
## Next Steps
|
||||
@@ -126,8 +126,7 @@ And without [these people](CONTRIBUTORS.md), it wouldn't be what it is today. A
|
||||
|
||||
Special Mentions:
|
||||
|
||||
* [Bill Kennedy](https://twitter.com/goinggodotnet) - Go guru, encourager and all-round nice guy, whose infectious energy and inspiration powered me on when I had none left.
|
||||
* [Mark Bates](https://github.com/markbates) - Creator of [Packr](https://github.com/gobuffalo/packr), inspiration for packing strategies which fed into some of the tooling.
|
||||
* [Byron](https://github.com/bh90210) - At times, Byron has single handedly kept this project alive. Without his incredible input, we never would have got to v1.
|
||||
|
||||
This project was mainly coded to the following albums:
|
||||
|
||||
@@ -148,3 +147,11 @@ This project was mainly coded to the following albums:
|
||||
## Licensing
|
||||
|
||||
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_large)
|
||||
|
||||
## Special Thank You
|
||||
|
||||
<p align="center" style="text-align: center">
|
||||
A special thank you to JetBrains for donating licenses to us!<br/><br/>
|
||||
Please click the logo to let them know your appreciation!<br/><br/>
|
||||
<a href="https://www.jetbrains.com?from=Wails"><img src="jetbrains-grayscale.png" width="30%"></a>
|
||||
</p>
|
||||
|
||||
13
app.go
13
app.go
@@ -2,6 +2,7 @@ package wails
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
|
||||
"github.com/syossan27/tebata"
|
||||
@@ -43,7 +44,7 @@ func CreateApp(optionalConfig ...*AppConfig) *App {
|
||||
}
|
||||
|
||||
result := &App{
|
||||
logLevel: "info",
|
||||
logLevel: "debug",
|
||||
renderer: renderer.NewWebView(),
|
||||
ipc: ipc.NewManager(),
|
||||
bindingManager: binding.NewManager(),
|
||||
@@ -65,6 +66,9 @@ func CreateApp(optionalConfig ...*AppConfig) *App {
|
||||
result.config.DisableInspector = true
|
||||
}
|
||||
|
||||
// Platform specific init
|
||||
platformInit()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -93,7 +97,7 @@ func (a *App) start() error {
|
||||
|
||||
// Check if we are to run in bridge mode
|
||||
if BuildMode == cmd.BuildModeBridge {
|
||||
a.renderer = &renderer.Bridge{}
|
||||
a.renderer = renderer.NewBridge()
|
||||
}
|
||||
|
||||
// Initialise the renderer
|
||||
@@ -102,6 +106,11 @@ func (a *App) start() error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Enable console for Windows debug builds
|
||||
if runtime.GOOS == "windows" && BuildMode == cmd.BuildModeDebug {
|
||||
a.renderer.EnableConsole()
|
||||
}
|
||||
|
||||
// Start signal handler
|
||||
t := tebata.New(os.Interrupt, os.Kill, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL)
|
||||
t.Reserve(func() {
|
||||
|
||||
7
app_other.go
Normal file
7
app_other.go
Normal file
@@ -0,0 +1,7 @@
|
||||
// +build +linux +darwin !windows
|
||||
|
||||
package wails
|
||||
|
||||
func platformInit() {
|
||||
|
||||
}
|
||||
27
app_windows.go
Normal file
27
app_windows.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// +build windows !linux !darwin
|
||||
|
||||
package wails
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func platformInit() {
|
||||
err := SetProcessDPIAware()
|
||||
if err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
# 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'
|
||||
@@ -1,138 +0,0 @@
|
||||
# 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
10
cmd/fs.go
10
cmd/fs.go
@@ -132,6 +132,16 @@ func (fs *FSHelper) LocalDir(dir string) (*Dir, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
// LoadRelativeFile loads the given file relative to the caller's directory
|
||||
func (fs *FSHelper) LoadRelativeFile(relativePath string) ([]byte, error) {
|
||||
_, filename, _, _ := runtime.Caller(0)
|
||||
fullPath, err := filepath.Abs(filepath.Join(path.Dir(filename), relativePath))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ioutil.ReadFile(fullPath)
|
||||
}
|
||||
|
||||
// GetSubdirs will return a list of FQPs to subdirectories in the given directory
|
||||
func (d *Dir) GetSubdirs() (map[string]string, error) {
|
||||
|
||||
|
||||
78
cmd/gomod.go
Normal file
78
cmd/gomod.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
||||
"github.com/Masterminds/semver"
|
||||
)
|
||||
|
||||
func GetWailsVersion() (*semver.Version, error) {
|
||||
var FS = NewFSHelper()
|
||||
var result *semver.Version
|
||||
|
||||
// Load file
|
||||
var err error
|
||||
goModFile, err := filepath.Abs(filepath.Join(".", "go.mod"))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Unable to load go.mod at %s", goModFile)
|
||||
}
|
||||
goMod, err := FS.LoadAsString(goModFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Unable to load go.mod")
|
||||
}
|
||||
|
||||
// Find wails version
|
||||
versionRegexp := regexp.MustCompile(`.*github.com/wailsapp/wails.*(v\d+.\d+.\d+(?:-pre\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)
|
||||
}
|
||||
return result, nil
|
||||
|
||||
}
|
||||
|
||||
func GetCurrentVersion() (*semver.Version, error) {
|
||||
result, err := semver.NewVersion(Version)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Unable to parse Wails version: %s", Version)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func GoModOutOfSync() (bool, error) {
|
||||
gomodversion, err := GetWailsVersion()
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
currentVersion, err := GetCurrentVersion()
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
result := !currentVersion.Equal(gomodversion)
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func UpdateGoModVersion() error {
|
||||
currentVersion, err := GetCurrentVersion()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
currentVersionString := currentVersion.String()
|
||||
|
||||
requireLine := "-require=github.com/wailsapp/wails@v" + currentVersionString
|
||||
|
||||
// Issue: go mod edit -require=github.com/wailsapp/wails@1.0.2-pre5
|
||||
helper := NewProgramHelper()
|
||||
command := []string{"go", "mod", "edit", requireLine}
|
||||
return helper.RunCommandArray(command)
|
||||
|
||||
}
|
||||
161
cmd/helpers.go
161
cmd/helpers.go
@@ -7,6 +7,7 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/leaanthony/mewn"
|
||||
@@ -35,16 +36,23 @@ func ValidateFrontendConfig(projectOptions *ProjectOptions) error {
|
||||
}
|
||||
|
||||
// InstallGoDependencies will run go get in the current directory
|
||||
func InstallGoDependencies() error {
|
||||
depSpinner := spinner.New("Ensuring Dependencies are up to date...")
|
||||
depSpinner.SetSpinSpeed(50)
|
||||
depSpinner.Start()
|
||||
err := NewProgramHelper().RunCommand("go get")
|
||||
func InstallGoDependencies(verbose bool) error {
|
||||
var depSpinner *spinner.Spinner
|
||||
if !verbose {
|
||||
depSpinner = spinner.New("Ensuring Dependencies are up to date...")
|
||||
depSpinner.SetSpinSpeed(50)
|
||||
depSpinner.Start()
|
||||
}
|
||||
err := NewProgramHelper(verbose).RunCommand("go get")
|
||||
if err != nil {
|
||||
depSpinner.Error()
|
||||
if !verbose {
|
||||
depSpinner.Error()
|
||||
}
|
||||
return err
|
||||
}
|
||||
depSpinner.Success()
|
||||
if !verbose {
|
||||
depSpinner.Success()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -61,7 +69,7 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
|
||||
}
|
||||
|
||||
// Check Mewn is installed
|
||||
err := CheckMewn()
|
||||
err := CheckMewn(projectOptions.Verbose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -72,9 +80,14 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
|
||||
compileMessage += " (Debug Mode)"
|
||||
}
|
||||
|
||||
packSpinner := spinner.New(compileMessage + "...")
|
||||
packSpinner.SetSpinSpeed(50)
|
||||
packSpinner.Start()
|
||||
var packSpinner *spinner.Spinner
|
||||
if !projectOptions.Verbose {
|
||||
packSpinner = spinner.New(compileMessage + "...")
|
||||
packSpinner.SetSpinSpeed(50)
|
||||
packSpinner.Start()
|
||||
} else {
|
||||
println(compileMessage)
|
||||
}
|
||||
|
||||
buildCommand := slicer.String()
|
||||
buildCommand.Add("mewn")
|
||||
@@ -87,8 +100,18 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
|
||||
buildCommand.Add("build")
|
||||
|
||||
if binaryName != "" {
|
||||
buildCommand.Add("-o")
|
||||
buildCommand.Add(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", binaryName)
|
||||
}
|
||||
|
||||
// If we are forcing a rebuild
|
||||
@@ -103,19 +126,33 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
|
||||
}
|
||||
|
||||
// Add windows flags
|
||||
if runtime.GOOS == "windows" {
|
||||
if runtime.GOOS == "windows" && buildMode == BuildModeProd {
|
||||
ldflags += "-H windowsgui "
|
||||
}
|
||||
|
||||
ldflags += "-X github.com/wailsapp/wails.BuildMode=" + buildMode
|
||||
|
||||
// If we wish to generate typescript
|
||||
if projectOptions.typescriptDefsFilename != "" {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
filename := filepath.Join(cwd, projectOptions.FrontEnd.Dir, projectOptions.typescriptDefsFilename)
|
||||
ldflags += " -X github.com/wailsapp/wails/lib/binding.typescriptDefinitionFilename=" + filename
|
||||
}
|
||||
|
||||
buildCommand.AddSlice([]string{"-ldflags", ldflags})
|
||||
err = NewProgramHelper().RunCommandArray(buildCommand.AsSlice())
|
||||
err = NewProgramHelper(projectOptions.Verbose).RunCommandArray(buildCommand.AsSlice())
|
||||
if err != nil {
|
||||
packSpinner.Error()
|
||||
if packSpinner != nil {
|
||||
packSpinner.Error()
|
||||
}
|
||||
return err
|
||||
}
|
||||
packSpinner.Success()
|
||||
if packSpinner != nil {
|
||||
packSpinner.Success()
|
||||
}
|
||||
|
||||
// packageApp
|
||||
if packageApp {
|
||||
@@ -139,45 +176,68 @@ func PackageApplication(projectOptions *ProjectOptions) error {
|
||||
}
|
||||
message = "Generating resource bundle"
|
||||
}
|
||||
packageSpinner := spinner.New(message)
|
||||
packageSpinner.SetSpinSpeed(50)
|
||||
packageSpinner.Start()
|
||||
var packageSpinner *spinner.Spinner
|
||||
if projectOptions.Verbose {
|
||||
packageSpinner = spinner.New(message)
|
||||
packageSpinner.SetSpinSpeed(50)
|
||||
packageSpinner.Start()
|
||||
}
|
||||
err := NewPackageHelper().Package(projectOptions)
|
||||
if err != nil {
|
||||
packageSpinner.Error()
|
||||
if packageSpinner != nil {
|
||||
packageSpinner.Error()
|
||||
}
|
||||
return err
|
||||
}
|
||||
packageSpinner.Success()
|
||||
if packageSpinner != nil {
|
||||
packageSpinner.Success()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// BuildFrontend runs the given build command
|
||||
func BuildFrontend(buildCommand string) error {
|
||||
buildFESpinner := spinner.New("Building frontend...")
|
||||
buildFESpinner.SetSpinSpeed(50)
|
||||
buildFESpinner.Start()
|
||||
err := NewProgramHelper().RunCommand(buildCommand)
|
||||
func BuildFrontend(projectOptions *ProjectOptions) error {
|
||||
var buildFESpinner *spinner.Spinner
|
||||
if !projectOptions.Verbose {
|
||||
buildFESpinner = spinner.New("Building frontend...")
|
||||
buildFESpinner.SetSpinSpeed(50)
|
||||
buildFESpinner.Start()
|
||||
} else {
|
||||
println("Building frontend...")
|
||||
}
|
||||
err := NewProgramHelper(projectOptions.Verbose).RunCommand(projectOptions.FrontEnd.Build)
|
||||
if err != nil {
|
||||
buildFESpinner.Error()
|
||||
if buildFESpinner != nil {
|
||||
buildFESpinner.Error()
|
||||
}
|
||||
return err
|
||||
}
|
||||
buildFESpinner.Success()
|
||||
if buildFESpinner != nil {
|
||||
buildFESpinner.Success()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckMewn checks if mewn is installed and if not, attempts to fetch it
|
||||
func CheckMewn() (err error) {
|
||||
programHelper := NewProgramHelper()
|
||||
func CheckMewn(verbose bool) (err error) {
|
||||
programHelper := NewProgramHelper(verbose)
|
||||
if !programHelper.IsInstalled("mewn") {
|
||||
buildSpinner := spinner.New()
|
||||
buildSpinner.SetSpinSpeed(50)
|
||||
buildSpinner.Start("Installing Mewn asset packer...")
|
||||
var buildSpinner *spinner.Spinner
|
||||
if !verbose {
|
||||
buildSpinner = spinner.New()
|
||||
buildSpinner.SetSpinSpeed(50)
|
||||
buildSpinner.Start("Installing Mewn asset packer...")
|
||||
}
|
||||
err := programHelper.InstallGoPackage("github.com/leaanthony/mewn/cmd/mewn")
|
||||
if err != nil {
|
||||
buildSpinner.Error()
|
||||
if buildSpinner != nil {
|
||||
buildSpinner.Error()
|
||||
}
|
||||
return err
|
||||
}
|
||||
buildSpinner.Success()
|
||||
if buildSpinner != nil {
|
||||
buildSpinner.Success()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -204,9 +264,14 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
|
||||
}
|
||||
|
||||
// Check if frontend deps have been updated
|
||||
feSpinner := spinner.New("Ensuring frontend dependencies are up to date (This may take a while)")
|
||||
feSpinner.SetSpinSpeed(50)
|
||||
feSpinner.Start()
|
||||
var feSpinner *spinner.Spinner
|
||||
if !projectOptions.Verbose {
|
||||
feSpinner = spinner.New("Ensuring frontend dependencies are up to date (This may take a while)")
|
||||
feSpinner.SetSpinSpeed(50)
|
||||
feSpinner.Start()
|
||||
} else {
|
||||
println("Ensuring frontend dependencies are up to date (This may take a while)")
|
||||
}
|
||||
|
||||
requiresNPMInstall := true
|
||||
|
||||
@@ -238,7 +303,11 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
|
||||
if savedMD5sum == packageJSONMD5 {
|
||||
// Same - no need for reinstall
|
||||
requiresNPMInstall = false
|
||||
feSpinner.Success("Skipped frontend dependencies (-f to force rebuild)")
|
||||
if feSpinner != nil {
|
||||
feSpinner.Success("Skipped frontend dependencies (-f to force rebuild)")
|
||||
} else {
|
||||
println("Skipped frontend dependencies (-f to force rebuild)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -247,12 +316,16 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
|
||||
// Different? Build
|
||||
if requiresNPMInstall || forceRebuild {
|
||||
// Install dependencies
|
||||
err = NewProgramHelper().RunCommand(projectOptions.FrontEnd.Install)
|
||||
err = NewProgramHelper(projectOptions.Verbose).RunCommand(projectOptions.FrontEnd.Install)
|
||||
if err != nil {
|
||||
feSpinner.Error()
|
||||
if feSpinner != nil {
|
||||
feSpinner.Error()
|
||||
}
|
||||
return err
|
||||
}
|
||||
feSpinner.Success()
|
||||
if feSpinner != nil {
|
||||
feSpinner.Success()
|
||||
}
|
||||
|
||||
// Update md5sum file
|
||||
ioutil.WriteFile(md5sumFile, []byte(packageJSONMD5), 0644)
|
||||
@@ -265,7 +338,7 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
|
||||
}
|
||||
|
||||
// Build frontend
|
||||
err = BuildFrontend(projectOptions.FrontEnd.Build)
|
||||
err = BuildFrontend(projectOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
17
cmd/linux.go
17
cmd/linux.go
@@ -43,8 +43,16 @@ const (
|
||||
Kali
|
||||
// Neon distribution
|
||||
Neon
|
||||
// ArcoLinux distribution
|
||||
ArcoLinux
|
||||
// Manjaro distribution
|
||||
Manjaro
|
||||
// ManjaroARM distribution
|
||||
ManjaroARM
|
||||
// Deepin distribution
|
||||
Deepin
|
||||
// Raspbian distribution
|
||||
Raspbian
|
||||
)
|
||||
|
||||
// DistroInfo contains all the information relating to a linux distribution
|
||||
@@ -100,6 +108,7 @@ func parseOsRelease(osRelease string) *DistroInfo {
|
||||
version = strings.Trim(splitLine[1], "\"")
|
||||
}
|
||||
}
|
||||
|
||||
// Check distro name against list of distros
|
||||
switch osID {
|
||||
case "fedora":
|
||||
@@ -128,8 +137,16 @@ func parseOsRelease(osRelease string) *DistroInfo {
|
||||
result.Distribution = Kali
|
||||
case "neon":
|
||||
result.Distribution = Neon
|
||||
case "arcolinux":
|
||||
result.Distribution = ArcoLinux
|
||||
case "manjaro":
|
||||
result.Distribution = Manjaro
|
||||
case "manjaro-arm":
|
||||
result.Distribution = ManjaroARM
|
||||
case "deepin":
|
||||
result.Distribution = Deepin
|
||||
case "raspbian":
|
||||
result.Distribution = Raspbian
|
||||
default:
|
||||
result.Distribution = Unknown
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package cmd
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/leaanthony/mewn"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -79,11 +78,14 @@ func (l *LinuxDB) GetDistro(distro string) *Distribution {
|
||||
// NewLinuxDB creates a new LinuxDB instance from the bundled
|
||||
// linuxdb.yaml file.
|
||||
func NewLinuxDB() *LinuxDB {
|
||||
data := mewn.Bytes("./linuxdb.yaml")
|
||||
data, err := fs.LoadRelativeFile("./linuxdb.yaml")
|
||||
if err != nil {
|
||||
log.Fatal("Could not load linuxdb.yaml")
|
||||
}
|
||||
result := LinuxDB{
|
||||
Distributions: make(map[string]*Distribution),
|
||||
}
|
||||
err := result.ImportData(data)
|
||||
err = result.ImportData(data)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -82,6 +82,15 @@ distributions:
|
||||
gccversioncommand: *gccdumpfullversion
|
||||
programs: *debiandefaultprograms
|
||||
libraries: *debiandefaultlibraries
|
||||
deepin:
|
||||
id: deepin
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: Deepin
|
||||
gccversioncommand: *gccdumpfullversion
|
||||
programs: *debiandefaultprograms
|
||||
libraries: *debiandefaultlibraries
|
||||
void:
|
||||
id: void
|
||||
releases:
|
||||
@@ -158,6 +167,15 @@ distributions:
|
||||
help: Please install with `sudo pacman -S gtk3` and try again
|
||||
- name: webkit2gtk
|
||||
help: Please install with `sudo pacman -S webkit2gtk` and try again
|
||||
arcolinux:
|
||||
id: arcolinux
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: ArcoLinux
|
||||
gccversioncommand: *gccdumpversion
|
||||
programs: *archdefaultprograms
|
||||
libraries: *archdefaultlibraries
|
||||
manjaro:
|
||||
id: manjaro
|
||||
releases:
|
||||
@@ -167,6 +185,15 @@ distributions:
|
||||
gccversioncommand: *gccdumpversion
|
||||
programs: *archdefaultprograms
|
||||
libraries: *archdefaultlibraries
|
||||
manjaro-arm:
|
||||
id: manjaro-arm
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: Manjaro-ARM
|
||||
gccversioncommand: *gccdumpversion
|
||||
programs: *archdefaultprograms
|
||||
libraries: *archdefaultlibraries
|
||||
gentoo:
|
||||
id: gentoo
|
||||
releases:
|
||||
@@ -185,4 +212,14 @@ distributions:
|
||||
- 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
|
||||
help: Please install with `sudo emerge webkit-gtk` and try again
|
||||
|
||||
raspbian:
|
||||
id: raspbian
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: Raspbian
|
||||
gccversioncommand: *gccdumpfullversion
|
||||
programs: *debiandefaultprograms
|
||||
libraries: *debiandefaultlibraries
|
||||
|
||||
@@ -191,8 +191,15 @@ func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
|
||||
|
||||
// Build 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 {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0"><dict>
|
||||
<key>CFBundlePackageType</key><string>APPL</string>
|
||||
<key>CFBundleName</key><string>{{.Title}}</string>
|
||||
<key>CFBundleExecutable</key><string>{{.Exe}}</string>
|
||||
<key>CFBundleIdentifier</key><string>{{.PackageID}}</string>
|
||||
|
||||
@@ -3,6 +3,7 @@ package cmd
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -11,14 +12,22 @@ import (
|
||||
|
||||
// ProgramHelper - Utility functions around installed applications
|
||||
type ProgramHelper struct {
|
||||
shell *ShellHelper
|
||||
shell *ShellHelper
|
||||
verbose bool
|
||||
}
|
||||
|
||||
// NewProgramHelper - Creates a new ProgramHelper
|
||||
func NewProgramHelper() *ProgramHelper {
|
||||
return &ProgramHelper{
|
||||
func NewProgramHelper(verbose ...bool) *ProgramHelper {
|
||||
result := &ProgramHelper{
|
||||
shell: NewShellHelper(),
|
||||
}
|
||||
if len(verbose) > 0 {
|
||||
result.verbose = verbose[0]
|
||||
if result.verbose {
|
||||
result.shell.SetVerbose()
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// IsInstalled tries to determine if the given binary name is installed
|
||||
@@ -29,8 +38,9 @@ func (p *ProgramHelper) IsInstalled(programName string) bool {
|
||||
|
||||
// Program - A struct to define an installed application/binary
|
||||
type Program struct {
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
verbose bool
|
||||
}
|
||||
|
||||
// FindProgram attempts to find the given program on the system.FindProgram
|
||||
@@ -45,8 +55,9 @@ func (p *ProgramHelper) FindProgram(programName string) *Program {
|
||||
return nil
|
||||
}
|
||||
return &Program{
|
||||
Name: programName,
|
||||
Path: path,
|
||||
Name: programName,
|
||||
Path: path,
|
||||
verbose: p.verbose,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,12 +74,18 @@ func (p *Program) Run(vars ...string) (stdout, stderr string, exitCode int, err
|
||||
return "", "", 1, err
|
||||
}
|
||||
cmd := exec.Command(command, vars...)
|
||||
var stdo, stde bytes.Buffer
|
||||
cmd.Stdout = &stdo
|
||||
cmd.Stderr = &stde
|
||||
err = cmd.Run()
|
||||
stdout = string(stdo.Bytes())
|
||||
stderr = string(stde.Bytes())
|
||||
if !p.verbose {
|
||||
var stdo, stde bytes.Buffer
|
||||
cmd.Stdout = &stdo
|
||||
cmd.Stderr = &stde
|
||||
err = cmd.Run()
|
||||
stdout = string(stdo.Bytes())
|
||||
stderr = string(stde.Bytes())
|
||||
} else {
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err = cmd.Run()
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/10385551/get-exit-code-go
|
||||
if err != nil {
|
||||
@@ -128,6 +145,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)
|
||||
return err
|
||||
}
|
||||
|
||||
args = args[1:]
|
||||
var stderr string
|
||||
var stdout string
|
||||
|
||||
@@ -142,21 +142,23 @@ func (ph *ProjectHelper) NewProjectOptions() *ProjectOptions {
|
||||
|
||||
// ProjectOptions holds all the options available for a project
|
||||
type ProjectOptions struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Author *author `json:"author,omitempty"`
|
||||
Version string `json:"version"`
|
||||
OutputDirectory string `json:"-"`
|
||||
UseDefaults bool `json:"-"`
|
||||
Template string `json:"-"`
|
||||
BinaryName string `json:"binaryname"`
|
||||
FrontEnd *frontend `json:"frontend,omitempty"`
|
||||
NPMProjectName string `json:"-"`
|
||||
system *SystemHelper
|
||||
log *Logger
|
||||
templates *TemplateHelper
|
||||
selectedTemplate *TemplateDetails
|
||||
WailsVersion string
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Author *author `json:"author,omitempty"`
|
||||
Version string `json:"version"`
|
||||
OutputDirectory string `json:"-"`
|
||||
UseDefaults bool `json:"-"`
|
||||
Template string `json:"-"`
|
||||
BinaryName string `json:"binaryname"`
|
||||
FrontEnd *frontend `json:"frontend,omitempty"`
|
||||
NPMProjectName string `json:"-"`
|
||||
system *SystemHelper
|
||||
log *Logger
|
||||
templates *TemplateHelper
|
||||
selectedTemplate *TemplateDetails
|
||||
WailsVersion string
|
||||
typescriptDefsFilename string
|
||||
Verbose bool `json:"-"`
|
||||
}
|
||||
|
||||
// Defaults sets the default project template
|
||||
@@ -165,6 +167,11 @@ func (po *ProjectOptions) Defaults() {
|
||||
po.WailsVersion = Version
|
||||
}
|
||||
|
||||
// SetTypescriptDefsFilename indicates that we want to generate typescript bindings to the given file
|
||||
func (po *ProjectOptions) SetTypescriptDefsFilename(filename string) {
|
||||
po.typescriptDefsFilename = filename
|
||||
}
|
||||
|
||||
// GetNPMBinaryName returns the type of package manager used by the project
|
||||
func (po *ProjectOptions) GetNPMBinaryName() (PackageManager, error) {
|
||||
if po.FrontEnd == nil {
|
||||
|
||||
42
cmd/shell.go
42
cmd/shell.go
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
// ShellHelper helps with Shell commands
|
||||
type ShellHelper struct {
|
||||
verbose bool
|
||||
}
|
||||
|
||||
// NewShellHelper creates a new ShellHelper!
|
||||
@@ -15,16 +16,27 @@ func NewShellHelper() *ShellHelper {
|
||||
return &ShellHelper{}
|
||||
}
|
||||
|
||||
// SetVerbose sets the verbose flag
|
||||
func (sh *ShellHelper) SetVerbose() {
|
||||
sh.verbose = true
|
||||
}
|
||||
|
||||
// Run the given command
|
||||
func (sh *ShellHelper) Run(command string, vars ...string) (stdout, stderr string, err error) {
|
||||
cmd := exec.Command(command, vars...)
|
||||
cmd.Env = append(os.Environ(), "GO111MODULE=on")
|
||||
var stdo, stde bytes.Buffer
|
||||
cmd.Stdout = &stdo
|
||||
cmd.Stderr = &stde
|
||||
err = cmd.Run()
|
||||
stdout = string(stdo.Bytes())
|
||||
stderr = string(stde.Bytes())
|
||||
if !sh.verbose {
|
||||
var stdo, stde bytes.Buffer
|
||||
cmd.Stdout = &stdo
|
||||
cmd.Stderr = &stde
|
||||
err = cmd.Run()
|
||||
stdout = string(stdo.Bytes())
|
||||
stderr = string(stde.Bytes())
|
||||
} else {
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err = cmd.Run()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -33,11 +45,17 @@ func (sh *ShellHelper) RunInDirectory(dir string, command string, vars ...string
|
||||
cmd := exec.Command(command, vars...)
|
||||
cmd.Dir = dir
|
||||
cmd.Env = append(os.Environ(), "GO111MODULE=on")
|
||||
var stdo, stde bytes.Buffer
|
||||
cmd.Stdout = &stdo
|
||||
cmd.Stderr = &stde
|
||||
err = cmd.Run()
|
||||
stdout = string(stdo.Bytes())
|
||||
stderr = string(stde.Bytes())
|
||||
if !sh.verbose {
|
||||
var stdo, stde bytes.Buffer
|
||||
cmd.Stdout = &stdo
|
||||
cmd.Stderr = &stde
|
||||
err = cmd.Run()
|
||||
stdout = string(stdo.Bytes())
|
||||
stderr = string(stde.Bytes())
|
||||
} else {
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err = cmd.Run()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -274,9 +274,9 @@ func CheckDependencies(logger *Logger) (bool, error) {
|
||||
distroInfo := GetLinuxDistroInfo()
|
||||
|
||||
switch distroInfo.Distribution {
|
||||
case Ubuntu, Debian, Zorin, Parrot, Linuxmint, Elementary, Kali, Neon:
|
||||
case Ubuntu, Debian, Zorin, Parrot, Linuxmint, Elementary, Kali, Neon, Deepin, Raspbian:
|
||||
libraryChecker = DpkgInstalled
|
||||
case Arch, Manjaro:
|
||||
case Arch, ArcoLinux, Manjaro, ManjaroARM:
|
||||
libraryChecker = PacmanInstalled
|
||||
case CentOS, Fedora:
|
||||
libraryChecker = RpmInstalled
|
||||
|
||||
@@ -9,4 +9,4 @@
|
||||
last 2 versions
|
||||
Firefox ESR
|
||||
not dead
|
||||
not IE 9-11 # For IE 9-11 support, remove 'not'.
|
||||
IE 9-11 # For IE 9-11 support, remove 'not'.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"ng": "npx ng",
|
||||
"start": "npx ng serve --poll=2000",
|
||||
"start": "npx ng serve --poll=2000 --host=0.0.0.0",
|
||||
"build": "npx ng build --single-bundle true --output-hashing none --prod --bundle-styles false",
|
||||
"test": "npx ng test",
|
||||
"lint": "npx ng lint",
|
||||
@@ -22,6 +22,7 @@
|
||||
"@angular/platform-browser-dynamic": "~8.0.1",
|
||||
"@angular/router": "~8.0.1",
|
||||
"@wailsapp/runtime": "^1.0.0",
|
||||
"core-js": "^3.4.4",
|
||||
"ngx-build-plus": "^8.0.3",
|
||||
"rxjs": "~6.4.0",
|
||||
"tslib": "^1.9.0",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'core-js/stable';
|
||||
import { enableProdMode } from '@angular/core';
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -11,7 +11,7 @@
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"importHelpers": true,
|
||||
"target": "es2015",
|
||||
"target": "es5",
|
||||
"typeRoots": [
|
||||
"node_modules/@types"
|
||||
],
|
||||
@@ -20,4 +20,4 @@
|
||||
"dom"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ func basic() string {
|
||||
|
||||
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")
|
||||
|
||||
app := wails.CreateApp(&wails.AppConfig{
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"core-js": "^3.1.4",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6",
|
||||
"core-js": "^3.6.4",
|
||||
"react": "^16.13.0",
|
||||
"react-dom": "^16.13.0",
|
||||
"wails-react-scripts": "3.0.1-2",
|
||||
"react-modal": "3.8.1",
|
||||
"@wailsapp/runtime": "^1.0.0"
|
||||
"react-modal": "3.11.2",
|
||||
"@wailsapp/runtime": "^1.0.10"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
'@vue/app'
|
||||
[ '@vue/app', { useBuiltIns: 'entry' } ]
|
||||
]
|
||||
}
|
||||
|
||||
@@ -8,20 +8,21 @@
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^2.6.4",
|
||||
"vue": "^2.5.22",
|
||||
"@wailsapp/runtime": "^1.0.0"
|
||||
"core-js": "^3.6.4",
|
||||
"regenerator-runtime": "^0.13.3",
|
||||
"vue": "^2.6.11",
|
||||
"@wailsapp/runtime": "^1.0.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "^3.4.0",
|
||||
"@vue/cli-plugin-eslint": "^3.4.0",
|
||||
"@vue/cli-service": "^3.4.0",
|
||||
"babel-eslint": "^10.0.1",
|
||||
"eslint": "^5.8.0",
|
||||
"eslint-plugin-vue": "^5.0.0",
|
||||
"@vue/cli-plugin-babel": "^4.2.3",
|
||||
"@vue/cli-plugin-eslint": "^4.2.3",
|
||||
"@vue/cli-service": "^4.2.3",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-plugin-vue": "^6.2.1",
|
||||
"eventsource-polyfill": "^0.9.6",
|
||||
"vue-template-compiler": "^2.5.21",
|
||||
"webpack-hot-middleware": "^2.24.3"
|
||||
"vue-template-compiler": "^2.6.11",
|
||||
"webpack-hot-middleware": "^2.25.0"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'core-js/stable';
|
||||
import 'regenerator-runtime/runtime';
|
||||
import Vue from 'vue';
|
||||
import App from './App.vue';
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
devServer: {
|
||||
disableHostCheck: true,
|
||||
host: "localhost"
|
||||
disableHostCheck: true
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
'@vue/app'
|
||||
[ '@vue/app', { useBuiltIns: 'entry' } ]
|
||||
]
|
||||
}
|
||||
|
||||
@@ -7,24 +7,24 @@
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"core-js": "^2.6.4",
|
||||
"dependencies": {
|
||||
"core-js": "^3.6.4",
|
||||
"regenerator-runtime": "^0.13.3",
|
||||
"material-design-icons-iconfont": "^5.0.1",
|
||||
"vue": "^2.5.22",
|
||||
"vuetify": "^1.5.14",
|
||||
"@wailsapp/runtime": "^1.0.0"
|
||||
"@wailsapp/runtime": "^1.0.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "^3.4.0",
|
||||
"@vue/cli-plugin-eslint": "^3.4.0",
|
||||
"@vue/cli-service": "^3.4.0",
|
||||
"babel-eslint": "^10.0.1",
|
||||
"eslint": "^5.8.0",
|
||||
"eslint-plugin-vue": "^5.0.0",
|
||||
"@vue/cli-plugin-babel": "^4.2.3",
|
||||
"@vue/cli-plugin-eslint": "^4.2.3",
|
||||
"@vue/cli-service": "^4.2.3",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-plugin-vue": "^6.2.1",
|
||||
"eventsource-polyfill": "^0.9.6",
|
||||
"vue-template-compiler": "^2.5.21",
|
||||
"webpack-hot-middleware": "^2.24.3"
|
||||
"vue-template-compiler": "^2.6.11",
|
||||
"webpack-hot-middleware": "^2.25.0"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
@@ -50,4 +50,4 @@
|
||||
"last 2 versions",
|
||||
"not ie <= 8"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'babel-polyfill';
|
||||
import 'core-js/stable';
|
||||
import 'regenerator-runtime/runtime';
|
||||
import Vue from 'vue';
|
||||
|
||||
// Setup Vuetify
|
||||
|
||||
@@ -37,7 +37,6 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
devServer: {
|
||||
disableHostCheck: true,
|
||||
host: "localhost"
|
||||
disableHostCheck: true
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "Vuetify Basic",
|
||||
"name": "Vuetify1.5/Webpack Basic",
|
||||
"version": "1.0.0",
|
||||
"shortdescription": "Vuetify + Webpack",
|
||||
"description": "Basic template using Vuetify and bundled using Webpack",
|
||||
"shortdescription": "A basic Vuetify1.5/Webpack4 template",
|
||||
"description": "Basic template using Vuetify v1.5 and bundled using Webpack",
|
||||
"install": "npm install",
|
||||
"build": "npm run build",
|
||||
"author": "lea <lea.anthony@gmail.com>",
|
||||
@@ -11,4 +11,4 @@
|
||||
"serve": "npm run serve",
|
||||
"bridge": "src",
|
||||
"wailsdir": ""
|
||||
}
|
||||
}
|
||||
|
||||
3
cmd/templates/vuetify2-basic/.jshint
Normal file
3
cmd/templates/vuetify2-basic/.jshint
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"esversion": 6
|
||||
}
|
||||
21
cmd/templates/vuetify2-basic/frontend/.gitignore
vendored
Normal file
21
cmd/templates/vuetify2-basic/frontend/.gitignore
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw*
|
||||
5
cmd/templates/vuetify2-basic/frontend/babel.config.js
Normal file
5
cmd/templates/vuetify2-basic/frontend/babel.config.js
Normal file
@@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
[ '@vue/app', { useBuiltIns: 'entry' } ]
|
||||
]
|
||||
};
|
||||
53
cmd/templates/vuetify2-basic/frontend/package.json.template
Normal file
53
cmd/templates/vuetify2-basic/frontend/package.json.template
Normal file
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"name": "{{.NPMProjectName}}",
|
||||
"author": "{{.Author.Name}}<{{.Author.Email}}>",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^3.6.4",
|
||||
"regenerator-runtime": "^0.13.3",
|
||||
"vue": "^2.6.11",
|
||||
"vuetify": "^2.2.15",
|
||||
"@wailsapp/runtime": "^1.0.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@mdi/font": "^4.9.95",
|
||||
"@vue/cli-plugin-babel": "^4.2.3",
|
||||
"@vue/cli-plugin-eslint": "^4.2.3",
|
||||
"@vue/cli-service": "^4.2.3",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-plugin-vue": "^6.2.1",
|
||||
"eventsource-polyfill": "^0.9.6",
|
||||
"vue-template-compiler": "^2.6.11",
|
||||
"webpack-hot-middleware": "^2.25.0"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"plugin:vue/essential",
|
||||
"eslint:recommended"
|
||||
],
|
||||
"rules": {},
|
||||
"parserOptions": {
|
||||
"parser": "babel-eslint"
|
||||
}
|
||||
},
|
||||
"postcss": {
|
||||
"plugins": {
|
||||
"autoprefixer": {}
|
||||
}
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions",
|
||||
"not ie <= 8"
|
||||
]
|
||||
}
|
||||
60
cmd/templates/vuetify2-basic/frontend/src/App.vue
Normal file
60
cmd/templates/vuetify2-basic/frontend/src/App.vue
Normal file
@@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<v-app id="inspire">
|
||||
<v-navigation-drawer v-model="drawer" clipped fixed app>
|
||||
<v-list dense>
|
||||
<v-list-item>
|
||||
<v-list-item-icon>
|
||||
<v-icon>mdi-view-dashboard</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>Dashboard</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
<v-list-item>
|
||||
<v-list-item-icon>
|
||||
<v-icon>mdi-settings</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>Settings</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-navigation-drawer>
|
||||
<v-app-bar app fixed clipped-left>
|
||||
<v-app-bar-nav-icon @click.stop="drawer = !drawer"></v-app-bar-nav-icon>
|
||||
<v-toolbar-title>Application</v-toolbar-title>
|
||||
</v-app-bar>
|
||||
<v-content>
|
||||
<v-container fluid class="px-0">
|
||||
<v-layout justify-center align-center class="px-0">
|
||||
<hello-world></hello-world>
|
||||
</v-layout>
|
||||
</v-container>
|
||||
</v-content>
|
||||
<v-footer app fixed>
|
||||
<span style="margin-left:1em">© You</span>
|
||||
</v-footer>
|
||||
</v-app>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HelloWorld from "./components/HelloWorld.vue"
|
||||
|
||||
export default {
|
||||
data: () => ({
|
||||
drawer: false
|
||||
}),
|
||||
components: {
|
||||
HelloWorld
|
||||
},
|
||||
props: {
|
||||
source: String
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.logo {
|
||||
width: 16em;
|
||||
}
|
||||
</style>
|
||||
BIN
cmd/templates/vuetify2-basic/frontend/src/assets/images/logo.png
Normal file
BIN
cmd/templates/vuetify2-basic/frontend/src/assets/images/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 301 KiB |
@@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<v-container fluid class="px-0">
|
||||
<v-layout>
|
||||
<v-flex xs12 sm6 offset-sm3>
|
||||
<v-card raised="raised" class="pa-4 ma-4">
|
||||
<v-layout justify-center align-center class="pa-4 ma-4">
|
||||
<v-img :src="require('../assets/images/logo.png')"></v-img>
|
||||
</v-layout>
|
||||
<v-card-actions>
|
||||
<v-layout justify-center align-center class="px-0">
|
||||
<v-btn color="blue" @click="getMessage">Press Me</v-btn>
|
||||
</v-layout>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
<div class="text-xs-center">
|
||||
<v-dialog v-model="dialog" width="500">
|
||||
<v-card>
|
||||
<v-card-title class="headline" primary-title>Message from Go</v-card-title>
|
||||
<v-card-text>{{message}}</v-card-text>
|
||||
<v-divider></v-divider>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn color="primary" text @click="dialog = false">Awesome</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</div>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
message: " ",
|
||||
raised: true,
|
||||
dialog: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getMessage: function () {
|
||||
var self = this
|
||||
window.backend.basic().then(result => {
|
||||
self.message = result
|
||||
self.dialog = true
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
h1 {
|
||||
margin-top: 2em;
|
||||
position: relative;
|
||||
min-height: 5rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
font-size: 1.7em;
|
||||
border-color: blue;
|
||||
background-color: blue;
|
||||
color: white;
|
||||
border: 3px solid white;
|
||||
border-radius: 10px;
|
||||
padding: 9px;
|
||||
cursor: pointer;
|
||||
transition: 500ms;
|
||||
}
|
||||
|
||||
a {
|
||||
font-size: 1.7em;
|
||||
border-color: white;
|
||||
background-color: #121212;
|
||||
color: white;
|
||||
border: 3px solid white;
|
||||
border-radius: 10px;
|
||||
padding: 9px;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
29
cmd/templates/vuetify2-basic/frontend/src/main.js
Normal file
29
cmd/templates/vuetify2-basic/frontend/src/main.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import 'core-js/stable';
|
||||
import 'regenerator-runtime/runtime';
|
||||
import '@mdi/font/css/materialdesignicons.css';
|
||||
import Vue from 'vue';
|
||||
import Vuetify from 'vuetify';
|
||||
import 'vuetify/dist/vuetify.min.css';
|
||||
|
||||
Vue.use(Vuetify);
|
||||
|
||||
import App from './App.vue';
|
||||
|
||||
Vue.config.productionTip = false;
|
||||
Vue.config.devtools = true;
|
||||
|
||||
import Wails from '@wailsapp/runtime';
|
||||
|
||||
Wails.Init(() => {
|
||||
new Vue({
|
||||
vuetify: new Vuetify({
|
||||
icons: {
|
||||
iconfont: 'mdi'
|
||||
},
|
||||
theme: {
|
||||
dark: true
|
||||
}
|
||||
}),
|
||||
render: h => h(App)
|
||||
}).$mount('#app');
|
||||
});
|
||||
42
cmd/templates/vuetify2-basic/frontend/vue.config.js
Normal file
42
cmd/templates/vuetify2-basic/frontend/vue.config.js
Normal file
@@ -0,0 +1,42 @@
|
||||
let cssConfig = {};
|
||||
|
||||
if (process.env.NODE_ENV == 'production') {
|
||||
cssConfig = {
|
||||
extract: {
|
||||
filename: '[name].css',
|
||||
chunkFilename: '[name].css'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
chainWebpack: config => {
|
||||
let limit = 9999999999999999;
|
||||
config.module
|
||||
.rule('images')
|
||||
.test(/\.(png|gif|jpg)(\?.*)?$/i)
|
||||
.use('url-loader')
|
||||
.loader('url-loader')
|
||||
.tap(options => Object.assign(options, { limit: limit }));
|
||||
config.module
|
||||
.rule('fonts')
|
||||
.test(/\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/i)
|
||||
.use('url-loader')
|
||||
.loader('url-loader')
|
||||
.options({
|
||||
limit: limit
|
||||
});
|
||||
},
|
||||
css: cssConfig,
|
||||
configureWebpack: {
|
||||
output: {
|
||||
filename: '[name].js'
|
||||
},
|
||||
optimization: {
|
||||
splitChunks: false
|
||||
}
|
||||
},
|
||||
devServer: {
|
||||
disableHostCheck: true
|
||||
}
|
||||
};
|
||||
5
cmd/templates/vuetify2-basic/go.mod.template
Normal file
5
cmd/templates/vuetify2-basic/go.mod.template
Normal file
@@ -0,0 +1,5 @@
|
||||
module {{.BinaryName}}
|
||||
|
||||
require (
|
||||
github.com/wailsapp/wails {{.WailsVersion}}
|
||||
)
|
||||
27
cmd/templates/vuetify2-basic/main.go.template
Normal file
27
cmd/templates/vuetify2-basic/main.go.template
Normal file
@@ -0,0 +1,27 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/leaanthony/mewn"
|
||||
"github.com/wailsapp/wails"
|
||||
)
|
||||
|
||||
func basic() string {
|
||||
return "Hello World!"
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
js := mewn.String("./frontend/dist/app.js")
|
||||
css := mewn.String("./frontend/dist/app.css")
|
||||
|
||||
app := wails.CreateApp(&wails.AppConfig{
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
Title: "{{.Name}}",
|
||||
JS: js,
|
||||
CSS: css,
|
||||
Colour: "#131313",
|
||||
})
|
||||
app.Bind(basic)
|
||||
app.Run()
|
||||
}
|
||||
14
cmd/templates/vuetify2-basic/template.json
Executable file
14
cmd/templates/vuetify2-basic/template.json
Executable file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "Vuetify2/Webpack Basic",
|
||||
"version": "1.0.0",
|
||||
"shortdescription": "A basic Vuetify2/Webpack4 template",
|
||||
"description": "Basic template using Vuetify v2 and bundled using Webpack",
|
||||
"install": "npm install",
|
||||
"build": "npm run build",
|
||||
"author": "Michael Hipp <michael@redmule.com>",
|
||||
"created": "2019-09-06",
|
||||
"frontenddir": "frontend",
|
||||
"serve": "npm run serve",
|
||||
"bridge": "src",
|
||||
"wailsdir": ""
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package cmd
|
||||
|
||||
// Version - Wails version
|
||||
const Version = "v0.18.10-pre"
|
||||
const Version = "v1.0.3-pre2"
|
||||
|
||||
@@ -40,7 +40,7 @@ Create your first project by running 'wails init'.`
|
||||
}
|
||||
|
||||
// Check Mewn
|
||||
err = cmd.CheckMewn()
|
||||
err = cmd.CheckMewn(false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/Masterminds/semver"
|
||||
@@ -183,35 +182,13 @@ func checkProjectDirectory() error {
|
||||
|
||||
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"))
|
||||
result, err := cmd.GetWailsVersion()
|
||||
|
||||
if err != nil {
|
||||
checkSpinner.Error()
|
||||
return nil, fmt.Errorf("Unable to load go.mod at %s", goModFile)
|
||||
checkSpinner.Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@ func init() {
|
||||
var packageApp = false
|
||||
var forceRebuild = false
|
||||
var debugMode = false
|
||||
var typescriptFilename = ""
|
||||
var verbose = false
|
||||
|
||||
buildSpinner := spinner.NewSpinner()
|
||||
buildSpinner.SetSpinSpeed(50)
|
||||
|
||||
@@ -21,7 +24,9 @@ func init() {
|
||||
LongDescription(commandDescription).
|
||||
BoolFlag("p", "Package application on successful build", &packageApp).
|
||||
BoolFlag("f", "Force rebuild of application components", &forceRebuild).
|
||||
BoolFlag("d", "Build in Debug mode", &debugMode)
|
||||
BoolFlag("d", "Build in Debug mode", &debugMode).
|
||||
BoolFlag("verbose", "Verbose output", &verbose).
|
||||
StringFlag("t", "Generate Typescript definitions to given file (at runtime)", &typescriptFilename)
|
||||
|
||||
initCmd.Action(func() error {
|
||||
|
||||
@@ -37,6 +42,7 @@ func init() {
|
||||
|
||||
// Project options
|
||||
projectOptions := &cmd.ProjectOptions{}
|
||||
projectOptions.Verbose = verbose
|
||||
|
||||
// Check we are in project directory
|
||||
// Check project.json loads correctly
|
||||
@@ -73,16 +79,13 @@ func init() {
|
||||
return err
|
||||
}
|
||||
|
||||
// Ensure that runtime init.js is the production version
|
||||
err = cmd.InstallProdRuntime(projectDir, projectOptions)
|
||||
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 {
|
||||
@@ -90,7 +93,7 @@ func init() {
|
||||
}
|
||||
|
||||
// Install dependencies
|
||||
err = cmd.InstallGoDependencies()
|
||||
err = cmd.InstallGoDependencies(projectOptions.Verbose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -101,6 +104,32 @@ func init() {
|
||||
buildMode = cmd.BuildModeDebug
|
||||
}
|
||||
|
||||
// Save if we wish to dump typescript or not
|
||||
if typescriptFilename != "" {
|
||||
projectOptions.SetTypescriptDefsFilename(typescriptFilename)
|
||||
}
|
||||
|
||||
// Update go.mod if it is out of sync with current version
|
||||
outofsync, err := cmd.GoModOutOfSync()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
gomodVersion, err := cmd.GetWailsVersion()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if outofsync {
|
||||
syncMessage := fmt.Sprintf("Updating go.mod (Wails version %s => %s)", gomodVersion, cmd.Version)
|
||||
buildSpinner := spinner.NewSpinner(syncMessage)
|
||||
buildSpinner.Start()
|
||||
err := cmd.UpdateGoModVersion()
|
||||
if err != nil {
|
||||
buildSpinner.Error(err.Error())
|
||||
return err
|
||||
}
|
||||
buildSpinner.Success()
|
||||
}
|
||||
|
||||
err = cmd.BuildApplication(projectOptions.BinaryName, forceRebuild, buildMode, packageApp, projectOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -10,12 +10,14 @@ import (
|
||||
func init() {
|
||||
|
||||
var forceRebuild = false
|
||||
var verbose = false
|
||||
buildSpinner := spinner.NewSpinner()
|
||||
buildSpinner.SetSpinSpeed(50)
|
||||
|
||||
commandDescription := `This command builds then serves your application in bridge mode. Useful for developing your app in a browser.`
|
||||
initCmd := app.Command("serve", "Run your Wails project in bridge mode").
|
||||
LongDescription(commandDescription).
|
||||
BoolFlag("verbose", "Verbose output", &verbose).
|
||||
BoolFlag("f", "Force rebuild of application components", &forceRebuild)
|
||||
|
||||
initCmd.Action(func() error {
|
||||
@@ -25,13 +27,14 @@ func init() {
|
||||
fmt.Println()
|
||||
|
||||
// Check Mewn is installed
|
||||
err := cmd.CheckMewn()
|
||||
err := cmd.CheckMewn(verbose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Project options
|
||||
projectOptions := &cmd.ProjectOptions{}
|
||||
projectOptions.Verbose = verbose
|
||||
|
||||
// Check we are in project directory
|
||||
// Check project.json loads correctly
|
||||
@@ -51,7 +54,7 @@ func init() {
|
||||
}
|
||||
|
||||
// Install dependencies
|
||||
err = cmd.InstallGoDependencies()
|
||||
err = cmd.InstallGoDependencies(projectOptions.Verbose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -80,15 +80,16 @@ To help you in this process, we will ask for some information, add Go/Wails deta
|
||||
npm := program.FindProgram("npm")
|
||||
if npm != nil {
|
||||
stdout, _, _, _ := npm.Run("--version")
|
||||
nodeVersion = stdout
|
||||
nodeVersion = nodeVersion[:len(nodeVersion)-1]
|
||||
npmVersion = stdout
|
||||
npmVersion = npmVersion[:len(npmVersion)-1]
|
||||
npmVersion = strings.TrimSpace(npmVersion)
|
||||
}
|
||||
|
||||
node := program.FindProgram("node")
|
||||
if node != nil {
|
||||
stdout, _, _, _ := node.Run("--version")
|
||||
npmVersion = stdout
|
||||
npmVersion = npmVersion[:len(npmVersion)-1]
|
||||
nodeVersion = stdout
|
||||
nodeVersion = nodeVersion[:len(nodeVersion)-1]
|
||||
}
|
||||
|
||||
str.WriteString("\n| Name | Value |\n| ----- | ----- |\n")
|
||||
|
||||
1
cmd/windres.bat
Normal file
1
cmd/windres.bat
Normal file
@@ -0,0 +1 @@
|
||||
windres.exe -o %1 %2
|
||||
9
go.mod
9
go.mod
@@ -3,9 +3,6 @@ module github.com/wailsapp/wails
|
||||
require (
|
||||
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
|
||||
github.com/fatih/color v1.7.0
|
||||
github.com/go-playground/colors v1.2.0
|
||||
github.com/gorilla/websocket v1.4.0
|
||||
@@ -13,7 +10,7 @@ require (
|
||||
github.com/kennygrant/sanitize v1.2.4
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
|
||||
github.com/leaanthony/mewn v0.10.7
|
||||
github.com/leaanthony/slicer v1.3.2
|
||||
github.com/leaanthony/slicer v1.4.0
|
||||
github.com/leaanthony/spinner v0.5.3
|
||||
github.com/mattn/go-colorable v0.1.1 // indirect
|
||||
github.com/mattn/go-isatty v0.0.7 // indirect
|
||||
@@ -30,4 +27,6 @@ require (
|
||||
golang.org/x/text v0.3.0
|
||||
gopkg.in/AlecAivazis/survey.v1 v1.8.4
|
||||
gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22
|
||||
)
|
||||
)
|
||||
|
||||
go 1.12
|
||||
|
||||
10
go.sum
10
go.sum
@@ -7,12 +7,6 @@ github.com/abadojack/whatlanggo v1.0.1/go.mod h1:66WiQbSbJBIlOZMsvbKe5m6pzQovxCH
|
||||
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=
|
||||
github.com/dchest/cssmin v0.0.0-20151210170030-fb8d9b44afdc h1:VBS1z48BFEe00G81z8MKOtwX7f/ISkuH38NscT8iVPw=
|
||||
github.com/dchest/cssmin v0.0.0-20151210170030-fb8d9b44afdc/go.mod h1:ABJPuor7YlcsHmvJ1QxX38e2NcufLY3hm0yXv+cy9sI=
|
||||
github.com/dchest/htmlmin v0.0.0-20150526090704-e254725e81ac h1:DpMwFluHWoZpV9ex5XjkWO4HyCz5HLVI8XbHw0FhHi4=
|
||||
github.com/dchest/htmlmin v0.0.0-20150526090704-e254725e81ac/go.mod h1:XsAE+b4rOZc8gvgsgF+wU75mNBvBcyED1wdd9PBLlJ0=
|
||||
github.com/dchest/jsmin v0.0.0-20160823214000-faeced883947 h1:Fm10/KNuoAyBm2P5P5H91Xy21hGcZnBdjR+cMdytv1M=
|
||||
github.com/dchest/jsmin v0.0.0-20160823214000-faeced883947/go.mod h1:Dv9D0NUlAsaQcGQZa5kc5mqR9ua72SmA8VXi4cd+cBw=
|
||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/go-playground/colors v1.2.0 h1:0EdjTXKrr2g1L/LQTYtIqabeHpZuGZz1U4osS1T8+5M=
|
||||
@@ -34,8 +28,8 @@ github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/leaanthony/mewn v0.10.7 h1:jCcNJyIUOpwj+I5SuATvCugDjHkoo+j6ubEOxxrxmPA=
|
||||
github.com/leaanthony/mewn v0.10.7/go.mod h1:CRkTx8unLiSSilu/Sd7i1LwrdaAL+3eQ3ses99qGMEQ=
|
||||
github.com/leaanthony/slicer v1.3.2 h1:kGWWFoyaY5WzwGrUsHXMmGbssuYthP4qYBNlkNpNAB8=
|
||||
github.com/leaanthony/slicer v1.3.2/go.mod h1:VMB/HGvr3uR3MRpFWHWAm0w+DHQLzPHYe2pKfpFlQIQ=
|
||||
github.com/leaanthony/slicer v1.4.0 h1:Q9u4w+UBU4WHjXnEDdz+eRLMKF/rnyosRBiqULnc1J8=
|
||||
github.com/leaanthony/slicer v1.4.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
|
||||
github.com/leaanthony/spinner v0.5.3 h1:IMTvgdQCec5QA4qRy0wil4XsRP+QcG1OwLWVK/LPZ5Y=
|
||||
github.com/leaanthony/spinner v0.5.3/go.mod h1:oHlrvWicr++CVV7ALWYi+qHk/XNA91D9IJ48IqmpVUo=
|
||||
github.com/leaanthony/synx v0.1.0 h1:R0lmg2w6VMb8XcotOwAe5DLyzwjLrskNkwU7LLWsyL8=
|
||||
|
||||
BIN
jetbrains-grayscale.png
Normal file
BIN
jetbrains-grayscale.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 103 KiB |
@@ -2,7 +2,11 @@ package binding
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/wailsapp/wails/lib/interfaces"
|
||||
@@ -10,6 +14,8 @@ import (
|
||||
"github.com/wailsapp/wails/lib/messages"
|
||||
)
|
||||
|
||||
var typescriptDefinitionFilename = ""
|
||||
|
||||
// Manager handles method binding
|
||||
type Manager struct {
|
||||
methods map[string]*boundMethod
|
||||
@@ -21,16 +27,19 @@ type Manager struct {
|
||||
renderer interfaces.Renderer
|
||||
runtime interfaces.Runtime // The runtime object to pass to bound structs
|
||||
objectsToBind []interface{}
|
||||
bindPackageNames bool // Package name should be considered when binding
|
||||
bindPackageNames bool // Package name should be considered when binding
|
||||
structList map[string][]string // structList["mystruct"] = []string{"Method1", "Method2"}
|
||||
}
|
||||
|
||||
// NewManager creates a new Manager struct
|
||||
func NewManager() interfaces.BindingManager {
|
||||
|
||||
result := &Manager{
|
||||
methods: make(map[string]*boundMethod),
|
||||
functions: make(map[string]*boundFunction),
|
||||
log: logger.NewCustomLogger("Bind"),
|
||||
internalMethods: newInternalMethods(),
|
||||
structList: make(map[string][]string),
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -88,9 +97,55 @@ func (b *Manager) initialise() error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// If we wish to generate a typescript definition file...
|
||||
if typescriptDefinitionFilename != "" {
|
||||
err := b.generateTypescriptDefinitions()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Generate typescript
|
||||
func (b *Manager) generateTypescriptDefinitions() error {
|
||||
|
||||
var output strings.Builder
|
||||
|
||||
for structname, methodList := range b.structList {
|
||||
structname = strings.SplitN(structname, ".", 2)[1]
|
||||
output.WriteString(fmt.Sprintf("Interface %s {\n", structname))
|
||||
for _, method := range methodList {
|
||||
output.WriteString(fmt.Sprintf("\t%s: (...args : any[]) => Promise\n", method))
|
||||
}
|
||||
output.WriteString("}\n")
|
||||
}
|
||||
|
||||
output.WriteString("\n")
|
||||
output.WriteString("Interface Backend {\n")
|
||||
|
||||
for structname := range b.structList {
|
||||
structname = strings.SplitN(structname, ".", 2)[1]
|
||||
output.WriteString(fmt.Sprintf("\t%[1]s: %[1]s\n", structname))
|
||||
}
|
||||
output.WriteString("}\n")
|
||||
|
||||
globals := `
|
||||
declare global {
|
||||
interface Window {
|
||||
backend: Backend;
|
||||
}
|
||||
}`
|
||||
output.WriteString(globals)
|
||||
|
||||
b.log.Info("Written Typescript file: " + typescriptDefinitionFilename)
|
||||
|
||||
dir := filepath.Dir(typescriptDefinitionFilename)
|
||||
os.MkdirAll(dir, 0755)
|
||||
return ioutil.WriteFile(typescriptDefinitionFilename, []byte(output.String()), 0755)
|
||||
}
|
||||
|
||||
// bind the given struct method
|
||||
func (b *Manager) bindMethod(object interface{}) error {
|
||||
|
||||
@@ -104,6 +159,12 @@ func (b *Manager) bindMethod(object interface{}) error {
|
||||
|
||||
b.log.Debugf("Processing struct: %s", baseName)
|
||||
|
||||
// Calc actual name
|
||||
actualName := strings.TrimPrefix(baseName, "main.")
|
||||
if b.structList[actualName] == nil {
|
||||
b.structList[actualName] = []string{}
|
||||
}
|
||||
|
||||
// Iterate over method definitions
|
||||
for i := 0; i < objectType.NumMethod(); i++ {
|
||||
|
||||
@@ -113,6 +174,8 @@ func (b *Manager) bindMethod(object interface{}) error {
|
||||
fullMethodName := baseName + "." + methodName
|
||||
method := reflect.ValueOf(object).MethodByName(methodName)
|
||||
|
||||
b.structList[actualName] = append(b.structList[actualName], methodName)
|
||||
|
||||
// Skip unexported methods
|
||||
if !unicode.IsUpper([]rune(methodName)[0]) {
|
||||
continue
|
||||
|
||||
@@ -3,7 +3,6 @@ package event
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/wailsapp/wails/lib/interfaces"
|
||||
"github.com/wailsapp/wails/lib/logger"
|
||||
@@ -13,6 +12,7 @@ import (
|
||||
// Manager handles and processes events
|
||||
type Manager struct {
|
||||
incomingEvents chan *messages.EventData
|
||||
quitChannel chan struct{}
|
||||
listeners map[string][]*eventListener
|
||||
running bool
|
||||
log *logger.CustomLogger
|
||||
@@ -24,6 +24,7 @@ type Manager struct {
|
||||
func NewManager() interfaces.EventManager {
|
||||
return &Manager{
|
||||
incomingEvents: make(chan *messages.EventData, 100),
|
||||
quitChannel: make(chan struct{}, 1),
|
||||
listeners: make(map[string][]*eventListener),
|
||||
running: false,
|
||||
log: logger.NewCustomLogger("Events"),
|
||||
@@ -141,8 +142,8 @@ func (e *Manager) Start(renderer interfaces.Renderer) {
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
case <-e.quitChannel:
|
||||
e.running = false
|
||||
}
|
||||
}
|
||||
e.wg.Done()
|
||||
@@ -152,7 +153,7 @@ func (e *Manager) Start(renderer interfaces.Renderer) {
|
||||
// Shutdown is called when exiting the Application
|
||||
func (e *Manager) Shutdown() {
|
||||
e.log.Debug("Shutting Down")
|
||||
e.running = false
|
||||
e.quitChannel <- struct{}{}
|
||||
e.log.Debug("Waiting for main loop to exit")
|
||||
e.wg.Wait()
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
package interfaces
|
||||
|
||||
// CallbackFunc defines the signature of a function required to be provided to the
|
||||
// Dispatch function so that the response may be returned
|
||||
type CallbackFunc func(string) error
|
||||
|
||||
// IPCManager is the event manager interface
|
||||
type IPCManager interface {
|
||||
BindRenderer(Renderer)
|
||||
Dispatch(message string)
|
||||
Dispatch(message string, f CallbackFunc)
|
||||
Start(eventManager EventManager, bindingManager BindingManager)
|
||||
Shutdown()
|
||||
}
|
||||
|
||||
@@ -3,14 +3,15 @@ package interfaces
|
||||
import (
|
||||
"github.com/wailsapp/wails/lib/messages"
|
||||
)
|
||||
|
||||
// Renderer is an interface describing a Wails target to render the app to
|
||||
type Renderer interface {
|
||||
Initialise(AppConfig, IPCManager, EventManager) error
|
||||
Run() error
|
||||
EnableConsole()
|
||||
|
||||
// Binding
|
||||
NewBinding(bindingName string) error
|
||||
Callback(data string) error
|
||||
|
||||
// Events
|
||||
NotifyEvent(eventData *messages.EventData) error
|
||||
|
||||
@@ -3,7 +3,6 @@ package ipc
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/wailsapp/wails/lib/interfaces"
|
||||
"github.com/wailsapp/wails/lib/logger"
|
||||
@@ -124,8 +123,8 @@ func (i *Manager) Start(eventManager interfaces.EventManager, bindingManager int
|
||||
i.log.DebugFields("Finished processing message", logger.Fields{
|
||||
"1D": &incomingMessage,
|
||||
})
|
||||
default:
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
case <-i.quitChannel:
|
||||
i.running = false
|
||||
}
|
||||
}
|
||||
i.log.Debug("Stopping")
|
||||
@@ -136,10 +135,10 @@ func (i *Manager) Start(eventManager interfaces.EventManager, bindingManager int
|
||||
// Dispatch receives JSON encoded messages from the renderer.
|
||||
// It processes the message to ensure that it is valid and places
|
||||
// the processed message on the message queue
|
||||
func (i *Manager) Dispatch(message string) {
|
||||
func (i *Manager) Dispatch(message string, cb interfaces.CallbackFunc) {
|
||||
|
||||
// Create a new IPC Message
|
||||
incomingMessage, err := newIPCMessage(message, i.SendResponse)
|
||||
incomingMessage, err := newIPCMessage(message, i.SendResponse(cb))
|
||||
if err != nil {
|
||||
i.log.ErrorFields("Could not understand incoming message! ", map[string]interface{}{
|
||||
"message": message,
|
||||
@@ -159,23 +158,25 @@ func (i *Manager) Dispatch(message string) {
|
||||
}
|
||||
|
||||
// SendResponse sends the given response back to the frontend
|
||||
func (i *Manager) SendResponse(response *ipcResponse) error {
|
||||
// It sends the data back to the correct renderer by way of the provided callback function
|
||||
func (i *Manager) SendResponse(cb interfaces.CallbackFunc) func(i *ipcResponse) error {
|
||||
|
||||
// Serialise the Message
|
||||
data, err := response.Serialise()
|
||||
if err != nil {
|
||||
fmt.Printf(err.Error())
|
||||
return err
|
||||
return func(response *ipcResponse) error {
|
||||
// Serialise the Message
|
||||
data, err := response.Serialise()
|
||||
if err != nil {
|
||||
fmt.Printf(err.Error())
|
||||
return err
|
||||
}
|
||||
return cb(data)
|
||||
}
|
||||
|
||||
// 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.quitChannel <- struct{}{}
|
||||
i.log.Debug("Waiting of main loop shutdown")
|
||||
i.wg.Wait()
|
||||
}
|
||||
|
||||
@@ -1,258 +1,10 @@
|
||||
package renderer
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/dchest/htmlmin"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/leaanthony/mewn"
|
||||
"github.com/wailsapp/wails/lib/interfaces"
|
||||
"github.com/wailsapp/wails/lib/logger"
|
||||
"github.com/wailsapp/wails/lib/messages"
|
||||
bridge "github.com/wailsapp/wails/lib/renderer/bridge"
|
||||
)
|
||||
|
||||
type messageType int
|
||||
|
||||
const (
|
||||
jsMessage messageType = iota
|
||||
cssMessage
|
||||
htmlMessage
|
||||
notifyMessage
|
||||
bindingMessage
|
||||
callbackMessage
|
||||
wailsRuntimeMessage
|
||||
)
|
||||
|
||||
func (m messageType) toString() string {
|
||||
return [...]string{"j", "s", "h", "n", "b", "c", "w"}[m]
|
||||
}
|
||||
|
||||
// Bridge is a backend that opens a local web server
|
||||
// and renders the files over a websocket
|
||||
type Bridge struct {
|
||||
// Common
|
||||
log *logger.CustomLogger
|
||||
ipcManager interfaces.IPCManager
|
||||
appConfig interfaces.AppConfig
|
||||
eventManager interfaces.EventManager
|
||||
bindingCache []string
|
||||
|
||||
// Bridge specific
|
||||
initialisationJS []string
|
||||
server *http.Server
|
||||
theConnection *websocket.Conn
|
||||
|
||||
// Mutex for writing to the socket
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
// 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
|
||||
ipcManager.BindRenderer(h)
|
||||
h.log = logger.NewCustomLogger("Bridge")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Bridge) evalJS(js string, mtype messageType) error {
|
||||
|
||||
message := mtype.toString() + js
|
||||
|
||||
if h.theConnection == nil {
|
||||
h.initialisationJS = append(h.initialisationJS, message)
|
||||
} else {
|
||||
// Prepend message type to message
|
||||
h.sendMessage(h.theConnection, message)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
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,
|
||||
})
|
||||
if err != nil {
|
||||
h.log.Fatal("Unable to minify CSS: " + css)
|
||||
}
|
||||
minifiedCSS := string(minified)
|
||||
minifiedCSS = strings.Replace(minifiedCSS, "\\", "\\\\", -1)
|
||||
minifiedCSS = strings.Replace(minifiedCSS, "'", "\\'", -1)
|
||||
minifiedCSS = strings.Replace(minifiedCSS, "\n", " ", -1)
|
||||
inject := fmt.Sprintf("wails._.InjectCSS('%s')", minifiedCSS)
|
||||
h.evalJS(inject, cssMessage)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
h.theConnection = conn
|
||||
h.log.Infof("Connection from frontend accepted [%p].", h.theConnection)
|
||||
conn.SetCloseHandler(func(int, string) error {
|
||||
h.log.Infof("Connection dropped [%p].", h.theConnection)
|
||||
h.theConnection = nil
|
||||
return nil
|
||||
})
|
||||
go h.start(conn)
|
||||
}
|
||||
|
||||
func (h *Bridge) sendMessage(conn *websocket.Conn, msg string) {
|
||||
|
||||
h.lock.Lock()
|
||||
defer h.lock.Unlock()
|
||||
|
||||
if err := conn.WriteMessage(websocket.TextMessage, []byte(msg)); err != nil {
|
||||
h.log.Error(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Bridge) start(conn *websocket.Conn) {
|
||||
|
||||
// set external.invoke
|
||||
h.log.Infof("Connected to frontend.")
|
||||
|
||||
wailsRuntime := mewn.String("../../runtime/assets/wails.js")
|
||||
h.evalJS(wailsRuntime, wailsRuntimeMessage)
|
||||
|
||||
// Inject bindings
|
||||
for _, binding := range h.bindingCache {
|
||||
h.evalJS(binding, bindingMessage)
|
||||
}
|
||||
|
||||
// Emit that everything is loaded and ready
|
||||
h.eventManager.Emit("wails:ready")
|
||||
|
||||
for {
|
||||
messageType, buffer, err := conn.ReadMessage()
|
||||
if messageType == -1 {
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
h.log.Errorf("Error reading message: ", err)
|
||||
continue
|
||||
}
|
||||
|
||||
h.log.Debugf("Got message: %#v\n", string(buffer))
|
||||
|
||||
h.ipcManager.Dispatch(string(buffer))
|
||||
}
|
||||
}
|
||||
|
||||
// Run the app in Bridge mode!
|
||||
func (h *Bridge) Run() error {
|
||||
h.server = &http.Server{Addr: ":34115"}
|
||||
http.HandleFunc("/bridge", h.wsBridgeHandler)
|
||||
|
||||
h.log.Info("Bridge mode started.")
|
||||
h.log.Info("The frontend will connect automatically.")
|
||||
|
||||
err := h.server.ListenAndServe()
|
||||
if err != nil && err != http.ErrServerClosed {
|
||||
h.log.Fatal(err.Error())
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// NewBinding creates a new binding with the frontend
|
||||
func (h *Bridge) NewBinding(methodName string) error {
|
||||
h.bindingCache = append(h.bindingCache, methodName)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SelectFile is unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Bridge) SelectFile() string {
|
||||
h.log.Warn("SelectFile() unsupported in bridge mode")
|
||||
return ""
|
||||
}
|
||||
|
||||
// SelectDirectory is unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Bridge) SelectDirectory() string {
|
||||
h.log.Warn("SelectDirectory() unsupported in bridge mode")
|
||||
return ""
|
||||
}
|
||||
|
||||
// SelectSaveFile is unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Bridge) SelectSaveFile() string {
|
||||
h.log.Warn("SelectSaveFile() unsupported in bridge mode")
|
||||
return ""
|
||||
}
|
||||
|
||||
// Callback sends a callback to the frontend
|
||||
func (h *Bridge) Callback(data string) error {
|
||||
return h.evalJS(data, callbackMessage)
|
||||
}
|
||||
|
||||
// NotifyEvent notifies the frontend of an event
|
||||
func (h *Bridge) NotifyEvent(event *messages.EventData) error {
|
||||
|
||||
// Look out! Nils about!
|
||||
var err error
|
||||
if event == nil {
|
||||
err = fmt.Errorf("Sent nil event to renderer.webViewRenderer")
|
||||
h.log.Error(err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
// Default data is a blank array
|
||||
data := []byte("[]")
|
||||
|
||||
// Process event data
|
||||
if event.Data != nil {
|
||||
// Marshall the data
|
||||
data, err = json.Marshal(event.Data)
|
||||
if err != nil {
|
||||
h.log.Errorf("Cannot unmarshall JSON data in event: %s ", err.Error())
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
message := fmt.Sprintf("window.wails._.Notify('%s','%s')", event.Name, data)
|
||||
return h.evalJS(message, notifyMessage)
|
||||
}
|
||||
|
||||
// SetColour is unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
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 Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Bridge) Fullscreen() {
|
||||
h.log.Warn("Fullscreen() unsupported in bridge mode")
|
||||
}
|
||||
|
||||
// UnFullscreen is unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Bridge) UnFullscreen() {
|
||||
h.log.Warn("UnFullscreen() unsupported in bridge mode")
|
||||
}
|
||||
|
||||
// SetTitle is currently unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Bridge) SetTitle(title string) {
|
||||
h.log.WarnFields("SetTitle() unsupported in bridge mode", logger.Fields{"title": title})
|
||||
}
|
||||
|
||||
// Close is unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Bridge) Close() {
|
||||
h.log.Debug("Shutting down")
|
||||
err := h.server.Close()
|
||||
if err != nil {
|
||||
h.log.Errorf(err.Error())
|
||||
}
|
||||
// NewBridge returns a new Bridge struct
|
||||
func NewBridge() *bridge.Bridge {
|
||||
return &bridge.Bridge{}
|
||||
}
|
||||
|
||||
214
lib/renderer/bridge/bridge.go
Normal file
214
lib/renderer/bridge/bridge.go
Normal file
@@ -0,0 +1,214 @@
|
||||
package renderer
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/wailsapp/wails/lib/interfaces"
|
||||
"github.com/wailsapp/wails/lib/logger"
|
||||
"github.com/wailsapp/wails/lib/messages"
|
||||
)
|
||||
|
||||
type messageType int
|
||||
|
||||
const (
|
||||
jsMessage messageType = iota
|
||||
cssMessage
|
||||
htmlMessage
|
||||
notifyMessage
|
||||
bindingMessage
|
||||
callbackMessage
|
||||
wailsRuntimeMessage
|
||||
)
|
||||
|
||||
func (m messageType) toString() string {
|
||||
return [...]string{"j", "s", "h", "n", "b", "c", "w"}[m]
|
||||
}
|
||||
|
||||
// Bridge is a backend that opens a local web server
|
||||
// and renders the files over a websocket
|
||||
type Bridge struct {
|
||||
// Common
|
||||
log *logger.CustomLogger
|
||||
ipcManager interfaces.IPCManager
|
||||
appConfig interfaces.AppConfig
|
||||
eventManager interfaces.EventManager
|
||||
bindingCache []string
|
||||
|
||||
// Bridge specific
|
||||
server *http.Server
|
||||
|
||||
lock sync.Mutex
|
||||
sessions map[string]session
|
||||
}
|
||||
|
||||
// Initialise the Bridge Renderer
|
||||
func (h *Bridge) Initialise(appConfig interfaces.AppConfig, ipcManager interfaces.IPCManager, eventManager interfaces.EventManager) error {
|
||||
h.sessions = map[string]session{}
|
||||
h.ipcManager = ipcManager
|
||||
h.appConfig = appConfig
|
||||
h.eventManager = eventManager
|
||||
ipcManager.BindRenderer(h)
|
||||
h.log = logger.NewCustomLogger("Bridge")
|
||||
return nil
|
||||
}
|
||||
|
||||
// EnableConsole not needed for bridge!
|
||||
func (h *Bridge) EnableConsole() {
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
h.log.Infof("Connection from frontend accepted [%s].", conn.RemoteAddr().String())
|
||||
h.startSession(conn)
|
||||
}
|
||||
|
||||
func (h *Bridge) startSession(conn *websocket.Conn) {
|
||||
s := session{
|
||||
conn: conn,
|
||||
bindingCache: h.bindingCache,
|
||||
ipc: h.ipcManager,
|
||||
log: h.log,
|
||||
eventManager: h.eventManager,
|
||||
}
|
||||
|
||||
conn.SetCloseHandler(func(int, string) error {
|
||||
h.log.Infof("Connection dropped [%s].", s.Identifier())
|
||||
h.eventManager.Emit("wails:bridge:session:closed", s.Identifier())
|
||||
h.lock.Lock()
|
||||
defer h.lock.Unlock()
|
||||
delete(h.sessions, s.Identifier())
|
||||
return nil
|
||||
})
|
||||
|
||||
h.lock.Lock()
|
||||
defer h.lock.Unlock()
|
||||
go s.start(len(h.sessions) == 0)
|
||||
h.sessions[s.Identifier()] = s
|
||||
}
|
||||
|
||||
// Run the app in Bridge mode!
|
||||
func (h *Bridge) Run() error {
|
||||
h.server = &http.Server{Addr: ":34115"}
|
||||
http.HandleFunc("/bridge", h.wsBridgeHandler)
|
||||
|
||||
h.log.Info("Bridge mode started.")
|
||||
h.log.Info("The frontend will connect automatically.")
|
||||
|
||||
err := h.server.ListenAndServe()
|
||||
if err != nil && err != http.ErrServerClosed {
|
||||
h.log.Fatal(err.Error())
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// NewBinding creates a new binding with the frontend
|
||||
func (h *Bridge) NewBinding(methodName string) error {
|
||||
h.bindingCache = append(h.bindingCache, methodName)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SelectFile is unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Bridge) SelectFile() string {
|
||||
h.log.Warn("SelectFile() unsupported in bridge mode")
|
||||
return ""
|
||||
}
|
||||
|
||||
// SelectDirectory is unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Bridge) SelectDirectory() string {
|
||||
h.log.Warn("SelectDirectory() unsupported in bridge mode")
|
||||
return ""
|
||||
}
|
||||
|
||||
// SelectSaveFile is unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Bridge) SelectSaveFile() string {
|
||||
h.log.Warn("SelectSaveFile() unsupported in bridge mode")
|
||||
return ""
|
||||
}
|
||||
|
||||
// NotifyEvent notifies the frontend of an event
|
||||
func (h *Bridge) NotifyEvent(event *messages.EventData) error {
|
||||
|
||||
// Look out! Nils about!
|
||||
var err error
|
||||
if event == nil {
|
||||
err = fmt.Errorf("Sent nil event to renderer.webViewRenderer")
|
||||
h.log.Error(err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
// Default data is a blank array
|
||||
data := []byte("[]")
|
||||
|
||||
// Process event data
|
||||
if event.Data != nil {
|
||||
// Marshall the data
|
||||
data, err = json.Marshal(event.Data)
|
||||
if err != nil {
|
||||
h.log.Errorf("Cannot unmarshall JSON data in event: %s ", err.Error())
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
message := fmt.Sprintf("window.wails._.Notify('%s','%s')", event.Name, data)
|
||||
dead := []session{}
|
||||
for _, session := range h.sessions {
|
||||
err := session.evalJS(message, notifyMessage)
|
||||
if err != nil {
|
||||
h.log.Debugf("Failed to send message to %s - Removing listener : %v", session.Identifier(), err)
|
||||
h.log.Infof("Connection from [%v] unresponsive - dropping", session.Identifier())
|
||||
dead = append(dead, session)
|
||||
}
|
||||
}
|
||||
h.lock.Lock()
|
||||
defer h.lock.Unlock()
|
||||
for _, session := range dead {
|
||||
delete(h.sessions, session.Identifier())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetColour is unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
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 Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Bridge) Fullscreen() {
|
||||
h.log.Warn("Fullscreen() unsupported in bridge mode")
|
||||
}
|
||||
|
||||
// UnFullscreen is unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Bridge) UnFullscreen() {
|
||||
h.log.Warn("UnFullscreen() unsupported in bridge mode")
|
||||
}
|
||||
|
||||
// SetTitle is currently unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Bridge) SetTitle(title string) {
|
||||
h.log.WarnFields("SetTitle() unsupported in bridge mode", logger.Fields{"title": title})
|
||||
}
|
||||
|
||||
// Close is unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Bridge) Close() {
|
||||
h.log.Debug("Shutting down")
|
||||
err := h.server.Close()
|
||||
if err != nil {
|
||||
h.log.Errorf(err.Error())
|
||||
}
|
||||
}
|
||||
90
lib/renderer/bridge/session.go
Normal file
90
lib/renderer/bridge/session.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package renderer
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/leaanthony/mewn"
|
||||
"github.com/wailsapp/wails/lib/interfaces"
|
||||
"github.com/wailsapp/wails/lib/logger"
|
||||
)
|
||||
|
||||
// TODO Move this back into bridge.go
|
||||
|
||||
// session represents a single websocket session
|
||||
type session struct {
|
||||
bindingCache []string
|
||||
conn *websocket.Conn
|
||||
eventManager interfaces.EventManager
|
||||
log *logger.CustomLogger
|
||||
ipc interfaces.IPCManager
|
||||
|
||||
// Mutex for writing to the socket
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
// Identifier returns a string identifier for the remote connection.
|
||||
// Taking the form of the client's <ip address>:<port>.
|
||||
func (s *session) Identifier() string {
|
||||
if s.conn != nil {
|
||||
return s.conn.RemoteAddr().String()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s *session) sendMessage(msg string) error {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
if err := s.conn.WriteMessage(websocket.TextMessage, []byte(msg)); err != nil {
|
||||
s.log.Debug(err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *session) start(firstSession bool) {
|
||||
s.log.Infof("Connected to frontend.")
|
||||
|
||||
wailsRuntime := mewn.String("../../runtime/assets/wails.js")
|
||||
s.evalJS(wailsRuntime, wailsRuntimeMessage)
|
||||
|
||||
// Inject bindings
|
||||
for _, binding := range s.bindingCache {
|
||||
s.evalJS(binding, bindingMessage)
|
||||
}
|
||||
s.eventManager.Emit("wails:bridge:session:started", s.Identifier())
|
||||
|
||||
// Emit that everything is loaded and ready
|
||||
if firstSession {
|
||||
s.eventManager.Emit("wails:ready")
|
||||
}
|
||||
|
||||
for {
|
||||
messageType, buffer, err := s.conn.ReadMessage()
|
||||
if messageType == -1 {
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
s.log.Errorf("Error reading message: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
s.log.Debugf("Got message: %#v\n", string(buffer))
|
||||
|
||||
s.ipc.Dispatch(string(buffer), s.Callback)
|
||||
}
|
||||
}
|
||||
|
||||
// Callback sends a callback to the frontend
|
||||
func (s *session) Callback(data string) error {
|
||||
return s.evalJS(data, callbackMessage)
|
||||
}
|
||||
|
||||
func (s *session) evalJS(js string, mtype messageType) error {
|
||||
|
||||
// Prepend message type to message
|
||||
return s.sendMessage(mtype.toString() + js)
|
||||
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -19,12 +19,13 @@ import (
|
||||
// WebView defines the main webview application window
|
||||
// Default values in []
|
||||
type WebView struct {
|
||||
window wv.WebView // The webview object
|
||||
ipc interfaces.IPCManager
|
||||
log *logger.CustomLogger
|
||||
config interfaces.AppConfig
|
||||
eventManager interfaces.EventManager
|
||||
bindingCache []string
|
||||
window wv.WebView // The webview object
|
||||
ipc interfaces.IPCManager
|
||||
log *logger.CustomLogger
|
||||
config interfaces.AppConfig
|
||||
eventManager interfaces.EventManager
|
||||
bindingCache []string
|
||||
enableConsole bool
|
||||
}
|
||||
|
||||
// NewWebView returns a new WebView struct
|
||||
@@ -57,7 +58,7 @@ func (w *WebView) Initialise(config interfaces.AppConfig, ipc interfaces.IPCMana
|
||||
URL: config.GetDefaultHTML(),
|
||||
Debug: !config.GetDisableInspector(),
|
||||
ExternalInvokeCallback: func(_ wv.WebView, message string) {
|
||||
w.ipc.Dispatch(message)
|
||||
w.ipc.Dispatch(message, w.callback)
|
||||
},
|
||||
})
|
||||
|
||||
@@ -103,6 +104,11 @@ func (w *WebView) evalJS(js string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// EnableConsole enables the console!
|
||||
func (w *WebView) EnableConsole() {
|
||||
w.enableConsole = true
|
||||
}
|
||||
|
||||
// Escape the Javascripts!
|
||||
func escapeJS(js string) (string, error) {
|
||||
result := strings.Replace(js, "\\", "\\\\", -1)
|
||||
@@ -172,6 +178,13 @@ func (w *WebView) Run() error {
|
||||
|
||||
w.log.Info("Running...")
|
||||
|
||||
// Inject firebug in debug mode on Windows
|
||||
if w.enableConsole {
|
||||
w.log.Debug("Enabling Wails console")
|
||||
console := mewn.String("../../runtime/assets/console.js")
|
||||
w.evalJS(console)
|
||||
}
|
||||
|
||||
// Runtime assets
|
||||
wailsRuntime := mewn.String("../../runtime/assets/wails.js")
|
||||
w.evalJS(wailsRuntime)
|
||||
@@ -286,8 +299,8 @@ func (w *WebView) SelectSaveFile() string {
|
||||
return result
|
||||
}
|
||||
|
||||
// Callback sends a callback to the frontend
|
||||
func (w *WebView) Callback(data string) error {
|
||||
// callback sends a callback to the frontend
|
||||
func (w *WebView) callback(data string) error {
|
||||
callbackCMD := fmt.Sprintf("window.wails._.Callback('%s');", data)
|
||||
return w.evalJS(callbackCMD)
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ 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 -std=c99 -DUNICODE=1
|
||||
#cgo windows CFLAGS: -DWEBVIEW_WINAPI=1 -std=c99
|
||||
#cgo windows LDFLAGS: -lole32 -lcomctl32 -loleaut32 -luuid -lgdi32
|
||||
|
||||
#cgo darwin CFLAGS: -DWEBVIEW_COCOA=1 -x objective-c
|
||||
|
||||
@@ -1603,9 +1603,20 @@ struct webview_priv
|
||||
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen)
|
||||
{
|
||||
if (w->priv.is_fullscreen == !!fullscreen)
|
||||
|
||||
BIN
logo_cropped.png
Normal file
BIN
logo_cropped.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 122 KiB |
@@ -14,7 +14,7 @@ function init() {
|
||||
window.wailsbridge = {
|
||||
reconnectOverlay: null,
|
||||
reconnectTimer: 300,
|
||||
wsURL: 'ws://localhost:34115/bridge',
|
||||
wsURL: 'ws://' + window.location.hostname + ':34115/bridge',
|
||||
connectionState: null,
|
||||
config: {},
|
||||
websocket: null,
|
||||
@@ -95,13 +95,6 @@ function startBridge() {
|
||||
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.
|
||||
// Removes it if second parameter is true.
|
||||
function addScript(script, remove) {
|
||||
@@ -214,4 +207,4 @@ function Init(callback) {
|
||||
start(callback);
|
||||
}
|
||||
|
||||
module.exports = Init;
|
||||
module.exports = Init;
|
||||
|
||||
175
runtime/assets/console.js
Normal file
175
runtime/assets/console.js
Normal file
@@ -0,0 +1,175 @@
|
||||
(function () {
|
||||
|
||||
window.wailsconsole = {};
|
||||
|
||||
var debugconsole = document.createElement("div");
|
||||
var header = document.createElement("div");
|
||||
var consoleOut = document.createElement("div");
|
||||
|
||||
|
||||
document.addEventListener('keyup', logKey);
|
||||
|
||||
debugconsole.id = "wailsdebug";
|
||||
debugconsole.style.fontSize = "18px";
|
||||
debugconsole.style.width = "100%";
|
||||
debugconsole.style.height = "35%";
|
||||
debugconsole.style.maxHeight = "35%";
|
||||
debugconsole.style.position = "fixed";
|
||||
debugconsole.style.left = "0px";
|
||||
debugconsole.style.backgroundColor = "rgba(255,255,255,0.8)";
|
||||
debugconsole.style.borderTop = '1px solid black';
|
||||
debugconsole.style.color = "black";
|
||||
debugconsole.style.display = "none";
|
||||
|
||||
header.style.width = "100%";
|
||||
header.style.height = "30px";
|
||||
header.style.display = "block";
|
||||
// header.style.paddingTop = "3px";
|
||||
header.style.verticalAlign = "middle";
|
||||
header.style.paddingLeft = "10px";
|
||||
header.style.background = "rgba(255,255,255,0.8)";
|
||||
header.innerHTML = " <span style='vertical-align: middle'> Wails Console > <input id='conin' style='border: solid 1px black; width: 50%'></input><span style='padding-left: 5px; cursor:pointer;' onclick='window.wailsconsole.clearConsole()'>Clear</span></span>";
|
||||
|
||||
consoleOut.style.position = "absolute";
|
||||
consoleOut.style.width = "100%";
|
||||
consoleOut.style.height = "auto";
|
||||
consoleOut.style.top = "30px";
|
||||
// consoleOut.style.paddingLeft = "10px";
|
||||
consoleOut.style.bottom = "0px";
|
||||
consoleOut.style.backgroundColor = "rgba(200,200,200,1)";
|
||||
consoleOut.style.overflowY = "scroll";
|
||||
consoleOut.style.msOverflowStyle = "-ms-autohiding-scrollbar";
|
||||
|
||||
debugconsole.appendChild(header);
|
||||
debugconsole.appendChild(consoleOut);
|
||||
document.body.appendChild(debugconsole);
|
||||
console.log(debugconsole.style.display)
|
||||
|
||||
function logKey(e) {
|
||||
var conin = document.getElementById('conin');
|
||||
if (e.which == 27 && e.shiftKey) {
|
||||
toggleConsole(conin);
|
||||
}
|
||||
if (e.which == 13 && consoleVisible()) {
|
||||
var command = conin.value.trim();
|
||||
if (command.length > 0) {
|
||||
console.log("> " + command)
|
||||
try {
|
||||
evaluateInput(command);
|
||||
} catch (e) {
|
||||
console.error(e.message);
|
||||
}
|
||||
conin.value = "";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function consoleVisible() {
|
||||
return debugconsole.style.display == "block";
|
||||
}
|
||||
|
||||
function toggleConsole(conin) {
|
||||
var display = "none"
|
||||
if (debugconsole.style.display == "none") display = "block";
|
||||
debugconsole.style.display = display;
|
||||
if (display == "block") {
|
||||
conin.focus();
|
||||
}
|
||||
}
|
||||
|
||||
function evaluateExpression(expression) {
|
||||
|
||||
var pathSegments = [].concat(expression.split('.'));
|
||||
if (pathSegments[0] == 'window') {
|
||||
pathSegments.shift()
|
||||
}
|
||||
var currentObject = window;
|
||||
for (var i = 0; i < pathSegments.length; i++) {
|
||||
var pathSegment = pathSegments[i];
|
||||
if (currentObject[pathSegment] == undefined) {
|
||||
return false;
|
||||
}
|
||||
currentObject = currentObject[pathSegment];
|
||||
}
|
||||
console.log(JSON.stringify(currentObject));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function evaluateInput(command) {
|
||||
try {
|
||||
if (evaluateExpression(command)) {
|
||||
return
|
||||
} else {
|
||||
eval(command);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e.message)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Set us up as a listener
|
||||
function hookIntoIPC() {
|
||||
if (window.wails && window.wails._ && window.wails._.AddIPCListener) {
|
||||
window.wails._.AddIPCListener(processIPCMessage);
|
||||
} else {
|
||||
setTimeout(hookIntoIPC, 100);
|
||||
}
|
||||
}
|
||||
hookIntoIPC();
|
||||
|
||||
function processIPCMessage(message) {
|
||||
console.log(message);
|
||||
var parsedMessage;
|
||||
try {
|
||||
parsedMessage = JSON.parse(message);
|
||||
} catch (e) {
|
||||
console.error("Error in parsing IPC message: " + e.message);
|
||||
return false;
|
||||
}
|
||||
var logmessage = "[IPC] "
|
||||
switch (parsedMessage.type) {
|
||||
case 'call':
|
||||
logmessage += " Call: " + parsedMessage.payload.bindingName;
|
||||
var params = "";
|
||||
var parsedParams = JSON.parse(parsedMessage.payload.data);
|
||||
if (parsedParams.length > 0) {
|
||||
params = parsedParams;
|
||||
}
|
||||
logmessage += "(" + params + ")";
|
||||
break;
|
||||
case 'log':
|
||||
logmessage += "Log (" + parsedMessage.payload.level + "): " + parsedMessage.payload.message;
|
||||
break;
|
||||
default:
|
||||
logmessage = message;
|
||||
}
|
||||
console.log(logmessage);
|
||||
}
|
||||
|
||||
window.wailsconsole.clearConsole = function () {
|
||||
consoleOut.innerHTML = "";
|
||||
}
|
||||
|
||||
console.log = function (message) {
|
||||
consoleOut.innerHTML = consoleOut.innerHTML + "<span style='padding-left: 5px'>" + message + '</span><br/>';
|
||||
consoleOut.scrollTop = consoleOut.scrollHeight;
|
||||
|
||||
};
|
||||
console.error = function (message) {
|
||||
consoleOut.innerHTML = consoleOut.innerHTML + "<span style='color:red; padding-left: 5px'> Error: " + message + '</span><br/>';
|
||||
consoleOut.scrollTop = consoleOut.scrollHeight;
|
||||
};
|
||||
// var h = document.getElementsByTagName("html")[0];
|
||||
// console.log("html margin: " + h.style.marginLeft);
|
||||
// console.log("html padding: " + h.style.paddingLeft);
|
||||
|
||||
// setInterval(function() { console.log("test");}, 1000);
|
||||
// setInterval(function() { console.error("oops");}, 3000);
|
||||
// var script = document.createElement('script');
|
||||
// script.src = "https://cdnjs.cloudflare.com/ajax/libs/firebug-lite/1.4.0/firebug-lite.js#startOpened=true";
|
||||
// document.body.appendChild(script);
|
||||
|
||||
})();
|
||||
File diff suppressed because one or more lines are too long
@@ -15,10 +15,7 @@
|
||||
"error",
|
||||
"tab"
|
||||
],
|
||||
"linebreak-style": [
|
||||
"error",
|
||||
"unix"
|
||||
],
|
||||
"linebreak-style": 0,
|
||||
"quotes": [
|
||||
"error",
|
||||
"single"
|
||||
@@ -28,4 +25,4 @@
|
||||
"always"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,13 +9,35 @@ The lightweight framework for web-like apps
|
||||
*/
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
// IPC Listeners
|
||||
var listeners = [];
|
||||
|
||||
/**
|
||||
* Adds a listener to IPC messages
|
||||
* @param {function} callback
|
||||
*/
|
||||
export function AddIPCListener(callback) {
|
||||
listeners.push(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke sends the given message to the backend
|
||||
*
|
||||
* @param {string} message
|
||||
*/
|
||||
function Invoke(message) {
|
||||
window.external.invoke(message);
|
||||
if (window.wailsbridge) {
|
||||
window.wailsbridge.websocket.send(message);
|
||||
} else {
|
||||
window.external.invoke(message);
|
||||
}
|
||||
|
||||
// Also send to listeners
|
||||
if (listeners.length > 0) {
|
||||
for (var i = 0; i < listeners.length; i++) {
|
||||
listeners[i](message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,6 +14,7 @@ import { On, OnMultiple, Emit, Notify, Heartbeat, Acknowledge } from './events';
|
||||
import { NewBinding } from './bindings';
|
||||
import { Callback } from './calls';
|
||||
import { AddScript, InjectCSS } from './utils';
|
||||
import { AddIPCListener } from './ipc';
|
||||
|
||||
// Initialise global if not already
|
||||
window.wails = window.wails || {};
|
||||
@@ -27,6 +28,7 @@ var internal = {
|
||||
AddScript,
|
||||
InjectCSS,
|
||||
Init,
|
||||
AddIPCListener,
|
||||
};
|
||||
|
||||
// Setup runtime structure
|
||||
@@ -46,6 +48,16 @@ var runtime = {
|
||||
// Augment global
|
||||
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('wails:loaded');
|
||||
|
||||
|
||||
@@ -32,6 +32,6 @@ function OpenFile(filename) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
OpenURL,
|
||||
OpenFile
|
||||
OpenURL: OpenURL,
|
||||
OpenFile: OpenFile
|
||||
};
|
||||
@@ -52,7 +52,8 @@ function Once(eventName, callback) {
|
||||
* @param {string} eventName
|
||||
*/
|
||||
function Emit(eventName) {
|
||||
return window.wails.Events.Emit(eventName);
|
||||
var args = [eventName].slice.call(arguments);
|
||||
return window.wails.Events.Emit.apply(null, args);
|
||||
}
|
||||
|
||||
|
||||
@@ -80,10 +81,10 @@ function Acknowledge(eventName) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
OnMultiple,
|
||||
On,
|
||||
Once,
|
||||
Emit,
|
||||
Heartbeat,
|
||||
Acknowledge
|
||||
OnMultiple: OnMultiple,
|
||||
On: On,
|
||||
Once: Once,
|
||||
Emit: Emit,
|
||||
Heartbeat: Heartbeat,
|
||||
Acknowledge: Acknowledge
|
||||
};
|
||||
@@ -18,4 +18,4 @@ function Init(callback) {
|
||||
window.wails._.Init(callback);
|
||||
}
|
||||
|
||||
module.exports = Init;
|
||||
module.exports = Init;
|
||||
|
||||
@@ -62,9 +62,9 @@ function Fatal(message) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Debug,
|
||||
Info,
|
||||
Warning,
|
||||
Error,
|
||||
Fatal
|
||||
Debug: Debug,
|
||||
Info: Info,
|
||||
Warning: Warning,
|
||||
Error: Error,
|
||||
Fatal: Fatal
|
||||
};
|
||||
|
||||
@@ -15,8 +15,8 @@ const Events = require('./events');
|
||||
const Init = require('./init');
|
||||
|
||||
module.exports = {
|
||||
Log,
|
||||
Browser,
|
||||
Events,
|
||||
Init
|
||||
Log: Log,
|
||||
Browser: Browser,
|
||||
Events: Events,
|
||||
Init: Init
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@wailsapp/runtime",
|
||||
"version": "1.0.6",
|
||||
"version": "1.0.11",
|
||||
"description": "Wails Javascript runtime library",
|
||||
"main": "main.js",
|
||||
"types": "runtime.d.ts",
|
||||
@@ -25,4 +25,4 @@
|
||||
"devDependencies": {
|
||||
"dts-gen": "^0.5.8"
|
||||
}
|
||||
}
|
||||
}
|
||||
12
runtime/js/runtime/runtime.d.ts
vendored
12
runtime/js/runtime/runtime.d.ts
vendored
@@ -6,12 +6,12 @@ declare const wailsapp__runtime: {
|
||||
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;
|
||||
Acknowledge(eventName: string): void;
|
||||
Emit(eventName: string, data?: any): void;
|
||||
Heartbeat(eventName: string, timeInMilliseconds: number, callback: (data?: any) => void): void;
|
||||
On(eventName: string, callback: (data?: any) => void): void;
|
||||
OnMultiple(eventName: string, callback: (data?: any) => void, maxCallbacks: number): void;
|
||||
Once(eventName: string, callback: (data?: any) => void): void;
|
||||
};
|
||||
Init(callback: () => void): void;
|
||||
Log: {
|
||||
|
||||
85
scripts/build.go
Normal file
85
scripts/build.go
Normal file
@@ -0,0 +1,85 @@
|
||||
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()
|
||||
fmt.Println(string(output))
|
||||
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")
|
||||
}
|
||||
Reference in New Issue
Block a user