mirror of
https://github.com/taigrr/wails.git
synced 2026-04-04 14:12:40 -07:00
Compare commits
2 Commits
js-package
...
update-wai
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9fbfccdd86 | ||
|
|
1d1a7967ad |
32
.github/workflows/latest-pre.yml
vendored
32
.github/workflows/latest-pre.yml
vendored
@@ -1,32 +0,0 @@
|
|||||||
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.13
|
|
||||||
uses: actions/setup-go@v1
|
|
||||||
with:
|
|
||||||
go-version: 1.13
|
|
||||||
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
32
.github/workflows/pr.yml
vendored
@@ -1,32 +0,0 @@
|
|||||||
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.13
|
|
||||||
uses: actions/setup-go@v1
|
|
||||||
with:
|
|
||||||
go-version: 1.13
|
|
||||||
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
34
.github/workflows/release.yml
vendored
@@ -1,34 +0,0 @@
|
|||||||
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.13
|
|
||||||
uses: actions/setup-go@v1
|
|
||||||
with:
|
|
||||||
go-version: 1.13
|
|
||||||
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
|
|
||||||
11
.gitignore
vendored
11
.gitignore
vendored
@@ -16,13 +16,4 @@ examples/**/example*
|
|||||||
cmd/wails/wails
|
cmd/wails/wails
|
||||||
.DS_Store
|
.DS_Store
|
||||||
tmp
|
tmp
|
||||||
node_modules/
|
node_modules/
|
||||||
package.json.md5
|
|
||||||
v2/test/**/frontend/dist
|
|
||||||
v2/test/**/build/
|
|
||||||
v2/test/frameless/icon.png
|
|
||||||
v2/test/hidden/icon.png
|
|
||||||
v2/internal/ffenestri/runtime.c
|
|
||||||
v2/internal/runtime/assets/desktop.js
|
|
||||||
v2/test/kitchensink/frontend/public/bundle.*
|
|
||||||
v2/pkg/parser/testproject/frontend/wails
|
|
||||||
@@ -2,33 +2,19 @@
|
|||||||
|
|
||||||
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!
|
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)
|
* [Dustin Krysak](https://wiki.ubuntu.com/bashfulrobot)
|
||||||
* [Qais Patankar](https://github.com/qaisjp)
|
* [Qais Patankar](https://github.com/qaisjp)
|
||||||
* [Anthony Lee](https://github.com/alee792)
|
* [Anthony Lee](https://github.com/alee792)
|
||||||
* [Adrian Lanzafame](https://github.com/lanzafame)
|
* [Adrian Lanzafame](https://github.com/lanzafame)
|
||||||
* [Mattn](https://github.com/mattn)
|
* [Mattn](https://github.com/mattn)
|
||||||
* [0xflotus](https://github.com/0xflotus)
|
* [0xflotus](https://github.com/0xflotus)
|
||||||
* [Michael D Henderson](https://github.com/mdhender)
|
* [Michael D Henderson](https://github.com/mdhender)
|
||||||
* [fred2104](https://github.com/fishfishfish2104)
|
* [fred2104](https://github.com/fishfishfish2104)
|
||||||
* [intelwalk](https://github.com/intelwalk)
|
* [intelwalk](https://github.com/intelwalk)
|
||||||
* [Mark Stenglein](https://github.com/ocelotsloth)
|
* [Mark Stenglein](https://github.com/ocelotsloth)
|
||||||
* [admin_3.exe](https://github.com/bh90210)
|
* [admin_3.exe](https://github.com/bh90210)
|
||||||
* [iceleo-com](https://github.com/iceleo-com)
|
* [iceleo-com](https://github.com/iceleo-com)
|
||||||
* [fallendusk](https://github.com/fallendusk)
|
* [fallendusk](https://github.com/fallendusk)
|
||||||
* [Nikolai Zimmermann](https://github.com/Chronophylos)
|
* [Florian Didran](https://github.com/fdidron)
|
||||||
* [Toyam Cox](https://github.com/Vaelatern)
|
* [Nikolai Zimmermann](https://github.com/Chronophylos)
|
||||||
* [Robin Eklind](https://github.com/mewmew)
|
* [Toyam Cox](https://github.com/Vaelatern)
|
||||||
* [Kris Raney](https://github.com/kraney)
|
|
||||||
* [Jack Mordaunt](https://github.com/JackMordaunt)
|
|
||||||
* [Michael Hipp](https://github.com/MichaelHipp)
|
|
||||||
* [Travis McLane](https://github.com/tmclane)
|
|
||||||
* [Reuben Thomas-Davis](https://github.com/Rested)
|
|
||||||
* [Jarek](https://github.com/Jarek-SRT)
|
|
||||||
* [Konez2k](https://github.com/konez2k)
|
|
||||||
* [msms](https://github.com/sayuthisobri)
|
|
||||||
* [dedo1911](https://github.com/dedo1911)
|
|
||||||
* [Florian Didron](https://github.com/fdidron)
|
|
||||||
* [Christopher Murphy](https://github.com/Splode)
|
|
||||||
* [Zámbó, Levente](https://github.com/Lyimmi)
|
|
||||||
* [artem](https://github.com/Unix4ever)
|
|
||||||
* [Tim Kipp](https://github.com/timkippdev)
|
|
||||||
|
|||||||
32
README.md
32
README.md
@@ -1,5 +1,5 @@
|
|||||||
<p align="center" style="text-align: center">
|
<p align="center" style="text-align: center">
|
||||||
<img src="logo_cropped.png" width="40%"><br/>
|
<img src="https://github.com/wailsapp/docs/raw/master/.vuepress/public/media/logo_cropped.png" width="40%"><br/>
|
||||||
</p>
|
</p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
A framework for building desktop applications using Go & Web Technologies.<br/><br/>
|
A framework for building desktop applications using Go & Web Technologies.<br/><br/>
|
||||||
@@ -11,14 +11,11 @@
|
|||||||
<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://app.fossa.io/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_shield" alt="FOSSA Status"><img src="https://app.fossa.io/api/projects/git%2Bgithub.com%2Fwailsapp%2Fwails.svg?type=shield"/></a>
|
||||||
<a href="https://houndci.com"><img src="https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg"/></a>
|
<a href="https://houndci.com"><img src="https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg"/></a>
|
||||||
<a href="https://github.com/avelino/awesome-go" rel="nofollow"><img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome"></a>
|
<a href="https://github.com/avelino/awesome-go" rel="nofollow"><img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome"></a>
|
||||||
<a href="https://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://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/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>
|
</p>
|
||||||
|
|
||||||
The traditional method of providing web interfaces to Go programs is via a built-in web server. Wails offers a different approach: it provides the ability to wrap both Go code and a web frontend into a single binary. Tools are provided to make this easy for you by handling project creation, compilation and bundling. All you have to do is get creative!
|
The traditional method of providing web interfaces to Go programs is via a built-in web server. Wails offers a different approach: it provides the ability to wrap both Go code and a web frontend into a single binary. Tools are provided to make this easy for you by handling project creation, compilation and bundling. All you have to do is get creative!
|
||||||
|
|
||||||
The official docs can be found at [https://wails.app](https://wails.app).
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Use standard Go libraries/frameworks for the backend
|
- Use standard Go libraries/frameworks for the backend
|
||||||
@@ -31,12 +28,15 @@ The official docs can be found at [https://wails.app](https://wails.app).
|
|||||||
- Powerful cli tool
|
- Powerful cli tool
|
||||||
- Multiplatform
|
- 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
|
## Installation
|
||||||
|
|
||||||
Wails uses cgo to bind to the native rendering engines so a number of platform dependent libraries are needed as well as an installation of Go. The basic requirements are:
|
Wails uses cgo to bind to the native rendering engines so a number of platform dependent libraries are needed as well as an installation of Go. The basic requirements are:
|
||||||
|
|
||||||
- Go 1.13
|
- Go 1.12
|
||||||
- npm
|
- npm
|
||||||
|
|
||||||
### MacOS
|
### MacOS
|
||||||
@@ -52,16 +52,15 @@ Make sure you have the xcode command line tools installed. This can be done by r
|
|||||||
`sudo apt install libgtk-3-dev libwebkit2gtk-4.0-dev`
|
`sudo apt install libgtk-3-dev libwebkit2gtk-4.0-dev`
|
||||||
|
|
||||||
_Debian: 8, 9, 10_
|
_Debian: 8, 9, 10_
|
||||||
|
|
||||||
_Ubuntu: 16.04, 18.04, 19.04_
|
_Ubuntu: 16.04, 18.04, 19.04_
|
||||||
|
|
||||||
_Also succesfully tested on: Zorin 15, Parrot 4.7, Linuxmint 19, Elementary 5, Kali, Neon_, Pop!_OS
|
_Also succesfully tested on: Zorin 15, Parrot 4.7, Linuxmint 19, Elementary 5, Kali-Rolling_
|
||||||
|
|
||||||
#### Arch Linux / ArchLabs
|
#### Arch Linux
|
||||||
|
|
||||||
`sudo pacman -S webkit2gtk gtk3`
|
`sudo pacman -S webkit2gtk gtk3`
|
||||||
|
|
||||||
_Also succesfully test on: Manjaro & ArcoLinux_
|
_Also succesfully test on: ArcoLinuxB_
|
||||||
|
|
||||||
#### Centos
|
#### Centos
|
||||||
|
|
||||||
@@ -94,7 +93,7 @@ Windows requires gcc and related tooling. The recommended download is from [http
|
|||||||
Installation is as simple as running the following command:
|
Installation is as simple as running the following command:
|
||||||
|
|
||||||
<pre style='color:white'>
|
<pre style='color:white'>
|
||||||
go get -u github.com/wailsapp/wails/cmd/wails
|
go get github.com/wailsapp/wails/cmd/wails
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## Next Steps
|
## Next Steps
|
||||||
@@ -126,7 +125,8 @@ And without [these people](CONTRIBUTORS.md), it wouldn't be what it is today. A
|
|||||||
|
|
||||||
Special Mentions:
|
Special Mentions:
|
||||||
|
|
||||||
* [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.
|
* [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.
|
||||||
|
|
||||||
This project was mainly coded to the following albums:
|
This project was mainly coded to the following albums:
|
||||||
|
|
||||||
@@ -147,11 +147,3 @@ This project was mainly coded to the following albums:
|
|||||||
## Licensing
|
## Licensing
|
||||||
|
|
||||||
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_large)
|
[](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>
|
|
||||||
|
|||||||
52
app.go
52
app.go
@@ -1,11 +1,6 @@
|
|||||||
package wails
|
package wails
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
"runtime"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/syossan27/tebata"
|
|
||||||
"github.com/wailsapp/wails/cmd"
|
"github.com/wailsapp/wails/cmd"
|
||||||
"github.com/wailsapp/wails/lib/binding"
|
"github.com/wailsapp/wails/lib/binding"
|
||||||
"github.com/wailsapp/wails/lib/event"
|
"github.com/wailsapp/wails/lib/event"
|
||||||
@@ -44,7 +39,7 @@ func CreateApp(optionalConfig ...*AppConfig) *App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
result := &App{
|
result := &App{
|
||||||
logLevel: "debug",
|
logLevel: "info",
|
||||||
renderer: renderer.NewWebView(),
|
renderer: renderer.NewWebView(),
|
||||||
ipc: ipc.NewManager(),
|
ipc: ipc.NewManager(),
|
||||||
bindingManager: binding.NewManager(),
|
bindingManager: binding.NewManager(),
|
||||||
@@ -66,15 +61,11 @@ func CreateApp(optionalConfig ...*AppConfig) *App {
|
|||||||
result.config.DisableInspector = true
|
result.config.DisableInspector = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Platform specific init
|
|
||||||
platformInit()
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the app
|
// Run the app
|
||||||
func (a *App) Run() error {
|
func (a *App) Run() error {
|
||||||
|
|
||||||
if BuildMode != cmd.BuildModeProd {
|
if BuildMode != cmd.BuildModeProd {
|
||||||
return a.cli.Run()
|
return a.cli.Run()
|
||||||
}
|
}
|
||||||
@@ -97,7 +88,7 @@ func (a *App) start() error {
|
|||||||
|
|
||||||
// Check if we are to run in bridge mode
|
// Check if we are to run in bridge mode
|
||||||
if BuildMode == cmd.BuildModeBridge {
|
if BuildMode == cmd.BuildModeBridge {
|
||||||
a.renderer = renderer.NewBridge()
|
a.renderer = &renderer.Bridge{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialise the renderer
|
// Initialise the renderer
|
||||||
@@ -106,18 +97,6 @@ func (a *App) start() error {
|
|||||||
return err
|
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() {
|
|
||||||
a.log.Debug("SIGNAL CAUGHT! Starting Shutdown")
|
|
||||||
a.renderer.Close()
|
|
||||||
})
|
|
||||||
|
|
||||||
// Start event manager and give it our renderer
|
// Start event manager and give it our renderer
|
||||||
a.eventManager.Start(a.renderer)
|
a.eventManager.Start(a.renderer)
|
||||||
|
|
||||||
@@ -133,33 +112,8 @@ func (a *App) start() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defer the shutdown
|
|
||||||
defer a.shutdown()
|
|
||||||
|
|
||||||
// Run the renderer
|
// Run the renderer
|
||||||
err = a.renderer.Run()
|
return a.renderer.Run()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// shutdown the app
|
|
||||||
func (a *App) shutdown() {
|
|
||||||
// Make sure this is only called once
|
|
||||||
a.log.Debug("Shutting down")
|
|
||||||
|
|
||||||
// Shutdown Binding Manager
|
|
||||||
a.bindingManager.Shutdown()
|
|
||||||
|
|
||||||
// Shutdown IPC Manager
|
|
||||||
a.ipc.Shutdown()
|
|
||||||
|
|
||||||
// Shutdown Event Manager
|
|
||||||
a.eventManager.Shutdown()
|
|
||||||
|
|
||||||
a.log.Debug("Cleanly Shutdown")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind allows the user to bind the given object
|
// Bind allows the user to bind the given object
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
// +build linux darwin !windows
|
|
||||||
|
|
||||||
package wails
|
|
||||||
|
|
||||||
func platformInit() {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
// +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
|
|
||||||
}
|
|
||||||
138
azure-pipelines.yaml
Normal file
138
azure-pipelines.yaml
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
# avoid double trigger by applying some rules
|
||||||
|
# start a pipeline when push to 'master' branch
|
||||||
|
trigger:
|
||||||
|
- master
|
||||||
|
# or when pull request on 'develop' branch
|
||||||
|
pr:
|
||||||
|
- develop
|
||||||
|
|
||||||
|
# for now there is only one stage 'Build'
|
||||||
|
# in the future we could use multistage strategy for releases
|
||||||
|
stages:
|
||||||
|
- stage: Build
|
||||||
|
|
||||||
|
# there are 3 jobs
|
||||||
|
# one for each os
|
||||||
|
jobs:
|
||||||
|
- deployment: Linux
|
||||||
|
displayName: Lin
|
||||||
|
variables:
|
||||||
|
GOPATH: '$(Agent.BuildDirectory)/gopath' # Go workspace path
|
||||||
|
GOROOT: '$(Agent.BuildDirectory)/go' # Go installation path
|
||||||
|
GOBIN: '$(GOPATH)/bin' # Go binaries path
|
||||||
|
GOMODULE: 'on'
|
||||||
|
modulePath: '$(Agent.BuildDirectory)/wails' # Path to the module's code
|
||||||
|
pool:
|
||||||
|
vmImage: 'Ubuntu-16.04'
|
||||||
|
environment: 'linux-dev'
|
||||||
|
strategy:
|
||||||
|
runOnce:
|
||||||
|
deploy:
|
||||||
|
steps:
|
||||||
|
- checkout: self # self represents the repo where the initial Pipelines YAML file was found
|
||||||
|
clean: true # whether to fetch clean each time
|
||||||
|
path: wails # path to check out source code, relative to the agent's build directory (e.g. \_work\1)
|
||||||
|
# go version 1.12.7
|
||||||
|
- script: |
|
||||||
|
wget "https://storage.googleapis.com/golang/go1.12.7.linux-amd64.tar.gz" --output-document "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
|
||||||
|
tar -C '$(Agent.BuildDirectory)' -xzf "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
|
||||||
|
displayName: 'Install Go 1.12.7 Linux'
|
||||||
|
- script: |
|
||||||
|
mkdir -p '$(GOBIN)'
|
||||||
|
mkdir -p '$(GOPATH)/pkg'
|
||||||
|
mkdir -p '$(GOROOT)'
|
||||||
|
shopt -s extglob
|
||||||
|
shopt -s dotglob
|
||||||
|
echo '##vso[task.prependpath]$(GOBIN)'
|
||||||
|
echo '##vso[task.prependpath]$(GOROOT)/bin'
|
||||||
|
displayName: 'Set up the Go workspace'
|
||||||
|
- script: |
|
||||||
|
go version
|
||||||
|
go get -v -d ./...
|
||||||
|
cd cmd/wails
|
||||||
|
go install
|
||||||
|
workingDirectory: '$(modulePath)'
|
||||||
|
displayName: 'Get dependencies, then build'
|
||||||
|
- script: |
|
||||||
|
wails version
|
||||||
|
workingDirectory: '$(modulePath)'
|
||||||
|
displayName: 'Check we have output'
|
||||||
|
|
||||||
|
- deployment: Mac
|
||||||
|
displayName: Mac
|
||||||
|
variables:
|
||||||
|
GOPATH: '$(Agent.BuildDirectory)/gopath' # Go workspace path
|
||||||
|
GOROOT: '$(Agent.BuildDirectory)/go' # Go installation path
|
||||||
|
GOBIN: '$(GOPATH)/bin' # Go binaries path
|
||||||
|
GOMODULE: 'on'
|
||||||
|
modulePath: '$(Agent.BuildDirectory)/wails' # Path to the module's code
|
||||||
|
pool:
|
||||||
|
vmImage: 'macOS-10.14'
|
||||||
|
environment: 'mac-dev'
|
||||||
|
strategy:
|
||||||
|
runOnce:
|
||||||
|
deploy:
|
||||||
|
steps:
|
||||||
|
- checkout: self # self represents the repo where the initial Pipelines YAML file was found
|
||||||
|
clean: true # whether to fetch clean each time
|
||||||
|
path: wails # path to check out source code, relative to the agent's build directory (e.g. \_work\1)
|
||||||
|
# go version 1.12.7
|
||||||
|
- script: |
|
||||||
|
wget "https://storage.googleapis.com/golang/go1.12.7.darwin-amd64.tar.gz" --output-document "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
|
||||||
|
tar -C '$(Agent.BuildDirectory)' -xzf "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
|
||||||
|
displayName: 'Install Go 1.12.7 Linux'
|
||||||
|
- script: |
|
||||||
|
mkdir -p '$(GOBIN)'
|
||||||
|
mkdir -p '$(GOPATH)/pkg'
|
||||||
|
mkdir -p '$(GOROOT)'
|
||||||
|
shopt -s extglob
|
||||||
|
shopt -s dotglob
|
||||||
|
echo '##vso[task.prependpath]$(GOBIN)'
|
||||||
|
echo '##vso[task.prependpath]$(GOROOT)/bin'
|
||||||
|
displayName: 'Set up the Go workspace'
|
||||||
|
- script: |
|
||||||
|
go version
|
||||||
|
go get -v -d ./...
|
||||||
|
cd cmd/wails
|
||||||
|
go install
|
||||||
|
workingDirectory: '$(modulePath)'
|
||||||
|
displayName: 'Get dependencies, then build'
|
||||||
|
- script: |
|
||||||
|
wails version
|
||||||
|
workingDirectory: '$(modulePath)'
|
||||||
|
displayName: 'Check we have output'
|
||||||
|
|
||||||
|
- deployment: Win
|
||||||
|
displayName: Win
|
||||||
|
variables:
|
||||||
|
GOMODULE: 'on'
|
||||||
|
modulePath: '$(Agent.BuildDirectory)/wails' # Path to the module's code
|
||||||
|
pool:
|
||||||
|
vmImage: 'windows-2019'
|
||||||
|
environment: 'win-dev'
|
||||||
|
strategy:
|
||||||
|
runOnce:
|
||||||
|
deploy:
|
||||||
|
steps:
|
||||||
|
- checkout: self # self represents the repo where the initial Pipelines YAML file was found
|
||||||
|
clean: true # whether to fetch clean each time
|
||||||
|
path: wails # path to check out source code, relative to the agent's build directory (e.g. \_work\1)
|
||||||
|
# Go tool installer
|
||||||
|
# Find in cache or download a specific version of Go and add it to the PATH
|
||||||
|
- task: GoTool@0
|
||||||
|
inputs:
|
||||||
|
version: '1.12.7'
|
||||||
|
goPath: '$(Agent.BuildDirectory)/go'
|
||||||
|
goBin: '$(Agent.BuildDirectory)/go/bin'
|
||||||
|
displayName: 'Set up the Go workspace'
|
||||||
|
- script: |
|
||||||
|
go version
|
||||||
|
go get -v -d ./...
|
||||||
|
cd cmd/wails
|
||||||
|
go install
|
||||||
|
workingDirectory: '$(modulePath)'
|
||||||
|
displayName: 'Get dependencies, then build'
|
||||||
|
- script: |
|
||||||
|
wails version
|
||||||
|
workingDirectory: '$(Agent.BuildDirectory)/go/bin'
|
||||||
|
displayName: 'Check we have output'
|
||||||
138
azure-pipelines.yml
Normal file
138
azure-pipelines.yml
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
# avoid double trigger by applying some rules
|
||||||
|
# start a pipeline when push to 'master' branch
|
||||||
|
trigger:
|
||||||
|
- master
|
||||||
|
# or when pull request on 'develop' branch
|
||||||
|
pr:
|
||||||
|
- develop
|
||||||
|
|
||||||
|
# for now there is only one stage 'Build'
|
||||||
|
# in the future we could use multistage strategy for releases
|
||||||
|
stages:
|
||||||
|
- stage: Build
|
||||||
|
|
||||||
|
# there are 3 jobs
|
||||||
|
# one for each os
|
||||||
|
jobs:
|
||||||
|
- deployment: Linux
|
||||||
|
displayName: Lin
|
||||||
|
variables:
|
||||||
|
GOPATH: '$(Agent.BuildDirectory)/gopath' # Go workspace path
|
||||||
|
GOROOT: '$(Agent.BuildDirectory)/go' # Go installation path
|
||||||
|
GOBIN: '$(GOPATH)/bin' # Go binaries path
|
||||||
|
GOMODULE: 'on'
|
||||||
|
modulePath: '$(Agent.BuildDirectory)/wails' # Path to the module's code
|
||||||
|
pool:
|
||||||
|
vmImage: 'Ubuntu-16.04'
|
||||||
|
environment: 'linux-dev'
|
||||||
|
strategy:
|
||||||
|
runOnce:
|
||||||
|
deploy:
|
||||||
|
steps:
|
||||||
|
- checkout: self # self represents the repo where the initial Pipelines YAML file was found
|
||||||
|
clean: true # whether to fetch clean each time
|
||||||
|
path: wails # path to check out source code, relative to the agent's build directory (e.g. \_work\1)
|
||||||
|
# go version 1.12.7
|
||||||
|
- script: |
|
||||||
|
wget "https://storage.googleapis.com/golang/go1.12.7.linux-amd64.tar.gz" --output-document "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
|
||||||
|
tar -C '$(Agent.BuildDirectory)' -xzf "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
|
||||||
|
displayName: 'Install Go 1.12.7 Linux'
|
||||||
|
- script: |
|
||||||
|
mkdir -p '$(GOBIN)'
|
||||||
|
mkdir -p '$(GOPATH)/pkg'
|
||||||
|
mkdir -p '$(GOROOT)'
|
||||||
|
shopt -s extglob
|
||||||
|
shopt -s dotglob
|
||||||
|
echo '##vso[task.prependpath]$(GOBIN)'
|
||||||
|
echo '##vso[task.prependpath]$(GOROOT)/bin'
|
||||||
|
displayName: 'Set up the Go workspace'
|
||||||
|
- script: |
|
||||||
|
go version
|
||||||
|
go get -v -d ./...
|
||||||
|
cd cmd/wails
|
||||||
|
go install
|
||||||
|
workingDirectory: '$(modulePath)'
|
||||||
|
displayName: 'Get dependencies, then build'
|
||||||
|
- script: |
|
||||||
|
wails version
|
||||||
|
workingDirectory: '$(modulePath)'
|
||||||
|
displayName: 'Check we have output'
|
||||||
|
|
||||||
|
- deployment: Mac
|
||||||
|
displayName: Mac
|
||||||
|
variables:
|
||||||
|
GOPATH: '$(Agent.BuildDirectory)/gopath' # Go workspace path
|
||||||
|
GOROOT: '$(Agent.BuildDirectory)/go' # Go installation path
|
||||||
|
GOBIN: '$(GOPATH)/bin' # Go binaries path
|
||||||
|
GOMODULE: 'on'
|
||||||
|
modulePath: '$(Agent.BuildDirectory)/wails' # Path to the module's code
|
||||||
|
pool:
|
||||||
|
vmImage: 'macOS-10.14'
|
||||||
|
environment: 'mac-dev'
|
||||||
|
strategy:
|
||||||
|
runOnce:
|
||||||
|
deploy:
|
||||||
|
steps:
|
||||||
|
- checkout: self # self represents the repo where the initial Pipelines YAML file was found
|
||||||
|
clean: true # whether to fetch clean each time
|
||||||
|
path: wails # path to check out source code, relative to the agent's build directory (e.g. \_work\1)
|
||||||
|
# go version 1.12.7
|
||||||
|
- script: |
|
||||||
|
wget "https://storage.googleapis.com/golang/go1.12.7.darwin-amd64.tar.gz" --output-document "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
|
||||||
|
tar -C '$(Agent.BuildDirectory)' -xzf "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
|
||||||
|
displayName: 'Install Go 1.12.7 Linux'
|
||||||
|
- script: |
|
||||||
|
mkdir -p '$(GOBIN)'
|
||||||
|
mkdir -p '$(GOPATH)/pkg'
|
||||||
|
mkdir -p '$(GOROOT)'
|
||||||
|
shopt -s extglob
|
||||||
|
shopt -s dotglob
|
||||||
|
echo '##vso[task.prependpath]$(GOBIN)'
|
||||||
|
echo '##vso[task.prependpath]$(GOROOT)/bin'
|
||||||
|
displayName: 'Set up the Go workspace'
|
||||||
|
- script: |
|
||||||
|
go version
|
||||||
|
go get -v -d ./...
|
||||||
|
cd cmd/wails
|
||||||
|
go install
|
||||||
|
workingDirectory: '$(modulePath)'
|
||||||
|
displayName: 'Get dependencies, then build'
|
||||||
|
- script: |
|
||||||
|
wails version
|
||||||
|
workingDirectory: '$(modulePath)'
|
||||||
|
displayName: 'Check we have output'
|
||||||
|
|
||||||
|
- deployment: Win
|
||||||
|
displayName: Win
|
||||||
|
variables:
|
||||||
|
GOMODULE: 'on'
|
||||||
|
modulePath: '$(Agent.BuildDirectory)/wails' # Path to the module's code
|
||||||
|
pool:
|
||||||
|
vmImage: 'windows-2019'
|
||||||
|
environment: 'win-dev'
|
||||||
|
strategy:
|
||||||
|
runOnce:
|
||||||
|
deploy:
|
||||||
|
steps:
|
||||||
|
- checkout: self # self represents the repo where the initial Pipelines YAML file was found
|
||||||
|
clean: true # whether to fetch clean each time
|
||||||
|
path: wails # path to check out source code, relative to the agent's build directory (e.g. \_work\1)
|
||||||
|
# Go tool installer
|
||||||
|
# Find in cache or download a specific version of Go and add it to the PATH
|
||||||
|
- task: GoTool@0
|
||||||
|
inputs:
|
||||||
|
version: '1.12.7'
|
||||||
|
goPath: '$(Agent.BuildDirectory)/go'
|
||||||
|
goBin: '$(Agent.BuildDirectory)/go/bin'
|
||||||
|
displayName: 'Set up the Go workspace'
|
||||||
|
- script: |
|
||||||
|
go version
|
||||||
|
go get -v -d ./...
|
||||||
|
cd cmd/wails
|
||||||
|
go install
|
||||||
|
workingDirectory: '$(modulePath)'
|
||||||
|
displayName: 'Get dependencies, then build'
|
||||||
|
- script: |
|
||||||
|
wails version
|
||||||
|
workingDirectory: '$(Agent.BuildDirectory)/go/bin'
|
||||||
|
displayName: 'Check we have output'
|
||||||
File diff suppressed because one or more lines are too long
31
cmd/fs.go
31
cmd/fs.go
@@ -12,7 +12,6 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/leaanthony/slicer"
|
"github.com/leaanthony/slicer"
|
||||||
)
|
)
|
||||||
@@ -48,22 +47,6 @@ func (fs *FSHelper) FileExists(path string) bool {
|
|||||||
return fi.Mode().IsRegular()
|
return fi.Mode().IsRegular()
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindFile returns the first occurrence of match inside path.
|
|
||||||
func (fs *FSHelper) FindFile(path, match string) (string, error) {
|
|
||||||
files, err := ioutil.ReadDir(path)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, f := range files {
|
|
||||||
if !f.IsDir() && strings.Contains(f.Name(), match) {
|
|
||||||
return f.Name(), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", fmt.Errorf("file not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateFile creates a file at the given filename location with the contents
|
// CreateFile creates a file at the given filename location with the contents
|
||||||
// set to the given data. It will create intermediary directories if needed.
|
// set to the given data. It will create intermediary directories if needed.
|
||||||
func (fs *FSHelper) CreateFile(filename string, data []byte) error {
|
func (fs *FSHelper) CreateFile(filename string, data []byte) error {
|
||||||
@@ -117,10 +100,10 @@ func (fs *FSHelper) RemoveFile(filename string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RemoveFiles removes the given filenames
|
// RemoveFiles removes the given filenames
|
||||||
func (fs *FSHelper) RemoveFiles(files []string, continueOnError bool) error {
|
func (fs *FSHelper) RemoveFiles(files []string) error {
|
||||||
for _, filename := range files {
|
for _, filename := range files {
|
||||||
err := os.Remove(filename)
|
err := os.Remove(filename)
|
||||||
if err != nil && !continueOnError {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,16 +132,6 @@ func (fs *FSHelper) LocalDir(dir string) (*Dir, error) {
|
|||||||
}, err
|
}, 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
|
// GetSubdirs will return a list of FQPs to subdirectories in the given directory
|
||||||
func (d *Dir) GetSubdirs() (map[string]string, error) {
|
func (d *Dir) GetSubdirs() (map[string]string, error) {
|
||||||
|
|
||||||
|
|||||||
78
cmd/gomod.go
78
cmd/gomod.go
@@ -1,78 +0,0 @@
|
|||||||
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)
|
|
||||||
|
|
||||||
}
|
|
||||||
429
cmd/helpers.go
429
cmd/helpers.go
@@ -5,15 +5,11 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"os/user"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/leaanthony/mewn"
|
"github.com/leaanthony/mewn"
|
||||||
"github.com/leaanthony/mewn/lib"
|
|
||||||
"github.com/leaanthony/slicer"
|
"github.com/leaanthony/slicer"
|
||||||
"github.com/leaanthony/spinner"
|
"github.com/leaanthony/spinner"
|
||||||
)
|
)
|
||||||
@@ -39,161 +35,34 @@ func ValidateFrontendConfig(projectOptions *ProjectOptions) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InstallGoDependencies will run go get in the current directory
|
// InstallGoDependencies will run go get in the current directory
|
||||||
func InstallGoDependencies(verbose bool) error {
|
func InstallGoDependencies() error {
|
||||||
var depSpinner *spinner.Spinner
|
depSpinner := spinner.New("Ensuring Dependencies are up to date...")
|
||||||
if !verbose {
|
depSpinner.SetSpinSpeed(50)
|
||||||
depSpinner = spinner.New("Ensuring Dependencies are up to date...")
|
depSpinner.Start()
|
||||||
depSpinner.SetSpinSpeed(50)
|
err := NewProgramHelper().RunCommand("go get")
|
||||||
depSpinner.Start()
|
|
||||||
}
|
|
||||||
err := NewProgramHelper(verbose).RunCommand("go get")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !verbose {
|
depSpinner.Error()
|
||||||
depSpinner.Error()
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !verbose {
|
depSpinner.Success()
|
||||||
depSpinner.Success()
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// EmbedAssets will embed the built frontend assets via mewn.
|
// BuildApplication will attempt to build the project based on the given inputs
|
||||||
func EmbedAssets() ([]string, error) {
|
func BuildApplication(binaryName string, forceRebuild bool, buildMode string, packageApp bool, projectOptions *ProjectOptions) error {
|
||||||
mewnFiles := lib.GetMewnFiles([]string{}, false)
|
|
||||||
|
|
||||||
referencedAssets, err := lib.GetReferencedAssets(mewnFiles)
|
// Generate Windows assets if needed
|
||||||
if err != nil {
|
if runtime.GOOS == "windows" {
|
||||||
return []string{}, err
|
cleanUp := !packageApp
|
||||||
}
|
err := NewPackageHelper().PackageWindows(projectOptions, cleanUp)
|
||||||
|
|
||||||
targetFiles := []string{}
|
|
||||||
|
|
||||||
for _, referencedAsset := range referencedAssets {
|
|
||||||
packfileData, err := lib.GeneratePackFileString(referencedAsset, false)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []string{}, err
|
return err
|
||||||
}
|
}
|
||||||
targetFile := filepath.Join(referencedAsset.BaseDir, referencedAsset.PackageName+"-mewn.go")
|
|
||||||
targetFiles = append(targetFiles, targetFile)
|
|
||||||
ioutil.WriteFile(targetFile, []byte(packfileData), 0644)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return targetFiles, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func InitializeCrossCompilation(verbose bool) error {
|
|
||||||
// Check Docker
|
|
||||||
if err := CheckIfInstalled("docker"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var packSpinner *spinner.Spinner
|
|
||||||
if !verbose {
|
|
||||||
packSpinner = spinner.New("Pulling wailsapp/xgo:latest docker image... (may take a while)")
|
|
||||||
packSpinner.SetSpinSpeed(50)
|
|
||||||
packSpinner.Start()
|
|
||||||
} else {
|
|
||||||
println("Pulling wailsapp/xgo:latest docker image... (may take a while)")
|
|
||||||
}
|
|
||||||
|
|
||||||
err := NewProgramHelper(verbose).RunCommandArray([]string{"docker",
|
|
||||||
"pull", "wailsapp/xgo:latest"})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if packSpinner != nil {
|
|
||||||
packSpinner.Error()
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if packSpinner != nil {
|
|
||||||
packSpinner.Success()
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BuildDocker builds the project using the cross compiling wailsapp/xgo:latest container
|
|
||||||
func BuildDocker(binaryName string, buildMode string, projectOptions *ProjectOptions) error {
|
|
||||||
var packSpinner *spinner.Spinner
|
|
||||||
if buildMode == BuildModeBridge {
|
|
||||||
return fmt.Errorf("you cant serve the application in cross-compilation")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check build directory
|
|
||||||
buildDirectory := filepath.Join(fs.Cwd(), "build")
|
|
||||||
if !fs.DirExists(buildDirectory) {
|
|
||||||
fs.MkDir(buildDirectory)
|
|
||||||
}
|
|
||||||
|
|
||||||
buildCommand := slicer.String()
|
|
||||||
userid := 1000
|
|
||||||
user, _ := user.Current()
|
|
||||||
if i, err := strconv.Atoi(user.Uid); err == nil {
|
|
||||||
userid = i
|
|
||||||
}
|
|
||||||
for _, arg := range []string{
|
|
||||||
"docker",
|
|
||||||
"run",
|
|
||||||
"--rm",
|
|
||||||
"-v", fmt.Sprintf("%s:/build", filepath.Join(fs.Cwd(), "build")),
|
|
||||||
"-v", fmt.Sprintf("%s:/source", fs.Cwd()),
|
|
||||||
"-e", fmt.Sprintf("LOCAL_USER_ID=%v", userid),
|
|
||||||
"-e", fmt.Sprintf("FLAG_LDFLAGS=%s", ldFlags(projectOptions, buildMode)),
|
|
||||||
"-e", "FLAG_V=false",
|
|
||||||
"-e", "FLAG_X=false",
|
|
||||||
"-e", "FLAG_RACE=false",
|
|
||||||
"-e", "FLAG_BUILDMODE=default",
|
|
||||||
"-e", "FLAG_TRIMPATH=false",
|
|
||||||
"-e", fmt.Sprintf("TARGETS=%s", projectOptions.Platform+"/"+projectOptions.Architecture),
|
|
||||||
"-e", "GOPROXY=",
|
|
||||||
"-e", "GO111MODULE=on",
|
|
||||||
"wailsapp/xgo:latest",
|
|
||||||
".",
|
|
||||||
} {
|
|
||||||
buildCommand.Add(arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
compileMessage := fmt.Sprintf(
|
|
||||||
"Packing + Compiling project for %s/%s using docker image wailsapp/xgo:latest",
|
|
||||||
projectOptions.Platform, projectOptions.Architecture)
|
|
||||||
|
|
||||||
if buildMode == BuildModeDebug {
|
|
||||||
compileMessage += " (Debug Mode)"
|
|
||||||
}
|
|
||||||
|
|
||||||
if !projectOptions.Verbose {
|
|
||||||
packSpinner = spinner.New(compileMessage + "...")
|
|
||||||
packSpinner.SetSpinSpeed(50)
|
|
||||||
packSpinner.Start()
|
|
||||||
} else {
|
|
||||||
println(compileMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
err := NewProgramHelper(projectOptions.Verbose).RunCommandArray(buildCommand.AsSlice())
|
|
||||||
if err != nil {
|
|
||||||
if packSpinner != nil {
|
|
||||||
packSpinner.Error()
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if packSpinner != nil {
|
|
||||||
packSpinner.Success()
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BuildNative builds on the target platform itself.
|
|
||||||
func BuildNative(binaryName string, forceRebuild bool, buildMode string, projectOptions *ProjectOptions) error {
|
|
||||||
|
|
||||||
// Check Mewn is installed
|
// Check Mewn is installed
|
||||||
if err := CheckMewn(projectOptions.Verbose); err != nil {
|
err := CheckMewn()
|
||||||
return err
|
if err != nil {
|
||||||
}
|
|
||||||
|
|
||||||
if err := CheckWindres(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,37 +72,23 @@ func BuildNative(binaryName string, forceRebuild bool, buildMode string, project
|
|||||||
compileMessage += " (Debug Mode)"
|
compileMessage += " (Debug Mode)"
|
||||||
}
|
}
|
||||||
|
|
||||||
var packSpinner *spinner.Spinner
|
packSpinner := spinner.New(compileMessage + "...")
|
||||||
if !projectOptions.Verbose {
|
packSpinner.SetSpinSpeed(50)
|
||||||
packSpinner = spinner.New(compileMessage + "...")
|
packSpinner.Start()
|
||||||
packSpinner.SetSpinSpeed(50)
|
|
||||||
packSpinner.Start()
|
|
||||||
} else {
|
|
||||||
println(compileMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
buildCommand := slicer.String()
|
buildCommand := slicer.String()
|
||||||
buildCommand.Add("go")
|
buildCommand.Add("mewn")
|
||||||
|
|
||||||
buildCommand.Add("build")
|
|
||||||
if buildMode == BuildModeBridge {
|
if buildMode == BuildModeBridge {
|
||||||
// Ignore errors
|
// Ignore errors
|
||||||
buildCommand.Add("-i")
|
buildCommand.Add("-i")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildCommand.Add("build")
|
||||||
|
|
||||||
if binaryName != "" {
|
if binaryName != "" {
|
||||||
// Alter binary name based on OS
|
buildCommand.Add("-o")
|
||||||
switch projectOptions.Platform {
|
buildCommand.Add(binaryName)
|
||||||
case "windows":
|
|
||||||
if !strings.HasSuffix(binaryName, ".exe") {
|
|
||||||
binaryName += ".exe"
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
if strings.HasSuffix(binaryName, ".exe") {
|
|
||||||
binaryName = strings.TrimSuffix(binaryName, ".exe")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buildCommand.Add("-o", filepath.Join("build", binaryName))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are forcing a rebuild
|
// If we are forcing a rebuild
|
||||||
@@ -241,74 +96,28 @@ func BuildNative(binaryName string, forceRebuild bool, buildMode string, project
|
|||||||
buildCommand.Add("-a")
|
buildCommand.Add("-a")
|
||||||
}
|
}
|
||||||
|
|
||||||
buildCommand.AddSlice([]string{"-ldflags", ldFlags(projectOptions, buildMode)})
|
// Setup ld flags
|
||||||
|
ldflags := "-w -s "
|
||||||
if projectOptions.Verbose {
|
if buildMode == BuildModeDebug {
|
||||||
fmt.Printf("Command: %v\n", buildCommand.AsSlice())
|
ldflags = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
err := NewProgramHelper(projectOptions.Verbose).RunCommandArray(buildCommand.AsSlice())
|
// Add windows flags
|
||||||
if err != nil {
|
if runtime.GOOS == "windows" {
|
||||||
if packSpinner != nil {
|
ldflags += "-H windowsgui "
|
||||||
packSpinner.Error()
|
}
|
||||||
}
|
|
||||||
return err
|
ldflags += "-X github.com/wailsapp/wails.BuildMode=" + buildMode
|
||||||
}
|
|
||||||
if packSpinner != nil {
|
buildCommand.AddSlice([]string{"-ldflags", ldflags})
|
||||||
packSpinner.Success()
|
err = NewProgramHelper().RunCommandArray(buildCommand.AsSlice())
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BuildApplication will attempt to build the project based on the given inputs
|
|
||||||
func BuildApplication(binaryName string, forceRebuild bool, buildMode string, packageApp bool, projectOptions *ProjectOptions) error {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
// embed resources
|
|
||||||
targetFiles, err := EmbedAssets()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if projectOptions.CrossCompile {
|
|
||||||
if err := InitializeCrossCompilation(projectOptions.Verbose); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
helper := NewPackageHelper(projectOptions.Platform)
|
|
||||||
|
|
||||||
// Generate windows resources
|
|
||||||
if projectOptions.Platform == "windows" {
|
|
||||||
if err := helper.PackageWindows(projectOptions, false); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// cleanup temporary embedded assets
|
|
||||||
defer func() {
|
|
||||||
for _, filename := range targetFiles {
|
|
||||||
if err := os.Remove(filename); err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Removed by popular demand
|
|
||||||
// TODO: Potentially add a flag to cleanup
|
|
||||||
// if projectOptions.Platform == "windows" {
|
|
||||||
// helper.CleanWindows(projectOptions)
|
|
||||||
// }
|
|
||||||
}()
|
|
||||||
|
|
||||||
if projectOptions.CrossCompile {
|
|
||||||
err = BuildDocker(binaryName, buildMode, projectOptions)
|
|
||||||
} else {
|
|
||||||
err = BuildNative(binaryName, forceRebuild, buildMode, projectOptions)
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
packSpinner.Error()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
packSpinner.Success()
|
||||||
|
|
||||||
|
// packageApp
|
||||||
if packageApp {
|
if packageApp {
|
||||||
err = PackageApplication(projectOptions)
|
err = PackageApplication(projectOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -321,76 +130,61 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
|
|||||||
|
|
||||||
// PackageApplication will attempt to package the application in a platform dependent way
|
// PackageApplication will attempt to package the application in a platform dependent way
|
||||||
func PackageApplication(projectOptions *ProjectOptions) error {
|
func PackageApplication(projectOptions *ProjectOptions) error {
|
||||||
var packageSpinner *spinner.Spinner
|
// Package app
|
||||||
if projectOptions.Verbose {
|
message := "Generating .app"
|
||||||
packageSpinner = spinner.New("Packaging application...")
|
if runtime.GOOS == "windows" {
|
||||||
packageSpinner.SetSpinSpeed(50)
|
err := CheckWindres()
|
||||||
packageSpinner.Start()
|
if err != nil {
|
||||||
}
|
return err
|
||||||
|
|
||||||
err := NewPackageHelper(projectOptions.Platform).Package(projectOptions)
|
|
||||||
if err != nil {
|
|
||||||
if packageSpinner != nil {
|
|
||||||
packageSpinner.Error()
|
|
||||||
}
|
}
|
||||||
|
message = "Generating resource bundle"
|
||||||
|
}
|
||||||
|
packageSpinner := spinner.New(message)
|
||||||
|
packageSpinner.SetSpinSpeed(50)
|
||||||
|
packageSpinner.Start()
|
||||||
|
err := NewPackageHelper().Package(projectOptions)
|
||||||
|
if err != nil {
|
||||||
|
packageSpinner.Error()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if packageSpinner != nil {
|
packageSpinner.Success()
|
||||||
packageSpinner.Success()
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildFrontend runs the given build command
|
// BuildFrontend runs the given build command
|
||||||
func BuildFrontend(projectOptions *ProjectOptions) error {
|
func BuildFrontend(buildCommand string) error {
|
||||||
var buildFESpinner *spinner.Spinner
|
buildFESpinner := spinner.New("Building frontend...")
|
||||||
if !projectOptions.Verbose {
|
buildFESpinner.SetSpinSpeed(50)
|
||||||
buildFESpinner = spinner.New("Building frontend...")
|
buildFESpinner.Start()
|
||||||
buildFESpinner.SetSpinSpeed(50)
|
err := NewProgramHelper().RunCommand(buildCommand)
|
||||||
buildFESpinner.Start()
|
|
||||||
} else {
|
|
||||||
println("Building frontend...")
|
|
||||||
}
|
|
||||||
err := NewProgramHelper(projectOptions.Verbose).RunCommand(projectOptions.FrontEnd.Build)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if buildFESpinner != nil {
|
buildFESpinner.Error()
|
||||||
buildFESpinner.Error()
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if buildFESpinner != nil {
|
buildFESpinner.Success()
|
||||||
buildFESpinner.Success()
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckMewn checks if mewn is installed and if not, attempts to fetch it
|
// CheckMewn checks if mewn is installed and if not, attempts to fetch it
|
||||||
func CheckMewn(verbose bool) (err error) {
|
func CheckMewn() (err error) {
|
||||||
programHelper := NewProgramHelper(verbose)
|
programHelper := NewProgramHelper()
|
||||||
if !programHelper.IsInstalled("mewn") {
|
if !programHelper.IsInstalled("mewn") {
|
||||||
var buildSpinner *spinner.Spinner
|
buildSpinner := spinner.New()
|
||||||
if !verbose {
|
buildSpinner.SetSpinSpeed(50)
|
||||||
buildSpinner = spinner.New()
|
buildSpinner.Start("Installing Mewn asset packer...")
|
||||||
buildSpinner.SetSpinSpeed(50)
|
|
||||||
buildSpinner.Start("Installing Mewn asset packer...")
|
|
||||||
}
|
|
||||||
err := programHelper.InstallGoPackage("github.com/leaanthony/mewn/cmd/mewn")
|
err := programHelper.InstallGoPackage("github.com/leaanthony/mewn/cmd/mewn")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if buildSpinner != nil {
|
buildSpinner.Error()
|
||||||
buildSpinner.Error()
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if buildSpinner != nil {
|
buildSpinner.Success()
|
||||||
buildSpinner.Success()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckWindres checks if Windres is installed and if not, aborts
|
// CheckWindres checks if Windres is installed and if not, aborts
|
||||||
func CheckWindres() (err error) {
|
func CheckWindres() (err error) {
|
||||||
if runtime.GOOS != "windows" { // FIXME: Handle windows cross-compile for windows!
|
if runtime.GOOS != "windows" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
programHelper := NewProgramHelper()
|
programHelper := NewProgramHelper()
|
||||||
@@ -400,15 +194,6 @@ func CheckWindres() (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckIfInstalled returns if application is installed
|
|
||||||
func CheckIfInstalled(application string) (err error) {
|
|
||||||
programHelper := NewProgramHelper()
|
|
||||||
if !programHelper.IsInstalled(application) {
|
|
||||||
return fmt.Errorf("%s not installed. Ensure you have installed %s correctly", application, application)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// InstallFrontendDeps attempts to install the frontend dependencies based on the given options
|
// InstallFrontendDeps attempts to install the frontend dependencies based on the given options
|
||||||
func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forceRebuild bool, caller string) error {
|
func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forceRebuild bool, caller string) error {
|
||||||
|
|
||||||
@@ -419,14 +204,9 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if frontend deps have been updated
|
// Check if frontend deps have been updated
|
||||||
var feSpinner *spinner.Spinner
|
feSpinner := spinner.New("Ensuring frontend dependencies are up to date (This may take a while)")
|
||||||
if !projectOptions.Verbose {
|
feSpinner.SetSpinSpeed(50)
|
||||||
feSpinner = spinner.New("Ensuring frontend dependencies are up to date (This may take a while)")
|
feSpinner.Start()
|
||||||
feSpinner.SetSpinSpeed(50)
|
|
||||||
feSpinner.Start()
|
|
||||||
} else {
|
|
||||||
println("Ensuring frontend dependencies are up to date (This may take a while)")
|
|
||||||
}
|
|
||||||
|
|
||||||
requiresNPMInstall := true
|
requiresNPMInstall := true
|
||||||
|
|
||||||
@@ -439,15 +219,6 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
|
|||||||
|
|
||||||
const md5sumFile = "package.json.md5"
|
const md5sumFile = "package.json.md5"
|
||||||
|
|
||||||
// If node_modules does not exist, force a rebuild.
|
|
||||||
nodeModulesPath, err := filepath.Abs(filepath.Join(".", "node_modules"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !fs.DirExists(nodeModulesPath) {
|
|
||||||
forceRebuild = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we aren't forcing the install and the md5sum file exists
|
// If we aren't forcing the install and the md5sum file exists
|
||||||
if !forceRebuild && fs.FileExists(md5sumFile) {
|
if !forceRebuild && fs.FileExists(md5sumFile) {
|
||||||
// Yes - read contents
|
// Yes - read contents
|
||||||
@@ -458,11 +229,7 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
|
|||||||
if savedMD5sum == packageJSONMD5 {
|
if savedMD5sum == packageJSONMD5 {
|
||||||
// Same - no need for reinstall
|
// Same - no need for reinstall
|
||||||
requiresNPMInstall = false
|
requiresNPMInstall = false
|
||||||
if feSpinner != nil {
|
feSpinner.Success("Skipped frontend dependencies (-f to force rebuild)")
|
||||||
feSpinner.Success("Skipped frontend dependencies (-f to force rebuild)")
|
|
||||||
} else {
|
|
||||||
println("Skipped frontend dependencies (-f to force rebuild)")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -471,16 +238,12 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
|
|||||||
// Different? Build
|
// Different? Build
|
||||||
if requiresNPMInstall || forceRebuild {
|
if requiresNPMInstall || forceRebuild {
|
||||||
// Install dependencies
|
// Install dependencies
|
||||||
err = NewProgramHelper(projectOptions.Verbose).RunCommand(projectOptions.FrontEnd.Install)
|
err = NewProgramHelper().RunCommand(projectOptions.FrontEnd.Install)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if feSpinner != nil {
|
feSpinner.Error()
|
||||||
feSpinner.Error()
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if feSpinner != nil {
|
feSpinner.Success()
|
||||||
feSpinner.Success()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update md5sum file
|
// Update md5sum file
|
||||||
ioutil.WriteFile(md5sumFile, []byte(packageJSONMD5), 0644)
|
ioutil.WriteFile(md5sumFile, []byte(packageJSONMD5), 0644)
|
||||||
@@ -493,7 +256,7 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build frontend
|
// Build frontend
|
||||||
err = BuildFrontend(projectOptions)
|
err = BuildFrontend(projectOptions.FrontEnd.Build)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -512,7 +275,7 @@ func InstallRuntime(caller string, projectDir string, projectOptions *ProjectOpt
|
|||||||
// InstallBridge installs the relevant bridge javascript library
|
// InstallBridge installs the relevant bridge javascript library
|
||||||
func InstallBridge(projectDir string, projectOptions *ProjectOptions) error {
|
func InstallBridge(projectDir string, projectOptions *ProjectOptions) error {
|
||||||
bridgeFileData := mewn.String("../runtime/assets/bridge.js")
|
bridgeFileData := mewn.String("../runtime/assets/bridge.js")
|
||||||
bridgeFileTarget := filepath.Join(projectDir, projectOptions.FrontEnd.Dir, "node_modules", "@wailsapp", "runtime", "init.js")
|
bridgeFileTarget := filepath.Join(projectDir, projectOptions.FrontEnd.Dir, "node_modules", "@wailsapp", "runtime", "main.js")
|
||||||
err := fs.CreateFile(bridgeFileTarget, []byte(bridgeFileData))
|
err := fs.CreateFile(bridgeFileTarget, []byte(bridgeFileData))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -520,7 +283,7 @@ func InstallBridge(projectDir string, projectOptions *ProjectOptions) error {
|
|||||||
// InstallProdRuntime installs the production runtime
|
// InstallProdRuntime installs the production runtime
|
||||||
func InstallProdRuntime(projectDir string, projectOptions *ProjectOptions) error {
|
func InstallProdRuntime(projectDir string, projectOptions *ProjectOptions) error {
|
||||||
prodInit := mewn.String("../runtime/js/runtime/init.js")
|
prodInit := mewn.String("../runtime/js/runtime/init.js")
|
||||||
bridgeFileTarget := filepath.Join(projectDir, projectOptions.FrontEnd.Dir, "node_modules", "@wailsapp", "runtime", "init.js")
|
bridgeFileTarget := filepath.Join(projectDir, projectOptions.FrontEnd.Dir, "node_modules", "@wailsapp", "runtime", "main.js")
|
||||||
err := fs.CreateFile(bridgeFileTarget, []byte(prodInit))
|
err := fs.CreateFile(bridgeFileTarget, []byte(prodInit))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -532,7 +295,7 @@ func ServeProject(projectOptions *ProjectOptions, logger *Logger) error {
|
|||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
logger.Green(">>>>> To connect, you will need to run '" + projectOptions.FrontEnd.Serve + "' in the '" + projectOptions.FrontEnd.Dir + "' directory <<<<<")
|
logger.Green(">>>>> To connect, you will need to run '" + projectOptions.FrontEnd.Serve + "' in the '" + projectOptions.FrontEnd.Dir + "' directory <<<<<")
|
||||||
}()
|
}()
|
||||||
location, err := filepath.Abs(filepath.Join("build", projectOptions.BinaryName))
|
location, err := filepath.Abs(projectOptions.BinaryName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -548,33 +311,3 @@ func ServeProject(projectOptions *ProjectOptions, logger *Logger) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ldFlags(po *ProjectOptions, buildMode string) string {
|
|
||||||
// Setup ld flags
|
|
||||||
ldflags := "-w -s "
|
|
||||||
if buildMode == BuildModeDebug {
|
|
||||||
ldflags = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add windows flags
|
|
||||||
if po.Platform == "windows" && buildMode == BuildModeProd {
|
|
||||||
ldflags += "-H windowsgui "
|
|
||||||
}
|
|
||||||
|
|
||||||
ldflags += "-X github.com/wailsapp/wails.BuildMode=" + buildMode
|
|
||||||
|
|
||||||
// Add additional ldflags passed in via the `ldflags` cli flag
|
|
||||||
if len(po.LdFlags) > 0 {
|
|
||||||
ldflags += " " + po.LdFlags
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we wish to generate typescript
|
|
||||||
if po.typescriptDefsFilename != "" {
|
|
||||||
cwd, err := os.Getwd()
|
|
||||||
if err == nil {
|
|
||||||
filename := filepath.Join(cwd, po.FrontEnd.Dir, po.typescriptDefsFilename)
|
|
||||||
ldflags += " -X github.com/wailsapp/wails/lib/binding.typescriptDefinitionFilename=" + filename
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ldflags
|
|
||||||
}
|
|
||||||
|
|||||||
62
cmd/linux.go
62
cmd/linux.go
@@ -41,28 +41,6 @@ const (
|
|||||||
Elementary
|
Elementary
|
||||||
// Kali distribution
|
// Kali distribution
|
||||||
Kali
|
Kali
|
||||||
// Neon distribution
|
|
||||||
Neon
|
|
||||||
// ArcoLinux distribution
|
|
||||||
ArcoLinux
|
|
||||||
// Manjaro distribution
|
|
||||||
Manjaro
|
|
||||||
// ManjaroARM distribution
|
|
||||||
ManjaroARM
|
|
||||||
// Deepin distribution
|
|
||||||
Deepin
|
|
||||||
// Raspbian distribution
|
|
||||||
Raspbian
|
|
||||||
// Tumbleweed (OpenSUSE) distribution
|
|
||||||
Tumbleweed
|
|
||||||
// Leap (OpenSUSE) distribution
|
|
||||||
Leap
|
|
||||||
// ArchLabs distribution
|
|
||||||
ArchLabs
|
|
||||||
// PopOS distribution
|
|
||||||
PopOS
|
|
||||||
// Solus distribution
|
|
||||||
Solus
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// DistroInfo contains all the information relating to a linux distribution
|
// DistroInfo contains all the information relating to a linux distribution
|
||||||
@@ -111,14 +89,13 @@ func parseOsRelease(osRelease string) *DistroInfo {
|
|||||||
}
|
}
|
||||||
switch splitLine[0] {
|
switch splitLine[0] {
|
||||||
case "ID":
|
case "ID":
|
||||||
osID = strings.ToLower(strings.Trim(splitLine[1], "\""))
|
osID = strings.Trim(splitLine[1], "\"")
|
||||||
case "NAME":
|
case "NAME":
|
||||||
osNAME = strings.Trim(splitLine[1], "\"")
|
osNAME = strings.Trim(splitLine[1], "\"")
|
||||||
case "VERSION_ID":
|
case "VERSION_ID":
|
||||||
version = strings.Trim(splitLine[1], "\"")
|
version = strings.Trim(splitLine[1], "\"")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check distro name against list of distros
|
// Check distro name against list of distros
|
||||||
switch osID {
|
switch osID {
|
||||||
case "fedora":
|
case "fedora":
|
||||||
@@ -127,8 +104,6 @@ func parseOsRelease(osRelease string) *DistroInfo {
|
|||||||
result.Distribution = CentOS
|
result.Distribution = CentOS
|
||||||
case "arch":
|
case "arch":
|
||||||
result.Distribution = Arch
|
result.Distribution = Arch
|
||||||
case "archlabs":
|
|
||||||
result.Distribution = ArchLabs
|
|
||||||
case "debian":
|
case "debian":
|
||||||
result.Distribution = Debian
|
result.Distribution = Debian
|
||||||
case "ubuntu":
|
case "ubuntu":
|
||||||
@@ -147,26 +122,6 @@ func parseOsRelease(osRelease string) *DistroInfo {
|
|||||||
result.Distribution = Elementary
|
result.Distribution = Elementary
|
||||||
case "kali":
|
case "kali":
|
||||||
result.Distribution = Kali
|
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
|
|
||||||
case "opensuse-tumbleweed":
|
|
||||||
result.Distribution = Tumbleweed
|
|
||||||
case "opensuse-leap":
|
|
||||||
result.Distribution = Leap
|
|
||||||
case "pop":
|
|
||||||
result.Distribution = PopOS
|
|
||||||
case "solus":
|
|
||||||
result.Distribution = Solus
|
|
||||||
default:
|
default:
|
||||||
result.Distribution = Unknown
|
result.Distribution = Unknown
|
||||||
}
|
}
|
||||||
@@ -203,17 +158,6 @@ func DpkgInstalled(packageName string) (bool, error) {
|
|||||||
return exitCode == 0, nil
|
return exitCode == 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// EOpkgInstalled uses dpkg to see if a package is installed
|
|
||||||
func EOpkgInstalled(packageName string) (bool, error) {
|
|
||||||
program := NewProgramHelper()
|
|
||||||
eopkg := program.FindProgram("eopkg")
|
|
||||||
if eopkg == nil {
|
|
||||||
return false, fmt.Errorf("cannot check dependencies: eopkg not found")
|
|
||||||
}
|
|
||||||
stdout, _, _, _ := eopkg.Run("info", packageName)
|
|
||||||
return strings.HasPrefix(stdout, "Installed"), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PacmanInstalled uses pacman to see if a package is installed.
|
// PacmanInstalled uses pacman to see if a package is installed.
|
||||||
func PacmanInstalled(packageName string) (bool, error) {
|
func PacmanInstalled(packageName string) (bool, error) {
|
||||||
program := NewProgramHelper()
|
program := NewProgramHelper()
|
||||||
@@ -285,9 +229,5 @@ func RequestSupportForDistribution(distroInfo *DistroInfo) error {
|
|||||||
|
|
||||||
fmt.Println("Opening browser to file request.")
|
fmt.Println("Opening browser to file request.")
|
||||||
browser.OpenURL(fullURL + url.PathEscape(params))
|
browser.OpenURL(fullURL + url.PathEscape(params))
|
||||||
result = Prompt("We have a guide for adding support for your distribution. Would you like to view it?", "yes")
|
|
||||||
if strings.ToLower(result) == "yes" {
|
|
||||||
browser.OpenURL("https://wails.app/guides/distro/")
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,25 +22,5 @@ UBUNTU_CODENAME=bionic
|
|||||||
if result.Distribution != Ubuntu {
|
if result.Distribution != Ubuntu {
|
||||||
t.Errorf("expected 'Ubuntu' ID but got '%d'", result.Distribution)
|
t.Errorf("expected 'Ubuntu' ID but got '%d'", result.Distribution)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func TestTumbleweedDetection(t *testing.T) {
|
|
||||||
osrelease := `
|
|
||||||
NAME="openSUSE Tumbleweed"
|
|
||||||
# VERSION="20200414"
|
|
||||||
ID="opensuse-tumbleweed"
|
|
||||||
ID_LIKE="opensuse suse"
|
|
||||||
VERSION_ID="20200414"
|
|
||||||
PRETTY_NAME="openSUSE Tumbleweed"
|
|
||||||
ANSI_COLOR="0;32"
|
|
||||||
CPE_NAME="cpe:/o:opensuse:tumbleweed:20200414"
|
|
||||||
BUG_REPORT_URL="https://bugs.opensuse.org"
|
|
||||||
HOME_URL="https://www.opensuse.org/"
|
|
||||||
LOGO="distributor-logo"
|
|
||||||
`
|
|
||||||
|
|
||||||
result := parseOsRelease(osrelease)
|
|
||||||
if result.Distribution != Tumbleweed {
|
|
||||||
t.Errorf("expected 'Tumbleweed' ID but got '%d'", result.Distribution)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
|
"github.com/leaanthony/mewn"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -78,14 +79,11 @@ func (l *LinuxDB) GetDistro(distro string) *Distribution {
|
|||||||
// NewLinuxDB creates a new LinuxDB instance from the bundled
|
// NewLinuxDB creates a new LinuxDB instance from the bundled
|
||||||
// linuxdb.yaml file.
|
// linuxdb.yaml file.
|
||||||
func NewLinuxDB() *LinuxDB {
|
func NewLinuxDB() *LinuxDB {
|
||||||
data, err := fs.LoadRelativeFile("./linuxdb.yaml")
|
data := mewn.Bytes("./linuxdb.yaml")
|
||||||
if err != nil {
|
|
||||||
log.Fatal("Could not load linuxdb.yaml")
|
|
||||||
}
|
|
||||||
result := LinuxDB{
|
result := LinuxDB{
|
||||||
Distributions: make(map[string]*Distribution),
|
Distributions: make(map[string]*Distribution),
|
||||||
}
|
}
|
||||||
err = result.ImportData(data)
|
err := result.ImportData(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
127
cmd/linuxdb.yaml
127
cmd/linuxdb.yaml
@@ -28,15 +28,6 @@ distributions:
|
|||||||
gccversioncommand: &gccdumpfullversion -dumpfullversion
|
gccversioncommand: &gccdumpfullversion -dumpfullversion
|
||||||
programs: *debiandefaultprograms
|
programs: *debiandefaultprograms
|
||||||
libraries: *debiandefaultlibraries
|
libraries: *debiandefaultlibraries
|
||||||
pop:
|
|
||||||
id: pop
|
|
||||||
releases:
|
|
||||||
default:
|
|
||||||
version: default
|
|
||||||
name: Pop!_OS
|
|
||||||
gccversioncommand: &gccdumpfullversion -dumpfullversion
|
|
||||||
programs: *debiandefaultprograms
|
|
||||||
libraries: *debiandefaultlibraries
|
|
||||||
kali:
|
kali:
|
||||||
id: kali
|
id: kali
|
||||||
releases:
|
releases:
|
||||||
@@ -82,24 +73,6 @@ distributions:
|
|||||||
gccversioncommand: *gccdumpfullversion
|
gccversioncommand: *gccdumpfullversion
|
||||||
programs: *debiandefaultprograms
|
programs: *debiandefaultprograms
|
||||||
libraries: *debiandefaultlibraries
|
libraries: *debiandefaultlibraries
|
||||||
neon:
|
|
||||||
id: neon
|
|
||||||
releases:
|
|
||||||
default:
|
|
||||||
version: default
|
|
||||||
name: KDE neon
|
|
||||||
gccversioncommand: *gccdumpfullversion
|
|
||||||
programs: *debiandefaultprograms
|
|
||||||
libraries: *debiandefaultlibraries
|
|
||||||
deepin:
|
|
||||||
id: deepin
|
|
||||||
releases:
|
|
||||||
default:
|
|
||||||
version: default
|
|
||||||
name: Deepin
|
|
||||||
gccversioncommand: *gccdumpfullversion
|
|
||||||
programs: *debiandefaultprograms
|
|
||||||
libraries: *debiandefaultlibraries
|
|
||||||
void:
|
void:
|
||||||
id: void
|
id: void
|
||||||
releases:
|
releases:
|
||||||
@@ -164,54 +137,18 @@ distributions:
|
|||||||
version: default
|
version: default
|
||||||
name: Arch Linux
|
name: Arch Linux
|
||||||
gccversioncommand: *gccdumpversion
|
gccversioncommand: *gccdumpversion
|
||||||
programs: &archdefaultprograms
|
programs:
|
||||||
- name: gcc
|
- name: gcc
|
||||||
help: Please install with `sudo pacman -S gcc` and try again
|
help: Please install with `sudo pacman -S gcc` and try again
|
||||||
- name: pkgconf
|
- name: pkgconf
|
||||||
help: Please install with `sudo pacman -S pkgconf` and try again
|
help: Please install with `sudo pacman -S pkgconf` and try again
|
||||||
- name: npm
|
- name: npm
|
||||||
help: Please install with `sudo pacman -S npm` and try again
|
help: Please install with `sudo pacman -S npm` and try again
|
||||||
libraries: &archdefaultlibraries
|
libraries:
|
||||||
- name: gtk3
|
- name: gtk3
|
||||||
help: Please install with `sudo pacman -S gtk3` and try again
|
help: Please install with `sudo pacman -S gtk3` and try again
|
||||||
- name: webkit2gtk
|
- name: webkit2gtk
|
||||||
help: Please install with `sudo pacman -S webkit2gtk` and try again
|
help: Please install with `sudo pacman -S webkit2gtk` and try again
|
||||||
arcolinux:
|
|
||||||
id: arcolinux
|
|
||||||
releases:
|
|
||||||
default:
|
|
||||||
version: default
|
|
||||||
name: ArcoLinux
|
|
||||||
gccversioncommand: *gccdumpversion
|
|
||||||
programs: *archdefaultprograms
|
|
||||||
libraries: *archdefaultlibraries
|
|
||||||
archlabs:
|
|
||||||
id: archlabs
|
|
||||||
releases:
|
|
||||||
default:
|
|
||||||
version: default
|
|
||||||
name: ArchLabs
|
|
||||||
gccversioncommand: *gccdumpversion
|
|
||||||
programs: *archdefaultprograms
|
|
||||||
libraries: *archdefaultlibraries
|
|
||||||
manjaro:
|
|
||||||
id: manjaro
|
|
||||||
releases:
|
|
||||||
default:
|
|
||||||
version: default
|
|
||||||
name: Manjaro Linux
|
|
||||||
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:
|
gentoo:
|
||||||
id: gentoo
|
id: gentoo
|
||||||
releases:
|
releases:
|
||||||
@@ -230,62 +167,4 @@ distributions:
|
|||||||
- name: gtk+:3
|
- name: gtk+:3
|
||||||
help: Please install with `sudo emerge gtk+:3` and try again
|
help: Please install with `sudo emerge gtk+:3` and try again
|
||||||
- name: webkit-gtk
|
- 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
|
|
||||||
solus:
|
|
||||||
id: solus
|
|
||||||
releases:
|
|
||||||
default:
|
|
||||||
version: default
|
|
||||||
name: Solus
|
|
||||||
gccversioncommand: *gccdumpfullversion
|
|
||||||
programs: &solusdefaultprograms
|
|
||||||
- name: gcc
|
|
||||||
help: Please install with `sudo eopkg it -c system.devel` and try again
|
|
||||||
- name: pkg-config
|
|
||||||
help: Please install with `sudo eopkg it -c system.devel` and try again
|
|
||||||
- name: npm
|
|
||||||
help: Please install with `sudo eopkg it nodejs` and try again
|
|
||||||
libraries: &solusdefaultlibraries
|
|
||||||
- name: libgtk-3-devel
|
|
||||||
help: Please install with `sudo eopkg it libgtk-3-devel` and try again
|
|
||||||
- name: libwebkit-gtk-devel
|
|
||||||
help: Please install with `sudo eopkg it libwebkit-gtk-devel` and try again
|
|
||||||
|
|
||||||
opensuse-tumbleweed:
|
|
||||||
id: opensuse-tumbleweed
|
|
||||||
releases:
|
|
||||||
default:
|
|
||||||
version: default
|
|
||||||
name: openSUSE Tumbleweed
|
|
||||||
gccversioncommand: *gccdumpfullversion
|
|
||||||
programs: &opensusedefaultprograms
|
|
||||||
- name: gcc
|
|
||||||
help: Please install with `sudo zypper in gcc-c++` and try again
|
|
||||||
- name: pkg-config
|
|
||||||
help: Please install with `sudo zypper in pkgconf-pkg-config` and try again
|
|
||||||
- name: npm
|
|
||||||
help: Please install `sudo zypper in nodejs` and try again
|
|
||||||
libraries: &opensusedefaultlibraries
|
|
||||||
- name: gtk3-devel
|
|
||||||
help: Please install with `sudo zypper in gtk3-devel` and try again
|
|
||||||
- name: webkit2gtk3-devel
|
|
||||||
help: Please install with `sudo zypper in webkit2gtk3-devel` and try again
|
|
||||||
opensuse-leap:
|
|
||||||
id: opensuse-leap
|
|
||||||
releases:
|
|
||||||
default:
|
|
||||||
version: default
|
|
||||||
name: openSUSE Leap
|
|
||||||
gccversioncommand: *gccdumpfullversion
|
|
||||||
programs: *opensusedefaultprograms
|
|
||||||
libraries: *opensusedefaultlibraries
|
|
||||||
289
cmd/package.go
289
cmd/package.go
@@ -1,12 +1,9 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"image/png"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
@@ -17,24 +14,21 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jackmordaunt/icns"
|
"github.com/jackmordaunt/icns"
|
||||||
"golang.org/x/image/draw"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// PackageHelper helps with the 'wails package' command
|
// PackageHelper helps with the 'wails package' command
|
||||||
type PackageHelper struct {
|
type PackageHelper struct {
|
||||||
platform string
|
fs *FSHelper
|
||||||
fs *FSHelper
|
log *Logger
|
||||||
log *Logger
|
system *SystemHelper
|
||||||
system *SystemHelper
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPackageHelper creates a new PackageHelper!
|
// NewPackageHelper creates a new PackageHelper!
|
||||||
func NewPackageHelper(platform string) *PackageHelper {
|
func NewPackageHelper() *PackageHelper {
|
||||||
return &PackageHelper{
|
return &PackageHelper{
|
||||||
platform: platform,
|
fs: NewFSHelper(),
|
||||||
fs: NewFSHelper(),
|
log: NewLogger(),
|
||||||
log: NewLogger(),
|
system: NewSystemHelper(),
|
||||||
system: NewSystemHelper(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,111 +53,6 @@ func newPlistData(title, exe, packageID, version, author string) *plistData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type windowsIcoHeader struct {
|
|
||||||
_ uint16
|
|
||||||
imageType uint16
|
|
||||||
imageCount uint16
|
|
||||||
}
|
|
||||||
|
|
||||||
type windowsIcoDescriptor struct {
|
|
||||||
width uint8
|
|
||||||
height uint8
|
|
||||||
colours uint8
|
|
||||||
_ uint8
|
|
||||||
planes uint16
|
|
||||||
bpp uint16
|
|
||||||
size uint32
|
|
||||||
offset uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type windowsIcoContainer struct {
|
|
||||||
Header windowsIcoDescriptor
|
|
||||||
Data []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateWindowsIcon(pngFilename string, iconfile string) error {
|
|
||||||
sizes := []int{256, 128, 64, 48, 32, 16}
|
|
||||||
|
|
||||||
pngfile, err := os.Open(pngFilename)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer pngfile.Close()
|
|
||||||
|
|
||||||
pngdata, err := png.Decode(pngfile)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
icons := []windowsIcoContainer{}
|
|
||||||
|
|
||||||
for _, size := range sizes {
|
|
||||||
rect := image.Rect(0, 0, int(size), int(size))
|
|
||||||
rawdata := image.NewRGBA(rect)
|
|
||||||
scale := draw.CatmullRom
|
|
||||||
scale.Scale(rawdata, rect, pngdata, pngdata.Bounds(), draw.Over, nil)
|
|
||||||
|
|
||||||
icondata := new(bytes.Buffer)
|
|
||||||
writer := bufio.NewWriter(icondata)
|
|
||||||
err = png.Encode(writer, rawdata)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
writer.Flush()
|
|
||||||
|
|
||||||
imgSize := size
|
|
||||||
if imgSize >= 256 {
|
|
||||||
imgSize = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
data := icondata.Bytes()
|
|
||||||
|
|
||||||
icn := windowsIcoContainer{
|
|
||||||
Header: windowsIcoDescriptor{
|
|
||||||
width: uint8(imgSize),
|
|
||||||
height: uint8(imgSize),
|
|
||||||
planes: 1,
|
|
||||||
bpp: 32,
|
|
||||||
size: uint32(len(data)),
|
|
||||||
},
|
|
||||||
Data: data,
|
|
||||||
}
|
|
||||||
icons = append(icons, icn)
|
|
||||||
}
|
|
||||||
|
|
||||||
outfile, err := os.Create(iconfile)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer outfile.Close()
|
|
||||||
|
|
||||||
ico := windowsIcoHeader{
|
|
||||||
imageType: 1,
|
|
||||||
imageCount: uint16(len(sizes)),
|
|
||||||
}
|
|
||||||
err = binary.Write(outfile, binary.LittleEndian, ico)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
offset := uint32(6 + 16*len(sizes))
|
|
||||||
for _, icon := range icons {
|
|
||||||
icon.Header.offset = offset
|
|
||||||
err = binary.Write(outfile, binary.LittleEndian, icon.Header)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
offset += icon.Header.size
|
|
||||||
}
|
|
||||||
for _, icon := range icons {
|
|
||||||
_, err = outfile.Write(icon.Data)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func defaultString(val string, defaultVal string) string {
|
func defaultString(val string, defaultVal string) string {
|
||||||
if val != "" {
|
if val != "" {
|
||||||
return val
|
return val
|
||||||
@@ -174,30 +63,29 @@ func defaultString(val string, defaultVal string) string {
|
|||||||
func (b *PackageHelper) getPackageFileBaseDir() string {
|
func (b *PackageHelper) getPackageFileBaseDir() string {
|
||||||
// Calculate template base dir
|
// Calculate template base dir
|
||||||
_, filename, _, _ := runtime.Caller(1)
|
_, filename, _, _ := runtime.Caller(1)
|
||||||
return filepath.Join(path.Dir(filename), "packages", b.platform)
|
return filepath.Join(path.Dir(filename), "packages", runtime.GOOS)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Package the application into a platform specific package
|
// Package the application into a platform specific package
|
||||||
func (b *PackageHelper) Package(po *ProjectOptions) error {
|
func (b *PackageHelper) Package(po *ProjectOptions) error {
|
||||||
switch b.platform {
|
switch runtime.GOOS {
|
||||||
case "darwin":
|
case "darwin":
|
||||||
|
// Check we have the exe
|
||||||
|
if !b.fs.FileExists(po.BinaryName) {
|
||||||
|
return fmt.Errorf("cannot bundle non-existent binary file '%s'. Please build with 'wails build' first", po.BinaryName)
|
||||||
|
}
|
||||||
return b.packageOSX(po)
|
return b.packageOSX(po)
|
||||||
case "windows":
|
case "windows":
|
||||||
return b.PackageWindows(po, true)
|
return b.PackageWindows(po, false)
|
||||||
case "linux":
|
case "linux":
|
||||||
return b.packageLinux(po)
|
return fmt.Errorf("linux is not supported at this time. Please see https://github.com/wailsapp/wails/issues/2")
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("platform '%s' not supported for bundling yet", b.platform)
|
return fmt.Errorf("platform '%s' not supported for bundling yet", runtime.GOOS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *PackageHelper) packageLinux(po *ProjectOptions) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Package the application for OSX
|
// Package the application for OSX
|
||||||
func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
|
func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
|
||||||
build := path.Join(b.fs.Cwd(), "build")
|
|
||||||
|
|
||||||
system := NewSystemHelper()
|
system := NewSystemHelper()
|
||||||
config, err := system.LoadConfig()
|
config, err := system.LoadConfig()
|
||||||
@@ -212,68 +100,39 @@ func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
|
|||||||
packageID := strings.Join([]string{"wails", name, version}, ".")
|
packageID := strings.Join([]string{"wails", name, version}, ".")
|
||||||
plistData := newPlistData(name, exe, packageID, version, author)
|
plistData := newPlistData(name, exe, packageID, version, author)
|
||||||
appname := po.Name + ".app"
|
appname := po.Name + ".app"
|
||||||
plistFilename := path.Join(build, appname, "Contents", "Info.plist")
|
|
||||||
customPlist := path.Join(b.fs.Cwd(), "info.plist")
|
|
||||||
|
|
||||||
// Check binary exists
|
// Check binary exists
|
||||||
source := path.Join(build, exe)
|
source := path.Join(b.fs.Cwd(), exe)
|
||||||
if po.CrossCompile == true {
|
|
||||||
file, err := b.fs.FindFile(build, "darwin")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
source = path.Join(build, file)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !b.fs.FileExists(source) {
|
if !b.fs.FileExists(source) {
|
||||||
// We need to build!
|
// We need to build!
|
||||||
return fmt.Errorf("Target '%s' not available. Has it been compiled yet?", source)
|
return fmt.Errorf("Target '%s' not available. Has it been compiled yet?", exe)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the existing package
|
// Remove the existing package
|
||||||
os.RemoveAll(appname)
|
os.RemoveAll(appname)
|
||||||
|
|
||||||
// Create directories
|
exeDir := path.Join(b.fs.Cwd(), appname, "/Contents/MacOS")
|
||||||
exeDir := path.Join(build, appname, "/Contents/MacOS")
|
|
||||||
b.fs.MkDirs(exeDir, 0755)
|
b.fs.MkDirs(exeDir, 0755)
|
||||||
resourceDir := path.Join(build, appname, "/Contents/Resources")
|
resourceDir := path.Join(b.fs.Cwd(), appname, "/Contents/Resources")
|
||||||
b.fs.MkDirs(resourceDir, 0755)
|
b.fs.MkDirs(resourceDir, 0755)
|
||||||
|
tmpl := template.New("infoPlist")
|
||||||
|
plistFile := filepath.Join(b.getPackageFileBaseDir(), "info.plist")
|
||||||
|
infoPlist, err := ioutil.ReadFile(plistFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tmpl.Parse(string(infoPlist))
|
||||||
|
|
||||||
// Do we have a custom plist in the project directory?
|
// Write the template to a buffer
|
||||||
if !fs.FileExists(customPlist) {
|
var tpl bytes.Buffer
|
||||||
|
err = tmpl.Execute(&tpl, plistData)
|
||||||
// No - create a new plist from our defaults
|
if err != nil {
|
||||||
tmpl := template.New("infoPlist")
|
return err
|
||||||
plistFile := filepath.Join(b.getPackageFileBaseDir(), "info.plist")
|
}
|
||||||
infoPlist, err := ioutil.ReadFile(plistFile)
|
filename := path.Join(b.fs.Cwd(), appname, "Contents", "Info.plist")
|
||||||
if err != nil {
|
err = ioutil.WriteFile(filename, tpl.Bytes(), 0644)
|
||||||
return err
|
if err != nil {
|
||||||
}
|
return err
|
||||||
tmpl.Parse(string(infoPlist))
|
|
||||||
|
|
||||||
// Write the template to a buffer
|
|
||||||
var tpl bytes.Buffer
|
|
||||||
err = tmpl.Execute(&tpl, plistData)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save to the package
|
|
||||||
err = ioutil.WriteFile(plistFilename, tpl.Bytes(), 0644)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Also write to project directory for customisation
|
|
||||||
err = ioutil.WriteFile(customPlist, tpl.Bytes(), 0644)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Yes - we have a plist. Copy it to the package verbatim
|
|
||||||
err = fs.CopyFile(customPlist, plistFilename)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy executable
|
// Copy executable
|
||||||
@@ -291,37 +150,22 @@ func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// CleanWindows removes any windows related files found in the directory
|
|
||||||
func (b *PackageHelper) CleanWindows(po *ProjectOptions) {
|
|
||||||
pdir := b.fs.Cwd()
|
|
||||||
basename := strings.TrimSuffix(po.BinaryName, ".exe")
|
|
||||||
exts := []string{".ico", ".exe.manifest", ".rc", "-res.syso"}
|
|
||||||
rsrcs := []string{}
|
|
||||||
for _, ext := range exts {
|
|
||||||
rsrcs = append(rsrcs, filepath.Join(pdir, basename+ext))
|
|
||||||
}
|
|
||||||
b.fs.RemoveFiles(rsrcs, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PackageWindows packages the application for windows platforms
|
// PackageWindows packages the application for windows platforms
|
||||||
func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
|
func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
|
||||||
outputDir := b.fs.Cwd()
|
|
||||||
basename := strings.TrimSuffix(po.BinaryName, ".exe")
|
basename := strings.TrimSuffix(po.BinaryName, ".exe")
|
||||||
|
|
||||||
// Copy default icon if needed
|
// Copy icon
|
||||||
icon, err := b.copyIcon()
|
tgtIconFile := filepath.Join(b.fs.Cwd(), basename+".ico")
|
||||||
if err != nil {
|
if !b.fs.FileExists(tgtIconFile) {
|
||||||
return err
|
srcIconfile := filepath.Join(b.getPackageFileBaseDir(), "wails.ico")
|
||||||
}
|
err := b.fs.CopyFile(srcIconfile, tgtIconFile)
|
||||||
|
if err != nil {
|
||||||
// Generate icon from PNG
|
return err
|
||||||
err = generateWindowsIcon(icon, basename+".ico")
|
}
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy manifest
|
// Copy manifest
|
||||||
tgtManifestFile := filepath.Join(outputDir, basename+".exe.manifest")
|
tgtManifestFile := filepath.Join(b.fs.Cwd(), basename+".exe.manifest")
|
||||||
if !b.fs.FileExists(tgtManifestFile) {
|
if !b.fs.FileExists(tgtManifestFile) {
|
||||||
srcManifestfile := filepath.Join(b.getPackageFileBaseDir(), "wails.exe.manifest")
|
srcManifestfile := filepath.Join(b.getPackageFileBaseDir(), "wails.exe.manifest")
|
||||||
err := b.fs.CopyFile(srcManifestfile, tgtManifestFile)
|
err := b.fs.CopyFile(srcManifestfile, tgtManifestFile)
|
||||||
@@ -331,7 +175,7 @@ func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copy rc file
|
// Copy rc file
|
||||||
tgtRCFile := filepath.Join(outputDir, basename+".rc")
|
tgtRCFile := filepath.Join(b.fs.Cwd(), basename+".rc")
|
||||||
if !b.fs.FileExists(tgtRCFile) {
|
if !b.fs.FileExists(tgtRCFile) {
|
||||||
srcRCfile := filepath.Join(b.getPackageFileBaseDir(), "wails.rc")
|
srcRCfile := filepath.Join(b.getPackageFileBaseDir(), "wails.rc")
|
||||||
rcfilebytes, err := ioutil.ReadFile(srcRCfile)
|
rcfilebytes, err := ioutil.ReadFile(srcRCfile)
|
||||||
@@ -346,37 +190,26 @@ func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build syso
|
// Build syso
|
||||||
sysofile := filepath.Join(outputDir, basename+"-res.syso")
|
sysofile := filepath.Join(b.fs.Cwd(), basename+"-res.syso")
|
||||||
|
windresCommand := []string{"windres", "-o", sysofile, tgtRCFile}
|
||||||
|
err := NewProgramHelper().RunCommandArray(windresCommand)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// cross-compile
|
// clean up
|
||||||
if b.platform != runtime.GOOS {
|
if cleanUp {
|
||||||
args := []string{
|
filesToDelete := []string{tgtIconFile, tgtManifestFile, tgtRCFile, sysofile}
|
||||||
"docker", "run", "--rm",
|
err := b.fs.RemoveFiles(filesToDelete)
|
||||||
"-v", outputDir + ":/build",
|
|
||||||
"--entrypoint", "/bin/sh",
|
|
||||||
"wailsapp/xgo:latest",
|
|
||||||
"-c", "/usr/bin/x86_64-w64-mingw32-windres -o /build/" + basename + "-res.syso /build/" + basename + ".rc",
|
|
||||||
}
|
|
||||||
if err := NewProgramHelper().RunCommandArray(args); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
batfile, err := fs.LocalDir(".")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
windresBatFile := filepath.Join(batfile.fullPath, "windres.bat")
|
|
||||||
windresCommand := []string{windresBatFile, sysofile, tgtRCFile}
|
|
||||||
err = NewProgramHelper().RunCommandArray(windresCommand)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *PackageHelper) copyIcon() (string, error) {
|
func (b *PackageHelper) copyIcon(resourceDir string) (string, error) {
|
||||||
|
|
||||||
// TODO: Read this from project.json
|
// TODO: Read this from project.json
|
||||||
const appIconFilename = "appicon.png"
|
const appIconFilename = "appicon.png"
|
||||||
@@ -401,7 +234,7 @@ func (b *PackageHelper) copyIcon() (string, error) {
|
|||||||
|
|
||||||
func (b *PackageHelper) packageIconOSX(resourceDir string) error {
|
func (b *PackageHelper) packageIconOSX(resourceDir string) error {
|
||||||
|
|
||||||
srcIcon, err := b.copyIcon()
|
srcIcon, err := b.copyIcon(resourceDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0"><dict>
|
<plist version="1.0"><dict>
|
||||||
<key>CFBundlePackageType</key><string>APPL</string>
|
|
||||||
<key>CFBundleName</key><string>{{.Title}}</string>
|
<key>CFBundleName</key><string>{{.Title}}</string>
|
||||||
<key>CFBundleExecutable</key><string>{{.Exe}}</string>
|
<key>CFBundleExecutable</key><string>{{.Exe}}</string>
|
||||||
<key>CFBundleIdentifier</key><string>{{.PackageID}}</string>
|
<key>CFBundleIdentifier</key><string>{{.PackageID}}</string>
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
100 ICON "$NAME$.ico"
|
100 ICON "$NAME$.ico"
|
||||||
110 24 "$NAME$.exe.manifest"
|
100 24 "$NAME$.exe.manifest"
|
||||||
@@ -3,7 +3,6 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -12,22 +11,14 @@ import (
|
|||||||
|
|
||||||
// ProgramHelper - Utility functions around installed applications
|
// ProgramHelper - Utility functions around installed applications
|
||||||
type ProgramHelper struct {
|
type ProgramHelper struct {
|
||||||
shell *ShellHelper
|
shell *ShellHelper
|
||||||
verbose bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewProgramHelper - Creates a new ProgramHelper
|
// NewProgramHelper - Creates a new ProgramHelper
|
||||||
func NewProgramHelper(verbose ...bool) *ProgramHelper {
|
func NewProgramHelper() *ProgramHelper {
|
||||||
result := &ProgramHelper{
|
return &ProgramHelper{
|
||||||
shell: NewShellHelper(),
|
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
|
// IsInstalled tries to determine if the given binary name is installed
|
||||||
@@ -38,9 +29,8 @@ func (p *ProgramHelper) IsInstalled(programName string) bool {
|
|||||||
|
|
||||||
// Program - A struct to define an installed application/binary
|
// Program - A struct to define an installed application/binary
|
||||||
type Program struct {
|
type Program struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
verbose bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindProgram attempts to find the given program on the system.FindProgram
|
// FindProgram attempts to find the given program on the system.FindProgram
|
||||||
@@ -55,9 +45,8 @@ func (p *ProgramHelper) FindProgram(programName string) *Program {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &Program{
|
return &Program{
|
||||||
Name: programName,
|
Name: programName,
|
||||||
Path: path,
|
Path: path,
|
||||||
verbose: p.verbose,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,18 +63,12 @@ func (p *Program) Run(vars ...string) (stdout, stderr string, exitCode int, err
|
|||||||
return "", "", 1, err
|
return "", "", 1, err
|
||||||
}
|
}
|
||||||
cmd := exec.Command(command, vars...)
|
cmd := exec.Command(command, vars...)
|
||||||
if !p.verbose {
|
var stdo, stde bytes.Buffer
|
||||||
var stdo, stde bytes.Buffer
|
cmd.Stdout = &stdo
|
||||||
cmd.Stdout = &stdo
|
cmd.Stderr = &stde
|
||||||
cmd.Stderr = &stde
|
err = cmd.Run()
|
||||||
err = cmd.Run()
|
stdout = string(stdo.Bytes())
|
||||||
stdout = string(stdo.Bytes())
|
stderr = string(stde.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
|
// https://stackoverflow.com/questions/10385551/get-exit-code-go
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -117,19 +100,6 @@ func (p *ProgramHelper) InstallGoPackage(packageName string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// InstallNPMPackage installs the given npm package
|
|
||||||
func (p *ProgramHelper) InstallNPMPackage(packageName string, save bool) error {
|
|
||||||
args := strings.Split("install "+packageName, " ")
|
|
||||||
if save {
|
|
||||||
args = append(args, "--save")
|
|
||||||
}
|
|
||||||
_, stderr, err := p.shell.Run("npm", args...)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(stderr)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// RunCommand runs the given command
|
// RunCommand runs the given command
|
||||||
func (p *ProgramHelper) RunCommand(command string) error {
|
func (p *ProgramHelper) RunCommand(command string) error {
|
||||||
args := strings.Split(command, " ")
|
args := strings.Split(command, " ")
|
||||||
@@ -138,14 +108,13 @@ func (p *ProgramHelper) RunCommand(command string) error {
|
|||||||
|
|
||||||
// RunCommandArray runs the command specified in the array
|
// RunCommandArray runs the command specified in the array
|
||||||
func (p *ProgramHelper) RunCommandArray(args []string, dir ...string) error {
|
func (p *ProgramHelper) RunCommandArray(args []string, dir ...string) error {
|
||||||
programCommand := args[0]
|
program := args[0]
|
||||||
// TODO: Run FindProgram here and get the full path to the exe
|
// TODO: Run FindProgram here and get the full path to the exe
|
||||||
program, err := exec.LookPath(programCommand)
|
program, err := exec.LookPath(program)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("ERROR: Looks like '%s' isn't installed. Please install and try again.", programCommand)
|
fmt.Printf("ERROR: Looks like '%s' isn't installed. Please install and try again.", program)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
args = args[1:]
|
args = args[1:]
|
||||||
var stderr string
|
var stderr string
|
||||||
var stdout string
|
var stdout string
|
||||||
|
|||||||
@@ -6,24 +6,13 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/leaanthony/slicer"
|
"github.com/leaanthony/slicer"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PackageManager indicates different package managers
|
|
||||||
type PackageManager int
|
|
||||||
|
|
||||||
const (
|
|
||||||
// UNKNOWN package manager
|
|
||||||
UNKNOWN PackageManager = iota
|
|
||||||
// NPM package manager
|
|
||||||
NPM
|
|
||||||
// YARN package manager
|
|
||||||
YARN
|
|
||||||
)
|
|
||||||
|
|
||||||
type author struct {
|
type author struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
@@ -141,27 +130,21 @@ func (ph *ProjectHelper) NewProjectOptions() *ProjectOptions {
|
|||||||
|
|
||||||
// ProjectOptions holds all the options available for a project
|
// ProjectOptions holds all the options available for a project
|
||||||
type ProjectOptions struct {
|
type ProjectOptions struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
Author *author `json:"author,omitempty"`
|
Author *author `json:"author,omitempty"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
OutputDirectory string `json:"-"`
|
OutputDirectory string `json:"-"`
|
||||||
UseDefaults bool `json:"-"`
|
UseDefaults bool `json:"-"`
|
||||||
Template string `json:"-"`
|
Template string `json:"-"`
|
||||||
BinaryName string `json:"binaryname"`
|
BinaryName string `json:"binaryname"`
|
||||||
FrontEnd *frontend `json:"frontend,omitempty"`
|
FrontEnd *frontend `json:"frontend,omitempty"`
|
||||||
NPMProjectName string `json:"-"`
|
NPMProjectName string `json:"-"`
|
||||||
system *SystemHelper
|
system *SystemHelper
|
||||||
log *Logger
|
log *Logger
|
||||||
templates *TemplateHelper
|
templates *TemplateHelper
|
||||||
selectedTemplate *TemplateDetails
|
selectedTemplate *TemplateDetails
|
||||||
WailsVersion string
|
WailsVersion string
|
||||||
typescriptDefsFilename string
|
|
||||||
Verbose bool `json:"-"`
|
|
||||||
CrossCompile bool
|
|
||||||
Platform string
|
|
||||||
Architecture string
|
|
||||||
LdFlags string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defaults sets the default project template
|
// Defaults sets the default project template
|
||||||
@@ -170,28 +153,6 @@ func (po *ProjectOptions) Defaults() {
|
|||||||
po.WailsVersion = Version
|
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 {
|
|
||||||
return UNKNOWN, fmt.Errorf("No frontend specified in project options")
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.Index(po.FrontEnd.Install, "npm") > -1 {
|
|
||||||
return NPM, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.Index(po.FrontEnd.Install, "yarn") > -1 {
|
|
||||||
return YARN, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return UNKNOWN, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PromptForInputs asks the user to input project details
|
// PromptForInputs asks the user to input project details
|
||||||
func (po *ProjectOptions) PromptForInputs() error {
|
func (po *ProjectOptions) PromptForInputs() error {
|
||||||
|
|
||||||
@@ -336,6 +297,11 @@ func processBinaryName(po *ProjectOptions) {
|
|||||||
if po.BinaryName == "" {
|
if po.BinaryName == "" {
|
||||||
var binaryNameComputed = computeBinaryName(po.Name)
|
var binaryNameComputed = computeBinaryName(po.Name)
|
||||||
po.BinaryName = Prompt("The output binary name", binaryNameComputed)
|
po.BinaryName = Prompt("The output binary name", binaryNameComputed)
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
if !strings.HasSuffix(po.BinaryName, ".exe") {
|
||||||
|
po.BinaryName += ".exe"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fmt.Println("Output binary Name: " + po.BinaryName)
|
fmt.Println("Output binary Name: " + po.BinaryName)
|
||||||
}
|
}
|
||||||
|
|||||||
42
cmd/shell.go
42
cmd/shell.go
@@ -8,7 +8,6 @@ import (
|
|||||||
|
|
||||||
// ShellHelper helps with Shell commands
|
// ShellHelper helps with Shell commands
|
||||||
type ShellHelper struct {
|
type ShellHelper struct {
|
||||||
verbose bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewShellHelper creates a new ShellHelper!
|
// NewShellHelper creates a new ShellHelper!
|
||||||
@@ -16,27 +15,16 @@ func NewShellHelper() *ShellHelper {
|
|||||||
return &ShellHelper{}
|
return &ShellHelper{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetVerbose sets the verbose flag
|
|
||||||
func (sh *ShellHelper) SetVerbose() {
|
|
||||||
sh.verbose = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the given command
|
// Run the given command
|
||||||
func (sh *ShellHelper) Run(command string, vars ...string) (stdout, stderr string, err error) {
|
func (sh *ShellHelper) Run(command string, vars ...string) (stdout, stderr string, err error) {
|
||||||
cmd := exec.Command(command, vars...)
|
cmd := exec.Command(command, vars...)
|
||||||
cmd.Env = append(os.Environ(), "GO111MODULE=on")
|
cmd.Env = append(os.Environ(), "GO111MODULE=on")
|
||||||
if !sh.verbose {
|
var stdo, stde bytes.Buffer
|
||||||
var stdo, stde bytes.Buffer
|
cmd.Stdout = &stdo
|
||||||
cmd.Stdout = &stdo
|
cmd.Stderr = &stde
|
||||||
cmd.Stderr = &stde
|
err = cmd.Run()
|
||||||
err = cmd.Run()
|
stdout = string(stdo.Bytes())
|
||||||
stdout = string(stdo.Bytes())
|
stderr = string(stde.Bytes())
|
||||||
stderr = string(stde.Bytes())
|
|
||||||
} else {
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
err = cmd.Run()
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,17 +33,11 @@ func (sh *ShellHelper) RunInDirectory(dir string, command string, vars ...string
|
|||||||
cmd := exec.Command(command, vars...)
|
cmd := exec.Command(command, vars...)
|
||||||
cmd.Dir = dir
|
cmd.Dir = dir
|
||||||
cmd.Env = append(os.Environ(), "GO111MODULE=on")
|
cmd.Env = append(os.Environ(), "GO111MODULE=on")
|
||||||
if !sh.verbose {
|
var stdo, stde bytes.Buffer
|
||||||
var stdo, stde bytes.Buffer
|
cmd.Stdout = &stdo
|
||||||
cmd.Stdout = &stdo
|
cmd.Stderr = &stde
|
||||||
cmd.Stderr = &stde
|
err = cmd.Run()
|
||||||
err = cmd.Run()
|
stdout = string(stdo.Bytes())
|
||||||
stdout = string(stdo.Bytes())
|
stderr = string(stde.Bytes())
|
||||||
stderr = string(stde.Bytes())
|
|
||||||
} else {
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
err = cmd.Run()
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
homedir "github.com/mitchellh/go-homedir"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SystemHelper - Defines everything related to the system
|
// SystemHelper - Defines everything related to the system
|
||||||
@@ -37,11 +38,10 @@ func NewSystemHelper() *SystemHelper {
|
|||||||
// setSystemDirs calculates the system directories it is interested in
|
// setSystemDirs calculates the system directories it is interested in
|
||||||
func (s *SystemHelper) setSystemDirs() {
|
func (s *SystemHelper) setSystemDirs() {
|
||||||
var err error
|
var err error
|
||||||
s.homeDir, err = os.UserHomeDir()
|
s.homeDir, err = homedir.Dir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Cannot find home directory! Please file a bug report!")
|
log.Fatal("Cannot find home directory! Please file a bug report!")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: A better config system
|
// TODO: A better config system
|
||||||
s.wailsSystemDir = filepath.Join(s.homeDir, ".wails")
|
s.wailsSystemDir = filepath.Join(s.homeDir, ".wails")
|
||||||
s.wailsSystemConfig = filepath.Join(s.wailsSystemDir, s.configFilename)
|
s.wailsSystemConfig = filepath.Join(s.wailsSystemDir, s.configFilename)
|
||||||
@@ -132,7 +132,7 @@ func (s *SystemHelper) setup() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const introText = `
|
const introText = `
|
||||||
Wails is a lightweight framework for creating web-like desktop apps in Go.
|
Wails is a lightweight framework for creating web-like desktop apps in Go.
|
||||||
I'll need to ask you a few questions so I can fill in your project templates and then I will try and see if you have the correct dependencies installed. If you don't have the right tools installed, I'll try and suggest how to install them.
|
I'll need to ask you a few questions so I can fill in your project templates and then I will try and see if you have the correct dependencies installed. If you don't have the right tools installed, I'll try and suggest how to install them.
|
||||||
`
|
`
|
||||||
|
|
||||||
@@ -274,18 +274,16 @@ func CheckDependencies(logger *Logger) (bool, error) {
|
|||||||
distroInfo := GetLinuxDistroInfo()
|
distroInfo := GetLinuxDistroInfo()
|
||||||
|
|
||||||
switch distroInfo.Distribution {
|
switch distroInfo.Distribution {
|
||||||
case Ubuntu, Debian, Zorin, Parrot, Linuxmint, Elementary, Kali, Neon, Deepin, Raspbian, PopOS:
|
case Ubuntu, Debian, Zorin, Parrot, Linuxmint, Elementary, Kali:
|
||||||
libraryChecker = DpkgInstalled
|
libraryChecker = DpkgInstalled
|
||||||
case Arch, ArcoLinux, ArchLabs, Manjaro, ManjaroARM:
|
case Arch:
|
||||||
libraryChecker = PacmanInstalled
|
libraryChecker = PacmanInstalled
|
||||||
case CentOS, Fedora, Tumbleweed, Leap:
|
case CentOS, Fedora:
|
||||||
libraryChecker = RpmInstalled
|
libraryChecker = RpmInstalled
|
||||||
case Gentoo:
|
case Gentoo:
|
||||||
libraryChecker = EqueryInstalled
|
libraryChecker = EqueryInstalled
|
||||||
case VoidLinux:
|
case VoidLinux:
|
||||||
libraryChecker = XbpsInstalled
|
libraryChecker = XbpsInstalled
|
||||||
case Solus:
|
|
||||||
libraryChecker = EOpkgInstalled
|
|
||||||
default:
|
default:
|
||||||
return false, RequestSupportForDistribution(distroInfo)
|
return false, RequestSupportForDistribution(distroInfo)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,4 +9,4 @@
|
|||||||
last 2 versions
|
last 2 versions
|
||||||
Firefox ESR
|
Firefox ESR
|
||||||
not dead
|
not dead
|
||||||
IE 9-11 # For IE 9-11 support, remove 'not'.
|
not IE 9-11 # For IE 9-11 support, remove 'not'.
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"ng": "npx ng",
|
"ng": "npx ng",
|
||||||
"start": "npx ng serve --poll=2000 --host=0.0.0.0",
|
"start": "npx ng serve --poll=2000",
|
||||||
"build": "npx ng build --single-bundle true --output-hashing none --prod --bundle-styles false",
|
"build": "npx ng build --single-bundle true --output-hashing none --prod --bundle-styles false",
|
||||||
"test": "npx ng test",
|
"test": "npx ng test",
|
||||||
"lint": "npx ng lint",
|
"lint": "npx ng lint",
|
||||||
@@ -22,7 +22,6 @@
|
|||||||
"@angular/platform-browser-dynamic": "~8.0.1",
|
"@angular/platform-browser-dynamic": "~8.0.1",
|
||||||
"@angular/router": "~8.0.1",
|
"@angular/router": "~8.0.1",
|
||||||
"@wailsapp/runtime": "^1.0.0",
|
"@wailsapp/runtime": "^1.0.0",
|
||||||
"core-js": "^3.4.4",
|
|
||||||
"ngx-build-plus": "^8.0.3",
|
"ngx-build-plus": "^8.0.3",
|
||||||
"rxjs": "~6.4.0",
|
"rxjs": "~6.4.0",
|
||||||
"tslib": "^1.9.0",
|
"tslib": "^1.9.0",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import 'core-js/stable';
|
|
||||||
import { enableProdMode } from '@angular/core';
|
import { enableProdMode } from '@angular/core';
|
||||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
|
||||||
@@ -7,7 +6,7 @@ import { environment } from './environments/environment';
|
|||||||
|
|
||||||
import 'zone.js'
|
import 'zone.js'
|
||||||
|
|
||||||
import * as Wails from '@wailsapp/runtime';
|
import Wails from '@wailsapp/runtime';
|
||||||
|
|
||||||
if (environment.production) {
|
if (environment.production) {
|
||||||
enableProdMode();
|
enableProdMode();
|
||||||
|
|||||||
17
cmd/templates/angular-template/frontend/src/wailsbridge.js
vendored
Normal file
17
cmd/templates/angular-template/frontend/src/wailsbridge.js
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
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",
|
"module": "esnext",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"importHelpers": true,
|
"importHelpers": true,
|
||||||
"target": "es5",
|
"target": "es2015",
|
||||||
"typeRoots": [
|
"typeRoots": [
|
||||||
"node_modules/@types"
|
"node_modules/@types"
|
||||||
],
|
],
|
||||||
@@ -20,4 +20,4 @@
|
|||||||
"dom"
|
"dom"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ func basic() string {
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
js := mewn.String("./frontend/dist/my-app/main.js")
|
js := mewn.String("./frontend/dist/my-app/main-es2015.js")
|
||||||
css := mewn.String("./frontend/dist/my-app/styles.css")
|
css := mewn.String("./frontend/dist/my-app/styles.css")
|
||||||
|
|
||||||
app := wails.CreateApp(&wails.AppConfig{
|
app := wails.CreateApp(&wails.AppConfig{
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-js": "^3.6.4",
|
"core-js": "^3.1.4",
|
||||||
"react": "^16.13.1",
|
"react": "^16.8.6",
|
||||||
"react-dom": "^16.13.1",
|
"react-dom": "^16.8.6",
|
||||||
"wails-react-scripts": "3.0.1-2",
|
"@wailsapp/wails-react-scripts": "3.0.1-2",
|
||||||
"react-modal": "3.11.2",
|
"react-modal": "3.8.1",
|
||||||
"@wailsapp/runtime": "^1.0.10"
|
"@wailsapp/runtime": "^1.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"start": "react-scripts start",
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.8 KiB |
@@ -1,13 +1,10 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
<head>
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
<meta name="description" content="Web site created using create-react-app" />
|
|
||||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
|
||||||
<!--
|
<!--
|
||||||
manifest.json provides metadata used when your web app is installed on a
|
manifest.json provides metadata used when your web app is installed on a
|
||||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||||
@@ -23,9 +20,8 @@
|
|||||||
Learn how to configure a non-root public URL by running `npm run build`.
|
Learn how to configure a non-root public URL by running `npm run build`.
|
||||||
-->
|
-->
|
||||||
<title>React App</title>
|
<title>React App</title>
|
||||||
</head>
|
</head>
|
||||||
|
<body>
|
||||||
<body>
|
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<!--
|
<!--
|
||||||
@@ -38,6 +34,5 @@
|
|||||||
To begin the development, run `npm start` or `yarn start`.
|
To begin the development, run `npm start` or `yarn start`.
|
||||||
To create a production bundle, use `npm run build` or `yarn build`.
|
To create a production bundle, use `npm run build` or `yarn build`.
|
||||||
-->
|
-->
|
||||||
</body>
|
</body>
|
||||||
|
</html>
|
||||||
</html>
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 37 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 176 KiB |
@@ -6,16 +6,6 @@
|
|||||||
"src": "favicon.ico",
|
"src": "favicon.ico",
|
||||||
"sizes": "64x64 32x32 24x24 16x16",
|
"sizes": "64x64 32x32 24x24 16x16",
|
||||||
"type": "image/x-icon"
|
"type": "image/x-icon"
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "logo192.png",
|
|
||||||
"type": "image/png",
|
|
||||||
"sizes": "192x192"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "logo512.png",
|
|
||||||
"type": "image/png",
|
|
||||||
"sizes": "512x512"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"start_url": ".",
|
"start_url": ".",
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
# https://www.robotstxt.org/robotstxt.html
|
|
||||||
User-agent: *
|
|
||||||
Disallow:
|
|
||||||
@@ -3,16 +3,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.App-logo {
|
.App-logo {
|
||||||
|
animation: App-logo-spin infinite 20s linear;
|
||||||
height: 40vmin;
|
height: 40vmin;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-reduced-motion: no-preference) {
|
|
||||||
.App-logo {
|
|
||||||
animation: App-logo-spin infinite 20s linear;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.App-header {
|
.App-header {
|
||||||
background-color: #282c34;
|
background-color: #282c34;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
|
|||||||
@@ -1,35 +1,48 @@
|
|||||||
import React, { useState } from 'react';
|
import React from 'react';
|
||||||
import Modal from 'react-modal';
|
import Modal from 'react-modal';
|
||||||
|
|
||||||
function HelloWorld() {
|
class HelloWorld extends React.Component {
|
||||||
const [showModal, setShowModal] = useState(false);
|
constructor(props, context) {
|
||||||
const [result, setResult] = useState(null);
|
super();
|
||||||
|
this.state = {
|
||||||
|
showModal: false
|
||||||
|
};
|
||||||
|
|
||||||
const handleOpenModal = () => {
|
this.handleOpenModal = this.handleOpenModal.bind(this);
|
||||||
setShowModal(true);
|
this.handleCloseModal = this.handleCloseModal.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
window.backend.basic().then((result) => setResult(result));
|
handleOpenModal () {
|
||||||
};
|
this.setState({ showModal: true });
|
||||||
|
|
||||||
const handleCloseModal = () => {
|
window.backend.basic().then(result =>
|
||||||
setShowModal(false);
|
this.setState({
|
||||||
};
|
result
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
handleCloseModal () {
|
||||||
<div className="App">
|
this.setState({ showModal: false });
|
||||||
<button onClick={() => handleOpenModal()} type="button">
|
}
|
||||||
Hello
|
|
||||||
</button>
|
render() {
|
||||||
<Modal
|
const { result } = this.state;
|
||||||
appElement={document.getElementById("app")}
|
return (
|
||||||
isOpen={showModal}
|
<div className="App">
|
||||||
contentLabel="Minimal Modal Example"
|
<button onClick={this.handleOpenModal} type="button">
|
||||||
>
|
Hello
|
||||||
<p>{result}</p>
|
</button>
|
||||||
<button onClick={() => handleCloseModal()}>Close Modal</button>
|
<Modal
|
||||||
</Modal>
|
isOpen={this.state.showModal}
|
||||||
</div>
|
contentLabel="Minimal Modal Example"
|
||||||
);
|
>
|
||||||
|
<p>{result}</p>
|
||||||
|
<button onClick={this.handleCloseModal}>Close Modal</button>
|
||||||
|
</Modal>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default HelloWorld;
|
export default HelloWorld;
|
||||||
|
|||||||
@@ -3,20 +3,9 @@ import ReactDOM from 'react-dom';
|
|||||||
import 'core-js/stable';
|
import 'core-js/stable';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
import * as serviceWorker from './serviceWorker';
|
|
||||||
|
|
||||||
import * as Wails from '@wailsapp/runtime';
|
import Wails from '@wailsapp/runtime';
|
||||||
|
|
||||||
Wails.Init(() => {
|
Wails.Init(() => {
|
||||||
ReactDOM.render(
|
ReactDOM.render(<App />, document.getElementById('app'));
|
||||||
<React.StrictMode>
|
|
||||||
<App />
|
|
||||||
</React.StrictMode>,
|
|
||||||
document.getElementById("app")
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// If you want your app to work offline and load faster, you can change
|
|
||||||
// unregister() to register() below. Note this comes with some pitfalls.
|
|
||||||
// Learn more about service workers: https://bit.ly/CRA-PWA
|
|
||||||
serviceWorker.unregister();
|
|
||||||
|
|||||||
17
cmd/templates/create-react-app/frontend/src/wailsbridge.js
Normal file
17
cmd/templates/create-react-app/frontend/src/wailsbridge.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
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,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "React JS",
|
"name": "React JS",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"shortdescription": "Create React App v4 template",
|
"shortdescription": "Create React App v3 template",
|
||||||
"description": "Create React App v4 standard tooling",
|
"description": "Create React App v3 standar tooling",
|
||||||
"install": "npm install",
|
"install": "npm install",
|
||||||
"build": "npm run build",
|
"build": "npm run build",
|
||||||
"author": "bh90210 <ktc@pm.me>",
|
"author": "bh90210 <ktc@pm.me>",
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
# README
|
|
||||||
|
|
||||||
This is an experimental template for vanilla HTML/JS/CSS.
|
|
||||||
|
|
||||||
The webpack rules may need to be adjusted to correctly embed all assets. Babel may also need to be setup correctly.
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "vanilla",
|
|
||||||
"author": "Lea<l>",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
|
||||||
"serve": "webpack-dev-server",
|
|
||||||
"build": "npx webpack"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"core-js": "^3.6.4",
|
|
||||||
"regenerator-runtime": "^0.13.3",
|
|
||||||
"@wailsapp/runtime": "^1.0.10"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"babel-eslint": "^10.1.0",
|
|
||||||
"copy-webpack-plugin": "^6.0.2",
|
|
||||||
"eslint": "^6.8.0",
|
|
||||||
"eventsource-polyfill": "^0.9.6",
|
|
||||||
"webpack": "^4.43.0",
|
|
||||||
"webpack-cli": "^3.3.11",
|
|
||||||
"webpack-dev-server": "^3.11.0",
|
|
||||||
"webpack-hot-middleware": "^2.25.0"
|
|
||||||
},
|
|
||||||
"eslintConfig": {
|
|
||||||
"root": true,
|
|
||||||
"env": {
|
|
||||||
"node": true
|
|
||||||
},
|
|
||||||
"extends": [
|
|
||||||
"eslint:recommended"
|
|
||||||
],
|
|
||||||
"rules": {},
|
|
||||||
"parserOptions": {
|
|
||||||
"parser": "babel-eslint"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"browserslist": [
|
|
||||||
"> 1%",
|
|
||||||
"last 2 versions",
|
|
||||||
"not ie <= 8"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<link rel="stylesheet" type="text/css" href="main.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
<script src="main.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,30 +0,0 @@
|
|||||||
import 'core-js/stable';
|
|
||||||
const runtime = require('@wailsapp/runtime');
|
|
||||||
|
|
||||||
// Main entry point
|
|
||||||
function start() {
|
|
||||||
|
|
||||||
// Ensure the default app div is 100% wide/high
|
|
||||||
var app = document.getElementById('app');
|
|
||||||
app.style.width = '100%';
|
|
||||||
app.style.height = '100%';
|
|
||||||
|
|
||||||
// Inject html
|
|
||||||
app.innerHTML = `
|
|
||||||
<div class='logo'></div>
|
|
||||||
<div class='container'>
|
|
||||||
<button id='button'>Click Me!</button>
|
|
||||||
<div id='result'/>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
// Connect button to Go method
|
|
||||||
document.getElementById('button').onclick = function() {
|
|
||||||
window.backend.basic().then( function(result) {
|
|
||||||
document.getElementById('result').innerText = result;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// We provide our entrypoint as a callback for runtime.Init
|
|
||||||
runtime.Init(start);
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
const path = require('path');
|
|
||||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
|
||||||
|
|
||||||
let imageSizeLimit = 9007199254740991; // Number.MAX_SAFE_INTEGER
|
|
||||||
let sourceDir = path.resolve(__dirname, 'src');
|
|
||||||
let buildDir = path.resolve(__dirname, 'build');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
entry: {
|
|
||||||
index: path.resolve(sourceDir, 'main.js')
|
|
||||||
},
|
|
||||||
output: {
|
|
||||||
path: buildDir,
|
|
||||||
filename: 'main.js'
|
|
||||||
},
|
|
||||||
optimization: {
|
|
||||||
splitChunks: false
|
|
||||||
},
|
|
||||||
devServer: {
|
|
||||||
disableHostCheck: true,
|
|
||||||
contentBase: path.join(__dirname, 'src'),
|
|
||||||
compress: true,
|
|
||||||
open: true,
|
|
||||||
port: 8090
|
|
||||||
},
|
|
||||||
mode: 'production',
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.(png|gif|jpg|woff2?|eot|ttf|otf|svg)(\?.*)?$/i,
|
|
||||||
use: [
|
|
||||||
{
|
|
||||||
loader: 'url-loader',
|
|
||||||
options: {
|
|
||||||
limit: imageSizeLimit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
new CopyWebpackPlugin({
|
|
||||||
patterns: [
|
|
||||||
{
|
|
||||||
from: path.resolve(sourceDir, 'main.css'),
|
|
||||||
to: path.resolve(buildDir, 'main.css')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
from: path.resolve(sourceDir, 'index.html'),
|
|
||||||
to: path.resolve(buildDir, 'index.html')
|
|
||||||
},
|
|
||||||
]
|
|
||||||
})
|
|
||||||
]
|
|
||||||
};
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
module {{.BinaryName}}
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/wailsapp/wails {{.WailsVersion}}
|
|
||||||
)
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/leaanthony/mewn"
|
|
||||||
"github.com/wailsapp/wails"
|
|
||||||
)
|
|
||||||
|
|
||||||
func basic() string {
|
|
||||||
return "Hello World!"
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
|
|
||||||
js := mewn.String("./frontend/build/main.js")
|
|
||||||
css := mewn.String("./frontend/build/main.css")
|
|
||||||
|
|
||||||
app := wails.CreateApp(&wails.AppConfig{
|
|
||||||
Width: 1024,
|
|
||||||
Height: 768,
|
|
||||||
Title: "{{.Name}}",
|
|
||||||
JS: js,
|
|
||||||
CSS: css,
|
|
||||||
Colour: "#131313",
|
|
||||||
})
|
|
||||||
app.Bind(basic)
|
|
||||||
app.Run()
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Vanilla",
|
|
||||||
"shortdescription": "A Vanilla HTML/JS template",
|
|
||||||
"description": "A basic template using plain html/js and bundled using Webpack 4",
|
|
||||||
"author": "Lea Anthony<lea.anthony@gmail.com>",
|
|
||||||
"created": "2020-06-14",
|
|
||||||
"frontenddir": "frontend",
|
|
||||||
"install": "npm install",
|
|
||||||
"build": "npm run build",
|
|
||||||
"serve": "npm run serve",
|
|
||||||
"bridge": "src"
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
presets: [
|
presets: [
|
||||||
[ '@vue/app', { useBuiltIns: 'entry' } ]
|
'@vue/app'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,21 +8,20 @@
|
|||||||
"lint": "vue-cli-service lint"
|
"lint": "vue-cli-service lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-js": "^3.6.4",
|
"core-js": "^2.6.4",
|
||||||
"regenerator-runtime": "^0.13.3",
|
"vue": "^2.5.22",
|
||||||
"vue": "^2.6.11",
|
"@wailsapp/runtime": "^1.0.0"
|
||||||
"@wailsapp/runtime": "^1.0.10"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/cli-plugin-babel": "^4.2.3",
|
"@vue/cli-plugin-babel": "^3.4.0",
|
||||||
"@vue/cli-plugin-eslint": "^4.2.3",
|
"@vue/cli-plugin-eslint": "^3.4.0",
|
||||||
"@vue/cli-service": "^4.2.3",
|
"@vue/cli-service": "^3.4.0",
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.0.1",
|
||||||
"eslint": "^6.8.0",
|
"eslint": "^5.8.0",
|
||||||
"eslint-plugin-vue": "^6.2.1",
|
"eslint-plugin-vue": "^5.0.0",
|
||||||
"eventsource-polyfill": "^0.9.6",
|
"eventsource-polyfill": "^0.9.6",
|
||||||
"vue-template-compiler": "^2.6.11",
|
"vue-template-compiler": "^2.5.21",
|
||||||
"webpack-hot-middleware": "^2.25.0"
|
"webpack-hot-middleware": "^2.24.3"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"root": true,
|
"root": true,
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
import 'core-js/stable';
|
|
||||||
import 'regenerator-runtime/runtime';
|
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import App from './App.vue';
|
import App from './App.vue';
|
||||||
|
|
||||||
Vue.config.productionTip = false;
|
Vue.config.productionTip = false;
|
||||||
Vue.config.devtools = true;
|
Vue.config.devtools = true;
|
||||||
|
|
||||||
import * as Wails from '@wailsapp/runtime';
|
import Wails from '@wailsapp/runtime';
|
||||||
|
|
||||||
Wails.Init(() => {
|
Wails.Init(() => {
|
||||||
new Vue({
|
new Vue({
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
devServer: {
|
devServer: {
|
||||||
disableHostCheck: true
|
disableHostCheck: true,
|
||||||
|
host: "localhost"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
presets: [
|
presets: [
|
||||||
[ '@vue/app', { useBuiltIns: 'entry' } ]
|
'@vue/app'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,24 +7,24 @@
|
|||||||
"build": "vue-cli-service build",
|
"build": "vue-cli-service build",
|
||||||
"lint": "vue-cli-service lint"
|
"lint": "vue-cli-service lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-js": "^3.6.4",
|
"babel-polyfill": "^6.26.0",
|
||||||
"regenerator-runtime": "^0.13.3",
|
"core-js": "^2.6.4",
|
||||||
"material-design-icons-iconfont": "^5.0.1",
|
"material-design-icons-iconfont": "^5.0.1",
|
||||||
"vue": "^2.5.22",
|
"vue": "^2.5.22",
|
||||||
"vuetify": "^1.5.14",
|
"vuetify": "^1.5.14",
|
||||||
"@wailsapp/runtime": "^1.0.10"
|
"@wailsapp/runtime": "^1.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/cli-plugin-babel": "^4.2.3",
|
"@vue/cli-plugin-babel": "^3.4.0",
|
||||||
"@vue/cli-plugin-eslint": "^4.2.3",
|
"@vue/cli-plugin-eslint": "^3.4.0",
|
||||||
"@vue/cli-service": "^4.2.3",
|
"@vue/cli-service": "^3.4.0",
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.0.1",
|
||||||
"eslint": "^6.8.0",
|
"eslint": "^5.8.0",
|
||||||
"eslint-plugin-vue": "^6.2.1",
|
"eslint-plugin-vue": "^5.0.0",
|
||||||
"eventsource-polyfill": "^0.9.6",
|
"eventsource-polyfill": "^0.9.6",
|
||||||
"vue-template-compiler": "^2.6.11",
|
"vue-template-compiler": "^2.5.21",
|
||||||
"webpack-hot-middleware": "^2.25.0"
|
"webpack-hot-middleware": "^2.24.3"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"root": true,
|
"root": true,
|
||||||
@@ -50,4 +50,4 @@
|
|||||||
"last 2 versions",
|
"last 2 versions",
|
||||||
"not ie <= 8"
|
"not ie <= 8"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import 'core-js/stable';
|
import 'babel-polyfill';
|
||||||
import 'regenerator-runtime/runtime';
|
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
|
||||||
// Setup Vuetify
|
// Setup Vuetify
|
||||||
@@ -13,7 +12,7 @@ import App from './App.vue';
|
|||||||
Vue.config.productionTip = false;
|
Vue.config.productionTip = false;
|
||||||
Vue.config.devtools = true;
|
Vue.config.devtools = true;
|
||||||
|
|
||||||
import * as Wails from '@wailsapp/runtime';
|
import Wails from '@wailsapp/runtime';
|
||||||
|
|
||||||
Wails.Init(() => {
|
Wails.Init(() => {
|
||||||
new Vue({
|
new Vue({
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
devServer: {
|
devServer: {
|
||||||
disableHostCheck: true
|
disableHostCheck: true,
|
||||||
|
host: "localhost"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "Vuetify1.5/Webpack Basic",
|
"name": "Vuetify Basic",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"shortdescription": "A basic Vuetify1.5/Webpack4 template",
|
"shortdescription": "Vuetify + Webpack",
|
||||||
"description": "Basic template using Vuetify v1.5 and bundled using Webpack",
|
"description": "Basic template using Vuetify and bundled using Webpack",
|
||||||
"install": "npm install",
|
"install": "npm install",
|
||||||
"build": "npm run build",
|
"build": "npm run build",
|
||||||
"author": "lea <lea.anthony@gmail.com>",
|
"author": "lea <lea.anthony@gmail.com>",
|
||||||
@@ -11,4 +11,4 @@
|
|||||||
"serve": "npm run serve",
|
"serve": "npm run serve",
|
||||||
"bridge": "src",
|
"bridge": "src",
|
||||||
"wailsdir": ""
|
"wailsdir": ""
|
||||||
}
|
}
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"esversion": 6
|
|
||||||
}
|
|
||||||
21
cmd/templates/vuetify2-basic/frontend/.gitignore
vendored
21
cmd/templates/vuetify2-basic/frontend/.gitignore
vendored
@@ -1,21 +0,0 @@
|
|||||||
.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*
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
presets: [
|
|
||||||
[ '@vue/app', { useBuiltIns: 'entry' } ]
|
|
||||||
]
|
|
||||||
};
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
{
|
|
||||||
"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"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
<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>
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 301 KiB |
@@ -1,85 +0,0 @@
|
|||||||
<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>
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
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');
|
|
||||||
});
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
module {{.BinaryName}}
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/wailsapp/wails {{.WailsVersion}}
|
|
||||||
)
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
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()
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"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
|
package cmd
|
||||||
|
|
||||||
// Version - Wails version
|
// Version - Wails version
|
||||||
const Version = "v1.7.2-pre3"
|
const Version = "v0.17.14-pre"
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ Create your first project by running 'wails init'.`
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check Mewn
|
// Check Mewn
|
||||||
err = cmd.CheckMewn(false)
|
err = cmd.CheckMewn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,385 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/Masterminds/semver"
|
|
||||||
"github.com/leaanthony/spinner"
|
|
||||||
"github.com/wailsapp/wails/cmd"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Constants
|
|
||||||
var checkSpinner = spinner.NewSpinner()
|
|
||||||
var migrateProjectOptions = &cmd.ProjectOptions{}
|
|
||||||
var migrateFS = cmd.NewFSHelper()
|
|
||||||
var migrateGithub = cmd.NewGitHubHelper()
|
|
||||||
var programHelper = cmd.NewProgramHelper()
|
|
||||||
var lessThanV1 *semver.Constraints
|
|
||||||
|
|
||||||
// The user's go.mod
|
|
||||||
var goMod string
|
|
||||||
var goModFile string
|
|
||||||
|
|
||||||
// The user's main.js
|
|
||||||
var mainJSFile string
|
|
||||||
var mainJSContents string
|
|
||||||
|
|
||||||
// Frontend directory
|
|
||||||
var frontEndDir string
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
|
|
||||||
var dryrun bool
|
|
||||||
var err error
|
|
||||||
|
|
||||||
lessThanV1, err = semver.NewConstraint("< v1.0.0")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// var forceRebuild = false
|
|
||||||
checkSpinner.SetSpinSpeed(50)
|
|
||||||
|
|
||||||
commandDescription := `EXPERIMENTAL - This command attempts to migrate projects to the latest Wails version.`
|
|
||||||
updateCmd := app.Command("migrate", "Migrate projects to latest Wails release").
|
|
||||||
LongDescription(commandDescription).
|
|
||||||
BoolFlag("dryrun", "Only display what would be done", &dryrun)
|
|
||||||
|
|
||||||
updateCmd.Action(func() error {
|
|
||||||
|
|
||||||
message := "Migrate Project"
|
|
||||||
logger.PrintSmallBanner(message)
|
|
||||||
logger.Red("WARNING: This is an experimental command. Ensure you have backups of your project!")
|
|
||||||
logger.Red("It currently only supports npm based projects.")
|
|
||||||
fmt.Println()
|
|
||||||
|
|
||||||
// Check project directory
|
|
||||||
err := checkProjectDirectory()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find Wails version from go.mod
|
|
||||||
wailsVersion, err := getWailsVersion()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get latest stable version
|
|
||||||
var latestVersion *semver.Version
|
|
||||||
latestVersion, err = getLatestWailsVersion()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var canMigrate bool
|
|
||||||
canMigrate, err = canMigrateVersion(wailsVersion, latestVersion)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !canMigrate {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for wailsbridge
|
|
||||||
wailsBridge, err := checkWailsBridge()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is main.js using bridge.Init()
|
|
||||||
canUpdateMainJS, err := checkMainJS()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Check if we are using legacy js runtime
|
|
||||||
|
|
||||||
// Operations
|
|
||||||
logger.Yellow("Operations to perform:")
|
|
||||||
|
|
||||||
logger.Yellowf(" - Update to Wails v%s\n", latestVersion)
|
|
||||||
|
|
||||||
if len(wailsBridge) > 0 {
|
|
||||||
logger.Yellow(" - Delete wailsbridge.js")
|
|
||||||
}
|
|
||||||
|
|
||||||
if canUpdateMainJS {
|
|
||||||
logger.Yellow(" - Patch main.js")
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Yellow(" - Ensure '@wailsapp/runtime` module is installed")
|
|
||||||
|
|
||||||
if dryrun {
|
|
||||||
logger.White("Exiting: Dry Run")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Red("*WARNING* About to modify your project!")
|
|
||||||
logger.Red("Type 'YES' to continue: ")
|
|
||||||
scanner := bufio.NewScanner(os.Stdin)
|
|
||||||
scanner.Scan()
|
|
||||||
input := scanner.Text()
|
|
||||||
if input != "YES" {
|
|
||||||
logger.Red("ABORTED!")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Yellow("Let's do this!")
|
|
||||||
|
|
||||||
err = updateWailsVersion(wailsVersion, latestVersion)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(wailsBridge) > 0 {
|
|
||||||
err = deleteWailsBridge(wailsBridge)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if canUpdateMainJS {
|
|
||||||
err = patchMainJS()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Install runtime
|
|
||||||
err = installWailsRuntime()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println()
|
|
||||||
logger.Yellow("Migration complete! Check project by running `wails build`.")
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkProjectDirectory() error {
|
|
||||||
// Get versions
|
|
||||||
checkSpinner.Start("Check Project Directory")
|
|
||||||
|
|
||||||
// Check we are in project directory
|
|
||||||
err := migrateProjectOptions.LoadConfig(migrateFS.Cwd())
|
|
||||||
if err != nil {
|
|
||||||
checkSpinner.Error()
|
|
||||||
return fmt.Errorf("Unable to find 'project.json'. Please check you are in a Wails project directory")
|
|
||||||
}
|
|
||||||
|
|
||||||
checkSpinner.Success()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getWailsVersion() (*semver.Version, error) {
|
|
||||||
checkSpinner.Start("Get Wails Version")
|
|
||||||
|
|
||||||
result, err := cmd.GetWailsVersion()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
checkSpinner.Error(err.Error())
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func canMigrateVersion(wailsVersion *semver.Version, latestVersion *semver.Version) (bool, error) {
|
|
||||||
checkSpinner.Start("Checking ability to Migrate")
|
|
||||||
|
|
||||||
// Check if we are at the latest version!!!!
|
|
||||||
if wailsVersion.Equal(latestVersion) || wailsVersion.GreaterThan(latestVersion) {
|
|
||||||
checkSpinner.Errorf("Checking ability to Migrate: No! (v%s >= v%s)", wailsVersion, latestVersion)
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for < v1.0.0
|
|
||||||
if lessThanV1.Check(wailsVersion) {
|
|
||||||
checkSpinner.Successf("Checking ability to Migrate: Yes! (v%s < v1.0.0)", wailsVersion)
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
checkSpinner.Error("Unable to migrate")
|
|
||||||
return false, fmt.Errorf("No migration rules for version %s", wailsVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkWailsBridge() (string, error) {
|
|
||||||
checkSpinner.Start("Checking if legacy Wails Bridge present")
|
|
||||||
|
|
||||||
// Check frontend dir is available
|
|
||||||
if migrateProjectOptions.FrontEnd == nil ||
|
|
||||||
len(migrateProjectOptions.FrontEnd.Dir) == 0 ||
|
|
||||||
!migrateFS.DirExists(migrateProjectOptions.FrontEnd.Dir) {
|
|
||||||
checkSpinner.Error("Unable to determine frontend directory")
|
|
||||||
return "", fmt.Errorf("Unable to determine frontend directory")
|
|
||||||
}
|
|
||||||
|
|
||||||
frontEndDir = migrateProjectOptions.FrontEnd.Dir
|
|
||||||
|
|
||||||
wailsBridgePath, err := filepath.Abs(filepath.Join(".", frontEndDir, "src", "wailsbridge.js"))
|
|
||||||
if err != nil {
|
|
||||||
checkSpinner.Error(err.Error())
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
// If it doesn't exist, return blank string
|
|
||||||
if !migrateFS.FileExists(wailsBridgePath) {
|
|
||||||
checkSpinner.Success("Checking if legacy Wails Bridge present: No")
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
checkSpinner.Success("Checking if legacy Wails Bridge present: Yes")
|
|
||||||
return wailsBridgePath, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function determines if the main.js file using wailsbridge can be auto-updated
|
|
||||||
func checkMainJS() (bool, error) {
|
|
||||||
|
|
||||||
checkSpinner.Start("Checking if main.js can be migrated")
|
|
||||||
var err error
|
|
||||||
|
|
||||||
// Check main.js is there
|
|
||||||
if migrateProjectOptions.FrontEnd == nil ||
|
|
||||||
len(migrateProjectOptions.FrontEnd.Dir) == 0 ||
|
|
||||||
!migrateFS.DirExists(migrateProjectOptions.FrontEnd.Dir) {
|
|
||||||
checkSpinner.Error("Unable to determine frontend directory")
|
|
||||||
return false, fmt.Errorf("Unable to determine frontend directory")
|
|
||||||
}
|
|
||||||
|
|
||||||
frontEndDir = migrateProjectOptions.FrontEnd.Dir
|
|
||||||
|
|
||||||
mainJSFile, err = filepath.Abs(filepath.Join(".", frontEndDir, "src", "main.js"))
|
|
||||||
if err != nil {
|
|
||||||
checkSpinner.Error("Unable to find main.js")
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
mainJSContents, err = migrateFS.LoadAsString(mainJSFile)
|
|
||||||
if err != nil {
|
|
||||||
checkSpinner.Error("Unable to load main.js")
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check we have a line like: import Bridge from "./wailsbridge";
|
|
||||||
if strings.Index(mainJSContents, `import Bridge from "./wailsbridge";`) == -1 {
|
|
||||||
checkSpinner.Success("Checking if main.js can be migrated: No - Cannot find `import Bridge`")
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check we have a line like: Bridge.Start(() => {
|
|
||||||
if strings.Index(mainJSContents, `Bridge.Start(`) == -1 {
|
|
||||||
checkSpinner.Success("Checking if main.js can be migrated: No - Cannot find `Bridge.Start`")
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
checkSpinner.Success("Checking if main.js can be migrated: Yes")
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getLatestWailsVersion() (*semver.Version, error) {
|
|
||||||
checkSpinner.Start("Checking GitHub for latest Wails version")
|
|
||||||
version, err := migrateGithub.GetLatestStableRelease()
|
|
||||||
if err != nil {
|
|
||||||
checkSpinner.Error("Checking GitHub for latest Wails version: Failed")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
checkSpinner.Successf("Checking GitHub for latest Wails version: v%s", version)
|
|
||||||
return version.Version, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateWailsVersion(currentVersion, latestVersion *semver.Version) error {
|
|
||||||
// Patch go.mod
|
|
||||||
checkSpinner.Start("Patching go.mod")
|
|
||||||
|
|
||||||
wailsModule := "github.com/wailsapp/wails"
|
|
||||||
old := fmt.Sprintf("%s v%s", wailsModule, currentVersion)
|
|
||||||
new := fmt.Sprintf("%s v%s", wailsModule, latestVersion)
|
|
||||||
|
|
||||||
goMod = strings.Replace(goMod, old, new, -1)
|
|
||||||
err := ioutil.WriteFile(goModFile, []byte(goMod), 0600)
|
|
||||||
if err != nil {
|
|
||||||
checkSpinner.Error()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
checkSpinner.Success()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteWailsBridge(bridgeFilename string) error {
|
|
||||||
// Patch go.mod
|
|
||||||
checkSpinner.Start("Delete legacy wailsbridge.js")
|
|
||||||
|
|
||||||
err := migrateFS.RemoveFile(bridgeFilename)
|
|
||||||
if err != nil {
|
|
||||||
checkSpinner.Error()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
checkSpinner.Success()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func patchMainJS() error {
|
|
||||||
// Patch main.js
|
|
||||||
checkSpinner.Start("Patching main.js")
|
|
||||||
|
|
||||||
// Patch import line
|
|
||||||
oldImportLine := `import Bridge from "./wailsbridge";`
|
|
||||||
newImportLine := `import * as Wails from "@wailsapp/runtime";`
|
|
||||||
mainJSContents = strings.Replace(mainJSContents, oldImportLine, newImportLine, -1)
|
|
||||||
|
|
||||||
// Patch Start line
|
|
||||||
oldStartLine := `Bridge.Start`
|
|
||||||
newStartLine := `Wails.Init`
|
|
||||||
mainJSContents = strings.Replace(mainJSContents, oldStartLine, newStartLine, -1)
|
|
||||||
|
|
||||||
err := ioutil.WriteFile(mainJSFile, []byte(mainJSContents), 0600)
|
|
||||||
if err != nil {
|
|
||||||
checkSpinner.Error()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
checkSpinner.Success()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func installWailsRuntime() error {
|
|
||||||
|
|
||||||
checkSpinner.Start("Installing @wailsapp/runtime module")
|
|
||||||
|
|
||||||
// Change to the frontend directory
|
|
||||||
err := os.Chdir(frontEndDir)
|
|
||||||
if err != nil {
|
|
||||||
checkSpinner.Error()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine package manager
|
|
||||||
packageManager, err := migrateProjectOptions.GetNPMBinaryName()
|
|
||||||
if err != nil {
|
|
||||||
checkSpinner.Error()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
switch packageManager {
|
|
||||||
case cmd.NPM:
|
|
||||||
// npm install --save @wailsapp/runtime
|
|
||||||
programHelper.InstallNPMPackage("@wailsapp/runtime", true)
|
|
||||||
default:
|
|
||||||
checkSpinner.Error()
|
|
||||||
return fmt.Errorf("Unknown package manager")
|
|
||||||
}
|
|
||||||
|
|
||||||
checkSpinner.Success()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -3,34 +3,16 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/leaanthony/spinner"
|
"github.com/leaanthony/spinner"
|
||||||
"github.com/wailsapp/wails/cmd"
|
"github.com/wailsapp/wails/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
// getSupportedPlatforms returns a slice of platform/architecture
|
|
||||||
// targets that are buildable using the cross-platform 'x' option.
|
|
||||||
func getSupportedPlatforms() []string {
|
|
||||||
return []string{
|
|
||||||
"darwin/amd64",
|
|
||||||
"linux/amd64",
|
|
||||||
"linux/arm-7",
|
|
||||||
"windows/amd64",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
||||||
var packageApp = false
|
var packageApp = false
|
||||||
var forceRebuild = false
|
var forceRebuild = false
|
||||||
var debugMode = false
|
var debugMode = false
|
||||||
var typescriptFilename = ""
|
|
||||||
var verbose = false
|
|
||||||
var platform = ""
|
|
||||||
var ldflags = ""
|
|
||||||
|
|
||||||
buildSpinner := spinner.NewSpinner()
|
buildSpinner := spinner.NewSpinner()
|
||||||
buildSpinner.SetSpinSpeed(50)
|
buildSpinner.SetSpinSpeed(50)
|
||||||
|
|
||||||
@@ -39,18 +21,7 @@ func init() {
|
|||||||
LongDescription(commandDescription).
|
LongDescription(commandDescription).
|
||||||
BoolFlag("p", "Package application on successful build", &packageApp).
|
BoolFlag("p", "Package application on successful build", &packageApp).
|
||||||
BoolFlag("f", "Force rebuild of application components", &forceRebuild).
|
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).
|
|
||||||
StringFlag("ldflags", "Extra options for -ldflags", &ldflags)
|
|
||||||
|
|
||||||
var b strings.Builder
|
|
||||||
for _, plat := range getSupportedPlatforms() {
|
|
||||||
fmt.Fprintf(&b, " - %s\n", plat)
|
|
||||||
}
|
|
||||||
initCmd.StringFlag("x",
|
|
||||||
fmt.Sprintf("Cross-compile application to specified platform via xgo\n%s", b.String()),
|
|
||||||
&platform)
|
|
||||||
|
|
||||||
initCmd.Action(func() error {
|
initCmd.Action(func() error {
|
||||||
|
|
||||||
@@ -66,7 +37,6 @@ func init() {
|
|||||||
|
|
||||||
// Project options
|
// Project options
|
||||||
projectOptions := &cmd.ProjectOptions{}
|
projectOptions := &cmd.ProjectOptions{}
|
||||||
projectOptions.Verbose = verbose
|
|
||||||
|
|
||||||
// Check we are in project directory
|
// Check we are in project directory
|
||||||
// Check project.json loads correctly
|
// Check project.json loads correctly
|
||||||
@@ -76,28 +46,6 @@ func init() {
|
|||||||
return fmt.Errorf("Unable to find 'project.json'. Please check you are in a Wails project directory")
|
return fmt.Errorf("Unable to find 'project.json'. Please check you are in a Wails project directory")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set cross-compile
|
|
||||||
projectOptions.Platform = runtime.GOOS
|
|
||||||
if len(platform) > 0 {
|
|
||||||
supported := false
|
|
||||||
for _, plat := range getSupportedPlatforms() {
|
|
||||||
if plat == platform {
|
|
||||||
supported = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !supported {
|
|
||||||
return fmt.Errorf("unsupported platform '%s' specified.\nPlease run `wails build -h` to see the supported platform/architecture options", platform)
|
|
||||||
}
|
|
||||||
|
|
||||||
projectOptions.CrossCompile = true
|
|
||||||
plat := strings.Split(platform, "/")
|
|
||||||
projectOptions.Platform = plat[0]
|
|
||||||
projectOptions.Architecture = plat[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add ldflags
|
|
||||||
projectOptions.LdFlags = ldflags
|
|
||||||
|
|
||||||
// Validate config
|
// Validate config
|
||||||
// Check if we have a frontend
|
// Check if we have a frontend
|
||||||
err = cmd.ValidateFrontendConfig(projectOptions)
|
err = cmd.ValidateFrontendConfig(projectOptions)
|
||||||
@@ -125,13 +73,16 @@ func init() {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that runtime init.js is the production version
|
// Ensure that runtime init.js is the production version
|
||||||
err = cmd.InstallProdRuntime(projectDir, projectOptions)
|
err = cmd.InstallProdRuntime(projectDir, projectOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Move to project directory
|
// Move to project directory
|
||||||
err = os.Chdir(projectDir)
|
err = os.Chdir(projectDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -139,7 +90,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Install dependencies
|
// Install dependencies
|
||||||
err = cmd.InstallGoDependencies(projectOptions.Verbose)
|
err = cmd.InstallGoDependencies()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -150,32 +101,6 @@ func init() {
|
|||||||
buildMode = cmd.BuildModeDebug
|
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)
|
err = cmd.BuildApplication(projectOptions.BinaryName, forceRebuild, buildMode, packageApp, projectOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/leaanthony/spinner"
|
"github.com/leaanthony/spinner"
|
||||||
"github.com/wailsapp/wails/cmd"
|
"github.com/wailsapp/wails/cmd"
|
||||||
@@ -11,14 +10,12 @@ import (
|
|||||||
func init() {
|
func init() {
|
||||||
|
|
||||||
var forceRebuild = false
|
var forceRebuild = false
|
||||||
var verbose = false
|
|
||||||
buildSpinner := spinner.NewSpinner()
|
buildSpinner := spinner.NewSpinner()
|
||||||
buildSpinner.SetSpinSpeed(50)
|
buildSpinner.SetSpinSpeed(50)
|
||||||
|
|
||||||
commandDescription := `This command builds then serves your application in bridge mode. Useful for developing your app in a browser.`
|
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").
|
initCmd := app.Command("serve", "Run your Wails project in bridge mode").
|
||||||
LongDescription(commandDescription).
|
LongDescription(commandDescription).
|
||||||
BoolFlag("verbose", "Verbose output", &verbose).
|
|
||||||
BoolFlag("f", "Force rebuild of application components", &forceRebuild)
|
BoolFlag("f", "Force rebuild of application components", &forceRebuild)
|
||||||
|
|
||||||
initCmd.Action(func() error {
|
initCmd.Action(func() error {
|
||||||
@@ -28,7 +25,7 @@ func init() {
|
|||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
|
||||||
// Check Mewn is installed
|
// Check Mewn is installed
|
||||||
err := cmd.CheckMewn(verbose)
|
err := cmd.CheckMewn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -44,10 +41,6 @@ func init() {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set project options
|
|
||||||
projectOptions.Verbose = verbose
|
|
||||||
projectOptions.Platform = runtime.GOOS
|
|
||||||
|
|
||||||
// Save project directory
|
// Save project directory
|
||||||
projectDir := fs.Cwd()
|
projectDir := fs.Cwd()
|
||||||
|
|
||||||
@@ -58,7 +51,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Install dependencies
|
// Install dependencies
|
||||||
err = cmd.InstallGoDependencies(projectOptions.Verbose)
|
err = cmd.InstallGoDependencies()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/leaanthony/spinner"
|
"github.com/leaanthony/spinner"
|
||||||
|
"github.com/mitchellh/go-homedir"
|
||||||
"github.com/wailsapp/wails/cmd"
|
"github.com/wailsapp/wails/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -146,7 +146,7 @@ func updateToVersion(targetVersion *cmd.SemanticVersion, force bool) error {
|
|||||||
updateSpinner.Start("Installing Wails " + desiredVersion)
|
updateSpinner.Start("Installing Wails " + desiredVersion)
|
||||||
|
|
||||||
// Run command in non module directory
|
// Run command in non module directory
|
||||||
homeDir, err := os.UserHomeDir()
|
homeDir, err := homedir.Dir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Cannot find home directory! Please file a bug report!")
|
log.Fatal("Cannot find home directory! Please file a bug report!")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,16 +80,15 @@ To help you in this process, we will ask for some information, add Go/Wails deta
|
|||||||
npm := program.FindProgram("npm")
|
npm := program.FindProgram("npm")
|
||||||
if npm != nil {
|
if npm != nil {
|
||||||
stdout, _, _, _ := npm.Run("--version")
|
stdout, _, _, _ := npm.Run("--version")
|
||||||
npmVersion = stdout
|
nodeVersion = stdout
|
||||||
npmVersion = npmVersion[:len(npmVersion)-1]
|
nodeVersion = nodeVersion[:len(nodeVersion)-1]
|
||||||
npmVersion = strings.TrimSpace(npmVersion)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
node := program.FindProgram("node")
|
node := program.FindProgram("node")
|
||||||
if node != nil {
|
if node != nil {
|
||||||
stdout, _, _, _ := node.Run("--version")
|
stdout, _, _, _ := node.Run("--version")
|
||||||
nodeVersion = stdout
|
npmVersion = stdout
|
||||||
nodeVersion = nodeVersion[:len(nodeVersion)-1]
|
npmVersion = npmVersion[:len(npmVersion)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
str.WriteString("\n| Name | Value |\n| ----- | ----- |\n")
|
str.WriteString("\n| Name | Value |\n| ----- | ----- |\n")
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
|
|
||||||
"github.com/wailsapp/wails/cmd"
|
"github.com/wailsapp/wails/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,9 +15,5 @@ func main() {
|
|||||||
err := app.Run()
|
err := app.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err.Error())
|
logger.Error(err.Error())
|
||||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
|
||||||
os.Exit(exitErr.ExitCode())
|
|
||||||
}
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
windres.exe -o %1 %2
|
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
package wails
|
package wails
|
||||||
|
|
||||||
import (
|
import "github.com/leaanthony/mewn"
|
||||||
"github.com/leaanthony/mewn"
|
|
||||||
"github.com/wailsapp/wails/runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AppConfig is the configuration structure used when creating a Wails App object
|
// AppConfig is the configuration structure used when creating a Wails App object
|
||||||
type AppConfig struct {
|
type AppConfig struct {
|
||||||
@@ -68,7 +65,7 @@ func (a *AppConfig) merge(in *AppConfig) error {
|
|||||||
a.CSS = in.CSS
|
a.CSS = in.CSS
|
||||||
}
|
}
|
||||||
if in.Title != "" {
|
if in.Title != "" {
|
||||||
a.Title = runtime.ProcessEncoding(in.Title)
|
a.Title = in.Title
|
||||||
}
|
}
|
||||||
|
|
||||||
if in.Colour != "" {
|
if in.Colour != "" {
|
||||||
|
|||||||
17
go.mod
17
go.mod
@@ -2,7 +2,9 @@ module github.com/wailsapp/wails
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Masterminds/semver v1.4.2
|
github.com/Masterminds/semver v1.4.2
|
||||||
github.com/abadojack/whatlanggo v1.0.1
|
github.com/dchest/cssmin v0.0.0-20151210170030-fb8d9b44afdc // indirect
|
||||||
|
github.com/dchest/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/fatih/color v1.7.0
|
||||||
github.com/go-playground/colors v1.2.0
|
github.com/go-playground/colors v1.2.0
|
||||||
github.com/gorilla/websocket v1.4.0
|
github.com/gorilla/websocket v1.4.0
|
||||||
@@ -10,22 +12,19 @@ require (
|
|||||||
github.com/kennygrant/sanitize v1.2.4
|
github.com/kennygrant/sanitize v1.2.4
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
|
||||||
github.com/leaanthony/mewn v0.10.7
|
github.com/leaanthony/mewn v0.10.7
|
||||||
github.com/leaanthony/slicer v1.4.0
|
github.com/leaanthony/slicer v1.3.2
|
||||||
github.com/leaanthony/spinner v0.5.3
|
github.com/leaanthony/spinner v0.5.3
|
||||||
github.com/mattn/go-colorable v0.1.1 // indirect
|
github.com/mattn/go-colorable v0.1.1 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.7 // indirect
|
github.com/mattn/go-isatty v0.0.7 // indirect
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||||
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4
|
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4
|
||||||
github.com/pkg/errors v0.8.1 // indirect
|
github.com/pkg/errors v0.8.1 // indirect
|
||||||
github.com/sirupsen/logrus v1.4.1
|
github.com/sirupsen/logrus v1.4.1
|
||||||
github.com/stretchr/testify v1.3.0 // indirect
|
github.com/stretchr/testify v1.3.0 // indirect
|
||||||
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 // indirect
|
||||||
golang.org/x/image v0.0.0-20200430140353-33d19683fad8
|
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5 // indirect
|
||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344 // indirect
|
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862
|
||||||
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c
|
|
||||||
golang.org/x/text v0.3.0
|
|
||||||
gopkg.in/AlecAivazis/survey.v1 v1.8.4
|
gopkg.in/AlecAivazis/survey.v1 v1.8.4
|
||||||
gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22
|
gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22
|
||||||
)
|
)
|
||||||
|
|
||||||
go 1.13
|
|
||||||
|
|||||||
34
go.sum
34
go.sum
@@ -2,11 +2,15 @@ github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITg
|
|||||||
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
|
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
|
||||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
|
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
|
||||||
github.com/abadojack/whatlanggo v1.0.1 h1:19N6YogDnf71CTHm3Mp2qhYfkRdyvbgwWdd2EPxJRG4=
|
|
||||||
github.com/abadojack/whatlanggo v1.0.1/go.mod h1:66WiQbSbJBIlOZMsvbKe5m6pzQovxCH9B/K8tQB2uoc=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
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 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
github.com/go-playground/colors v1.2.0 h1:0EdjTXKrr2g1L/LQTYtIqabeHpZuGZz1U4osS1T8+5M=
|
github.com/go-playground/colors v1.2.0 h1:0EdjTXKrr2g1L/LQTYtIqabeHpZuGZz1U4osS1T8+5M=
|
||||||
@@ -28,14 +32,15 @@ github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
|
|||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
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 h1:jCcNJyIUOpwj+I5SuATvCugDjHkoo+j6ubEOxxrxmPA=
|
||||||
github.com/leaanthony/mewn v0.10.7/go.mod h1:CRkTx8unLiSSilu/Sd7i1LwrdaAL+3eQ3ses99qGMEQ=
|
github.com/leaanthony/mewn v0.10.7/go.mod h1:CRkTx8unLiSSilu/Sd7i1LwrdaAL+3eQ3ses99qGMEQ=
|
||||||
github.com/leaanthony/slicer v1.4.0 h1:Q9u4w+UBU4WHjXnEDdz+eRLMKF/rnyosRBiqULnc1J8=
|
github.com/leaanthony/slicer v1.3.2 h1:kGWWFoyaY5WzwGrUsHXMmGbssuYthP4qYBNlkNpNAB8=
|
||||||
github.com/leaanthony/slicer v1.4.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
|
github.com/leaanthony/slicer v1.3.2/go.mod h1:VMB/HGvr3uR3MRpFWHWAm0w+DHQLzPHYe2pKfpFlQIQ=
|
||||||
github.com/leaanthony/spinner v0.5.3 h1:IMTvgdQCec5QA4qRy0wil4XsRP+QcG1OwLWVK/LPZ5Y=
|
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/spinner v0.5.3/go.mod h1:oHlrvWicr++CVV7ALWYi+qHk/XNA91D9IJ48IqmpVUo=
|
||||||
github.com/leaanthony/synx v0.1.0 h1:R0lmg2w6VMb8XcotOwAe5DLyzwjLrskNkwU7LLWsyL8=
|
github.com/leaanthony/synx v0.1.0 h1:R0lmg2w6VMb8XcotOwAe5DLyzwjLrskNkwU7LLWsyL8=
|
||||||
github.com/leaanthony/synx v0.1.0/go.mod h1:Iz7eybeeG8bdq640iR+CwYb8p+9EOsgMWghkSRyZcqs=
|
github.com/leaanthony/synx v0.1.0/go.mod h1:Iz7eybeeG8bdq640iR+CwYb8p+9EOsgMWghkSRyZcqs=
|
||||||
github.com/leaanthony/wincursor v0.1.0 h1:Dsyp68QcF5cCs65AMBmxoYNEm0n8K7mMchG6a8fYxf8=
|
github.com/leaanthony/wincursor v0.1.0 h1:Dsyp68QcF5cCs65AMBmxoYNEm0n8K7mMchG6a8fYxf8=
|
||||||
github.com/leaanthony/wincursor v0.1.0/go.mod h1:7TVwwrzSH/2Y9gLOGH+VhA+bZhoWXBRgbGNTMk+yimE=
|
github.com/leaanthony/wincursor v0.1.0/go.mod h1:7TVwwrzSH/2Y9gLOGH+VhA+bZhoWXBRgbGNTMk+yimE=
|
||||||
|
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
|
||||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
|
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
|
||||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||||
@@ -46,6 +51,8 @@ github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc
|
|||||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
||||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||||
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4 h1:49lOXmGaUpV9Fz3gd7TFZY106KVlPVa5jcYD1gaQf98=
|
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4 h1:49lOXmGaUpV9Fz3gd7TFZY106KVlPVa5jcYD1gaQf98=
|
||||||
@@ -62,28 +69,21 @@ github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
|||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba h1:2DHfQOxcpWdGf5q5IzCUFPNvRX9Icf+09RvQK2VnJq0=
|
|
||||||
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba/go.mod h1:iLnlXG2Pakcii2CU0cbY07DRCSvpWNa7nFxtevhOChk=
|
|
||||||
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw=
|
|
||||||
golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
|
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5 h1:6M3SDHlHHDCx2PcQw3S4KsR170vGqDhJDOmpVd4Hjak=
|
||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
|
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862 h1:rM0ROo5vb9AdYJi1110yjWGMej9ITfKddS89P3Fkhug=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c h1:UIcGWL6/wpCfyGuJnRFJRurA+yj8RrW7Q6x2YMCXt6c=
|
|
||||||
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
gopkg.in/AlecAivazis/survey.v1 v1.8.4 h1:10xXXN3wgIhPheb5NI58zFgZv32Ana7P3Tl4shW+0Qc=
|
gopkg.in/AlecAivazis/survey.v1 v1.8.4 h1:10xXXN3wgIhPheb5NI58zFgZv32Ana7P3Tl4shW+0Qc=
|
||||||
gopkg.in/AlecAivazis/survey.v1 v1.8.4/go.mod h1:iBNOmqKz/NUbZx3bA+4hAGLRC7fSK7tgtVDT4tB22XA=
|
gopkg.in/AlecAivazis/survey.v1 v1.8.4/go.mod h1:iBNOmqKz/NUbZx3bA+4hAGLRC7fSK7tgtVDT4tB22XA=
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 103 KiB |
@@ -2,11 +2,7 @@ package binding
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/lib/interfaces"
|
"github.com/wailsapp/wails/lib/interfaces"
|
||||||
@@ -14,32 +10,26 @@ import (
|
|||||||
"github.com/wailsapp/wails/lib/messages"
|
"github.com/wailsapp/wails/lib/messages"
|
||||||
)
|
)
|
||||||
|
|
||||||
var typescriptDefinitionFilename = ""
|
|
||||||
|
|
||||||
// Manager handles method binding
|
// Manager handles method binding
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
methods map[string]*boundMethod
|
methods map[string]*boundMethod
|
||||||
functions map[string]*boundFunction
|
functions map[string]*boundFunction
|
||||||
internalMethods *internalMethods
|
internalMethods *internalMethods
|
||||||
initMethods []*boundMethod
|
initMethods []*boundMethod
|
||||||
shutdownMethods []*boundMethod
|
|
||||||
log *logger.CustomLogger
|
log *logger.CustomLogger
|
||||||
renderer interfaces.Renderer
|
renderer interfaces.Renderer
|
||||||
runtime interfaces.Runtime // The runtime object to pass to bound structs
|
runtime interfaces.Runtime // The runtime object to pass to bound structs
|
||||||
objectsToBind []interface{}
|
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
|
// NewManager creates a new Manager struct
|
||||||
func NewManager() interfaces.BindingManager {
|
func NewManager() interfaces.BindingManager {
|
||||||
|
|
||||||
result := &Manager{
|
result := &Manager{
|
||||||
methods: make(map[string]*boundMethod),
|
methods: make(map[string]*boundMethod),
|
||||||
functions: make(map[string]*boundFunction),
|
functions: make(map[string]*boundFunction),
|
||||||
log: logger.NewCustomLogger("Bind"),
|
log: logger.NewCustomLogger("Bind"),
|
||||||
internalMethods: newInternalMethods(),
|
internalMethods: newInternalMethods(),
|
||||||
structList: make(map[string][]string),
|
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -97,55 +87,9 @@ func (b *Manager) initialise() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we wish to generate a typescript definition file...
|
|
||||||
if typescriptDefinitionFilename != "" {
|
|
||||||
err := b.generateTypescriptDefinitions()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
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
|
// bind the given struct method
|
||||||
func (b *Manager) bindMethod(object interface{}) error {
|
func (b *Manager) bindMethod(object interface{}) error {
|
||||||
|
|
||||||
@@ -159,12 +103,6 @@ func (b *Manager) bindMethod(object interface{}) error {
|
|||||||
|
|
||||||
b.log.Debugf("Processing struct: %s", baseName)
|
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
|
// Iterate over method definitions
|
||||||
for i := 0; i < objectType.NumMethod(); i++ {
|
for i := 0; i < objectType.NumMethod(); i++ {
|
||||||
|
|
||||||
@@ -174,8 +112,6 @@ func (b *Manager) bindMethod(object interface{}) error {
|
|||||||
fullMethodName := baseName + "." + methodName
|
fullMethodName := baseName + "." + methodName
|
||||||
method := reflect.ValueOf(object).MethodByName(methodName)
|
method := reflect.ValueOf(object).MethodByName(methodName)
|
||||||
|
|
||||||
b.structList[actualName] = append(b.structList[actualName], methodName)
|
|
||||||
|
|
||||||
// Skip unexported methods
|
// Skip unexported methods
|
||||||
if !unicode.IsUpper([]rune(methodName)[0]) {
|
if !unicode.IsUpper([]rune(methodName)[0]) {
|
||||||
continue
|
continue
|
||||||
@@ -191,9 +127,6 @@ func (b *Manager) bindMethod(object interface{}) error {
|
|||||||
if newMethod.isWailsInit {
|
if newMethod.isWailsInit {
|
||||||
b.log.Debugf("Detected WailsInit function: %s", fullMethodName)
|
b.log.Debugf("Detected WailsInit function: %s", fullMethodName)
|
||||||
b.initMethods = append(b.initMethods, newMethod)
|
b.initMethods = append(b.initMethods, newMethod)
|
||||||
} else if newMethod.isWailsShutdown {
|
|
||||||
b.log.Debugf("Detected WailsShutdown function: %s", fullMethodName)
|
|
||||||
b.shutdownMethods = append(b.shutdownMethods, newMethod)
|
|
||||||
} else {
|
} else {
|
||||||
// Save boundMethod
|
// Save boundMethod
|
||||||
b.log.Infof("Bound Method: %s()", fullMethodName)
|
b.log.Infof("Bound Method: %s()", fullMethodName)
|
||||||
@@ -359,13 +292,3 @@ func (b *Manager) callWailsInitMethods() error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown the binding manager
|
|
||||||
func (b *Manager) Shutdown() {
|
|
||||||
b.log.Debug("Shutdown called")
|
|
||||||
for _, method := range b.shutdownMethods {
|
|
||||||
b.log.Debugf("Calling Shutdown for method: %s", method.fullName)
|
|
||||||
method.call("[]")
|
|
||||||
}
|
|
||||||
b.log.Debug("Shutdown complete")
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ type boundMethod struct {
|
|||||||
log *logger.CustomLogger
|
log *logger.CustomLogger
|
||||||
hasErrorReturnType bool // Indicates if there is an error return type
|
hasErrorReturnType bool // Indicates if there is an error return type
|
||||||
isWailsInit bool
|
isWailsInit bool
|
||||||
isWailsShutdown bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new bound method based on the given method + type
|
// Creates a new bound method based on the given method + type
|
||||||
@@ -40,11 +39,6 @@ func newBoundMethod(name string, fullName string, method reflect.Value, objectTy
|
|||||||
err = result.processWailsInit()
|
err = result.processWailsInit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Are we a WailsShutdown method?
|
|
||||||
if result.Name == "WailsShutdown" {
|
|
||||||
err = result.processWailsShutdown()
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,20 +211,3 @@ func (b *boundMethod) processWailsInit() error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *boundMethod) processWailsShutdown() error {
|
|
||||||
// We must have only 1 input, it must be *wails.Runtime
|
|
||||||
if len(b.inputs) != 0 {
|
|
||||||
return fmt.Errorf("Invalid WailsShutdown() definition. Expected 0 inputs, but got %d", len(b.inputs))
|
|
||||||
}
|
|
||||||
|
|
||||||
// We must have only 1 output, it must be error
|
|
||||||
if len(b.returnTypes) != 0 {
|
|
||||||
return fmt.Errorf("Invalid WailsShutdown() definition. Expected 0 return types, but got %d", len(b.returnTypes))
|
|
||||||
}
|
|
||||||
|
|
||||||
// We are indeed a wails Shutdown method
|
|
||||||
b.isWailsShutdown = true
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,30 +3,26 @@ package event
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/lib/interfaces"
|
|
||||||
"github.com/wailsapp/wails/lib/logger"
|
"github.com/wailsapp/wails/lib/logger"
|
||||||
"github.com/wailsapp/wails/lib/messages"
|
"github.com/wailsapp/wails/lib/messages"
|
||||||
|
"github.com/wailsapp/wails/lib/interfaces"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Manager handles and processes events
|
// Manager handles and processes events
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
incomingEvents chan *messages.EventData
|
incomingEvents chan *messages.EventData
|
||||||
quitChannel chan struct{}
|
|
||||||
listeners map[string][]*eventListener
|
listeners map[string][]*eventListener
|
||||||
running bool
|
exit bool
|
||||||
log *logger.CustomLogger
|
log *logger.CustomLogger
|
||||||
renderer interfaces.Renderer // Messages will be dispatched to the frontend
|
renderer interfaces.Renderer // Messages will be dispatched to the frontend
|
||||||
wg sync.WaitGroup
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewManager creates a new event manager with a 100 event buffer
|
// NewManager creates a new event manager with a 100 event buffer
|
||||||
func NewManager() interfaces.EventManager {
|
func NewManager() interfaces.EventManager {
|
||||||
return &Manager{
|
return &Manager{
|
||||||
incomingEvents: make(chan *messages.EventData, 100),
|
incomingEvents: make(chan *messages.EventData, 100),
|
||||||
quitChannel: make(chan struct{}, 1),
|
|
||||||
listeners: make(map[string][]*eventListener),
|
listeners: make(map[string][]*eventListener),
|
||||||
running: false,
|
exit: false,
|
||||||
log: logger.NewCustomLogger("Events"),
|
log: logger.NewCustomLogger("Events"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,14 +87,15 @@ func (e *Manager) Start(renderer interfaces.Renderer) {
|
|||||||
// Store renderer
|
// Store renderer
|
||||||
e.renderer = renderer
|
e.renderer = renderer
|
||||||
|
|
||||||
// Set up waitgroup so we can wait for goroutine to quit
|
// Set up waitgroup so we can wait for goroutine to start
|
||||||
e.running = true
|
var wg sync.WaitGroup
|
||||||
e.wg.Add(1)
|
wg.Add(1)
|
||||||
|
|
||||||
// Run main loop in separate goroutine
|
// Run main loop in separate goroutine
|
||||||
go func() {
|
go func() {
|
||||||
|
wg.Done()
|
||||||
e.log.Info("Listening")
|
e.log.Info("Listening")
|
||||||
for e.running {
|
for e.exit == false {
|
||||||
// TODO: Listen for application exit
|
// TODO: Listen for application exit
|
||||||
select {
|
select {
|
||||||
case event := <-e.incomingEvents:
|
case event := <-e.incomingEvents:
|
||||||
@@ -142,18 +139,14 @@ func (e *Manager) Start(renderer interfaces.Renderer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case <-e.quitChannel:
|
|
||||||
e.running = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
e.wg.Done()
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// Wait for goroutine to start
|
||||||
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown is called when exiting the Application
|
func (e *Manager) stop() {
|
||||||
func (e *Manager) Shutdown() {
|
e.exit = true
|
||||||
e.log.Debug("Shutting Down")
|
|
||||||
e.quitChannel <- struct{}{}
|
|
||||||
e.log.Debug("Waiting for main loop to exit")
|
|
||||||
e.wg.Wait()
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,5 +7,4 @@ type BindingManager interface {
|
|||||||
Bind(object interface{})
|
Bind(object interface{})
|
||||||
Start(renderer Renderer, runtime Runtime) error
|
Start(renderer Renderer, runtime Runtime) error
|
||||||
ProcessCall(callData *messages.CallData) (result interface{}, err error)
|
ProcessCall(callData *messages.CallData) (result interface{}, err error)
|
||||||
Shutdown()
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,5 +8,4 @@ type EventManager interface {
|
|||||||
Emit(eventName string, optionalData ...interface{})
|
Emit(eventName string, optionalData ...interface{})
|
||||||
On(eventName string, callback func(...interface{}))
|
On(eventName string, callback func(...interface{}))
|
||||||
Start(Renderer)
|
Start(Renderer)
|
||||||
Shutdown()
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,8 @@
|
|||||||
package interfaces
|
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
|
// IPCManager is the event manager interface
|
||||||
type IPCManager interface {
|
type IPCManager interface {
|
||||||
BindRenderer(Renderer)
|
BindRenderer(Renderer)
|
||||||
Dispatch(message string, f CallbackFunc)
|
Dispatch(message string)
|
||||||
Start(eventManager EventManager, bindingManager BindingManager)
|
Start(eventManager EventManager, bindingManager BindingManager)
|
||||||
Shutdown()
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,23 +3,22 @@ package interfaces
|
|||||||
import (
|
import (
|
||||||
"github.com/wailsapp/wails/lib/messages"
|
"github.com/wailsapp/wails/lib/messages"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Renderer is an interface describing a Wails target to render the app to
|
// Renderer is an interface describing a Wails target to render the app to
|
||||||
type Renderer interface {
|
type Renderer interface {
|
||||||
Initialise(AppConfig, IPCManager, EventManager) error
|
Initialise(AppConfig, IPCManager, EventManager) error
|
||||||
Run() error
|
Run() error
|
||||||
EnableConsole()
|
|
||||||
|
|
||||||
// Binding
|
// Binding
|
||||||
NewBinding(bindingName string) error
|
NewBinding(bindingName string) error
|
||||||
|
Callback(data string) error
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
NotifyEvent(eventData *messages.EventData) error
|
NotifyEvent(eventData *messages.EventData) error
|
||||||
|
|
||||||
// Dialog Runtime
|
// Dialog Runtime
|
||||||
SelectFile(title string, filter string) string
|
SelectFile() string
|
||||||
SelectDirectory() string
|
SelectDirectory() string
|
||||||
SelectSaveFile(title string, filter string) string
|
SelectSaveFile() string
|
||||||
|
|
||||||
// Window Runtime
|
// Window Runtime
|
||||||
SetColour(string) error
|
SetColour(string) error
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package ipc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/wailsapp/wails/lib/interfaces"
|
"github.com/wailsapp/wails/lib/interfaces"
|
||||||
"github.com/wailsapp/wails/lib/logger"
|
"github.com/wailsapp/wails/lib/logger"
|
||||||
@@ -13,20 +12,18 @@ import (
|
|||||||
type Manager struct {
|
type Manager struct {
|
||||||
renderer interfaces.Renderer // The renderer
|
renderer interfaces.Renderer // The renderer
|
||||||
messageQueue chan *ipcMessage
|
messageQueue chan *ipcMessage
|
||||||
quitChannel chan struct{}
|
// quitChannel chan struct{}
|
||||||
// signals chan os.Signal
|
// signals chan os.Signal
|
||||||
log *logger.CustomLogger
|
log *logger.CustomLogger
|
||||||
eventManager interfaces.EventManager
|
eventManager interfaces.EventManager
|
||||||
bindingManager interfaces.BindingManager
|
bindingManager interfaces.BindingManager
|
||||||
running bool
|
|
||||||
wg sync.WaitGroup
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewManager creates a new IPC Manager
|
// NewManager creates a new IPC Manager
|
||||||
func NewManager() interfaces.IPCManager {
|
func NewManager() interfaces.IPCManager {
|
||||||
result := &Manager{
|
result := &Manager{
|
||||||
messageQueue: make(chan *ipcMessage, 100),
|
messageQueue: make(chan *ipcMessage, 100),
|
||||||
quitChannel: make(chan struct{}),
|
// quitChannel: make(chan struct{}),
|
||||||
// signals: make(chan os.Signal, 1),
|
// signals: make(chan os.Signal, 1),
|
||||||
log: logger.NewCustomLogger("IPC"),
|
log: logger.NewCustomLogger("IPC"),
|
||||||
}
|
}
|
||||||
@@ -47,12 +44,9 @@ func (i *Manager) Start(eventManager interfaces.EventManager, bindingManager int
|
|||||||
|
|
||||||
i.log.Info("Starting")
|
i.log.Info("Starting")
|
||||||
// signal.Notify(manager.signals, os.Interrupt)
|
// signal.Notify(manager.signals, os.Interrupt)
|
||||||
i.running = true
|
|
||||||
|
|
||||||
// Keep track of this goroutine
|
|
||||||
i.wg.Add(1)
|
|
||||||
go func() {
|
go func() {
|
||||||
for i.running {
|
running := true
|
||||||
|
for running {
|
||||||
select {
|
select {
|
||||||
case incomingMessage := <-i.messageQueue:
|
case incomingMessage := <-i.messageQueue:
|
||||||
i.log.DebugFields("Processing message", logger.Fields{
|
i.log.DebugFields("Processing message", logger.Fields{
|
||||||
@@ -123,22 +117,25 @@ func (i *Manager) Start(eventManager interfaces.EventManager, bindingManager int
|
|||||||
i.log.DebugFields("Finished processing message", logger.Fields{
|
i.log.DebugFields("Finished processing message", logger.Fields{
|
||||||
"1D": &incomingMessage,
|
"1D": &incomingMessage,
|
||||||
})
|
})
|
||||||
case <-i.quitChannel:
|
// case <-manager.quitChannel:
|
||||||
i.running = false
|
// Debug("[MessageQueue] Quit caught")
|
||||||
|
// running = false
|
||||||
|
// case <-manager.signals:
|
||||||
|
// Debug("[MessageQueue] Signal caught")
|
||||||
|
// running = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i.log.Debug("Stopping")
|
i.log.Debug("Stopping")
|
||||||
i.wg.Done()
|
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dispatch receives JSON encoded messages from the renderer.
|
// Dispatch receives JSON encoded messages from the renderer.
|
||||||
// It processes the message to ensure that it is valid and places
|
// It processes the message to ensure that it is valid and places
|
||||||
// the processed message on the message queue
|
// the processed message on the message queue
|
||||||
func (i *Manager) Dispatch(message string, cb interfaces.CallbackFunc) {
|
func (i *Manager) Dispatch(message string) {
|
||||||
|
|
||||||
// Create a new IPC Message
|
// Create a new IPC Message
|
||||||
incomingMessage, err := newIPCMessage(message, i.SendResponse(cb))
|
incomingMessage, err := newIPCMessage(message, i.SendResponse)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
i.log.ErrorFields("Could not understand incoming message! ", map[string]interface{}{
|
i.log.ErrorFields("Could not understand incoming message! ", map[string]interface{}{
|
||||||
"message": message,
|
"message": message,
|
||||||
@@ -158,25 +155,15 @@ func (i *Manager) Dispatch(message string, cb interfaces.CallbackFunc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SendResponse sends the given response back to the frontend
|
// SendResponse sends the given response back to the frontend
|
||||||
// It sends the data back to the correct renderer by way of the provided callback function
|
func (i *Manager) SendResponse(response *ipcResponse) error {
|
||||||
func (i *Manager) SendResponse(cb interfaces.CallbackFunc) func(i *ipcResponse) error {
|
|
||||||
|
|
||||||
return func(response *ipcResponse) error {
|
// Serialise the Message
|
||||||
// Serialise the Message
|
data, err := response.Serialise()
|
||||||
data, err := response.Serialise()
|
if err != nil {
|
||||||
if err != nil {
|
fmt.Printf(err.Error())
|
||||||
fmt.Printf(err.Error())
|
return err
|
||||||
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.quitChannel <- struct{}{}
|
|
||||||
i.log.Debug("Waiting of main loop shutdown")
|
|
||||||
i.wg.Wait()
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,254 @@
|
|||||||
package renderer
|
package renderer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
bridge "github.com/wailsapp/wails/lib/renderer/bridge"
|
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewBridge returns a new Bridge struct
|
type messageType int
|
||||||
func NewBridge() *bridge.Bridge {
|
|
||||||
return &bridge.Bridge{}
|
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 {
|
||||||
|
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.Warn("Close() unsupported in bridge mode")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,222 +0,0 @@
|
|||||||
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 := newSession(conn,
|
|
||||||
h.bindingCache,
|
|
||||||
h.ipcManager,
|
|
||||||
logger.NewCustomLogger("BridgeSession"),
|
|
||||||
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(title string, filter string) 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(title string, filter string) 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 marshal JSON data in event: %s ", err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Double encode data to ensure everything is escaped correctly.
|
|
||||||
data, err = json.Marshal(string(data))
|
|
||||||
if err != nil {
|
|
||||||
h.log.Errorf("Cannot marshal JSON data in event: %s ", err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
message := "window.wails._.Notify('" + event.Name + "'," + string(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")
|
|
||||||
for _, session := range h.sessions {
|
|
||||||
session.Shutdown()
|
|
||||||
}
|
|
||||||
err := h.server.Close()
|
|
||||||
if err != nil {
|
|
||||||
h.log.Errorf(err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package renderer
|
|
||||||
|
|
||||||
// Autogenerated by Mewn - Do not alter
|
|
||||||
|
|
||||||
import "github.com/leaanthony/mewn"
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
mewn.AddAsset(".", "../../runtime/assets/wails.js", "1f8b08000000000000ff94586d8f1bb711fe2b2ba255481f8f91dc14a977c318cee582a838df053ebbfda00a01b53b92e85b915b2e758a20f1bf17b3efba97a2050c7bc519728633cf3c33f468b533a9d7d650c38e8fca45208f216917234f1d3bea1585b95b30077ee74c84df02fe28acf365825bacc42579d4b1e3793c9af246181f43489a4d0637a52acfa96df772cbfb6fcfb815b91c4dfab5e0c5561aee452a817b91c9de550edcb1a317163fd9e974b7fc0aa91719acb481df9c2dc0f943a57604b3db8253cb1ce2d184afc1c72eb0c0bd70727875b233f5ee8c8ca43f146057d1fd61bbb4f9785cff2bbcbdf74e9bf567b51e8f5fb3f85c971f1f55be83987cb4d92e0712187f6d33f9fd77281bb576db6852bbebcfae5f25653a86f1981ae9a9618cff6d0c6d864ca257f43b94125b9922b2bd93198ff18fe82df59b30974e36cea50e94076a7679cef0382f1c75afb9ee38c960a576b9274f235edfc204c6df560e95555cfa201bb6b28e56308ab4890cf322a38e5bde5d17d8b103112c82586a93557e71cb588b2f873132f2399a9fdcf67da7d19f2a1adf43fc82b04330fa059c28c281714073f6494a1ac5264485b3dee225c54695777bd306abae02dc8067149210eea917a59cb040e76718f788cb12228c59ea49823900c61b4f66467bc2e9739f6781b12699c7903489abc34a7e86e56efde2ae5d609dd6ccacec8b4af940e99fca194ce54b7aab81deb573d6bda8950db47e515ee52f6a95ed756c7b1d5befb29cdc1560be7cba7971dfa13dbdd1fb456359bda0b86c0d68395ff4dca7da1c34a1c45cc68663fa962a7d98fd1c7b5ea8436e55164348ce9854afe85e9bcceec55ee9bc5c3a9dade1fdf325b1876569d307f0a20484358b1b25f8c383332a17da3cda07a086712d72306bbff971d2d50cc849023fb482042e2e989ec3821a16e8dfefef6e455d6e7a75a08eb1d0dd2dad11ab28c9ed9af0630e8f90c7866fa12cd51a620803e51dde28a524abb16306a2bc11e90a3043c9aa91ec5b940c855923841a1a4351d98856351e0c0b78cf3d2fcefad2639b9bb64c77793e927e3c6e3e4e27eae5847103fbe83767b7ba04da67de715b675527993d6a692ec825b9d85316f61b9d032de67a5193de8f13867aa92cc17fd65bb03b4f8708b2b4423725572acf236f2372612e48e4f516b2c8eebc883ec1bf7750fa68f6731c910bcd5860dcb3044dc8a3af8ffc55992c8738e50e903a62cb1d94367f84d885c4bb03e6096147f811c94f9bf5adda221633e555fc24cfc82b9a8554f97453c5d29ad2e620aa582330c21008eb33ea7aa4a446a720171543757a073caad15a53f293b3fb129ce8ea6f98c2e5ebba750d1a16f6b2c179ea0e85b7435ac6801b8999fba28dffcbdb0fcea9039d76547fb651acc17f5226b3db7f60a341f4cc278b9798fcdd64f2fdf4ddbbb77ffdeefbef26efde4ddf7c547e235cb597b25011c0b663f4c8d00a5fa3675d77444da44de99549b17f01637ee3ec3e42873f1f0ae800618cf511a62d52519aabb28c5419a9a83d90b040fd4697dc30ee11b197538ebfc555433067cdac9dbd842a8afc50b73fc3f8e5742411f6132925f59772ca42e09bb352b96b4b6533370b897f9d4ef345d31fd0e96d75d30425a2d8951bea06b9bcee3be9139ccd17a2cc75da7aa4dc7ab705e34b562fd329b2af3c9a015221248a127804e309f77565df9f39fb80e610f16d5dc33efaa50d03417d7261181f4d7a7cd79aa369e89dbeeab24eafda794695a55e9bd36918d49e45a709fcd0dd60c8a6d5ddbdec64735824ed3687038b67ff53bff7dc311cd67050f6384c876ec0604d042b30f4610c0dce110a6032790c7cd83fe4f0c7e9d44b7bfd2ac75fe5f116f63fd5b4113f9f8fe60b915a932a4f8d288b5c7b4a0461d56797c4f3939118a16d45d3ae15393949dc0fade0729ab80b39adadd40f04dc377aa096b141729b6a21ad139693489711968e8a1e55aeb3e8ab7a5465ea74e1239d81f17aa5c109c258e2e776814c3fb70b790c5519cded22d4ad1c44610bca1aabfabf5ad5ff9f55bd904ff80afbf0e0d1d4c2a6ab910a037d6e938e6f0df7c8b3dd8cd9f799b3f20769705a5cbf20edb921701f280bbc2590e7d94e8ccc20b5197cf934bbb2dbc21a3098780745ae52a0dffeabbcf876cd0961fdd27c72f94e5dae16c7b701457ffed3b80a823b1c1b4a28942b713e694a12dacb9399a943895a51a1ca12326c91ed0015475dfc413483072722fad8cc2011611d34595293ec8efabaa9d7196c38c4c93ac278aaceb895450bb7b6cf4bd20625faa6b3ea38f9a6cab983b52e3d64a3d188b496cedba61e5ac5ee9a8372ed4060c5591f673c831c3c44e8056f4e786f45dddc69b3c0625ca9ba3c0581f4c802bfb55eaf0ef1b39e83dcdcd395af58bca159c6ebc2ab961ae21a561eaea31fd56c8b95cb30757a983a18a42ea3e76943c7a2128cc7cc99ca3d115d238347c8ec91ac0839d8ae6b51cdc663dff287e35316aac6e343e01fb2ecbe2aa92737ac2f95d9b42a8fe6e9799d03fea2a4ae424c8cf0f0879786779a4b9b1d903dc164571b9d67880e188fafab21686630de57f7f72fb0deabb6fc2107c212c042fce0bdd3cb9d074a90d7092768ffdbb42c09e3202addfb0d807f3ffc21d2b2fc5cf919c3996f4f6ca2ceadcda07abcf7c20da8ec74ea7eaec137ce953f1d3eab6af0a30495080e3aeccc427d6bede319867af6dbd50dc2da803b8b80aebb3c4e82fc561e6fec3a76bc19d262cbabe496f1f1ce3cc9d25df368bd331f77b9d7450ef11dbfde6a1f5ff35f4139bf04759ed9fef184f34a728f3818f056554433e3c13daabc7aa3227b399cb5bbd5e1b08db34860950f1fd20763f739646b889fbcbb466866309365dd2ca6fa4dd1cee0b78936ade3035e309c7c831c8707518cd2eff1d7c18c32434386b27075f6c6e3b7ac6dc1d654257efe1f569e57cf8ee1167163d7a2e9456fdebc79135da9dd7ae3a32f6653314956134e8432c2f86b5b7bc2c4d9e835ad2f9f6e50035ed7b8d106a25b8b5afe75ad2b9befb6a6d173afeb5521401dcb02bfc687a0cecb185fcb901116162cf94f000000ffff04075a367c140000")
|
|
||||||
}
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
package renderer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"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
|
|
||||||
shutdown chan bool
|
|
||||||
writeChan chan []byte
|
|
||||||
|
|
||||||
done bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func newSession(conn *websocket.Conn, bindingCache []string, ipc interfaces.IPCManager, logger *logger.CustomLogger, eventMgr interfaces.EventManager) *session {
|
|
||||||
return &session{
|
|
||||||
conn: conn,
|
|
||||||
bindingCache: bindingCache,
|
|
||||||
ipc: ipc,
|
|
||||||
log: logger,
|
|
||||||
eventManager: eventMgr,
|
|
||||||
shutdown: make(chan bool),
|
|
||||||
writeChan: make(chan []byte, 100),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 {
|
|
||||||
if !s.done {
|
|
||||||
s.writeChan <- *(*[]byte)(unsafe.Pointer(&msg))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *session) start(firstSession bool) {
|
|
||||||
s.log.Infof("Connected to frontend.")
|
|
||||||
go s.writePump()
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
if s.done {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shutdown
|
|
||||||
func (s *session) Shutdown() {
|
|
||||||
s.done = true
|
|
||||||
s.shutdown <- true
|
|
||||||
s.log.Debugf("session %v exit", s.Identifier())
|
|
||||||
}
|
|
||||||
|
|
||||||
// writePump pulls messages from the writeChan and sends them to the client
|
|
||||||
// since it uses a channel to read the messages the socket is protected without locks
|
|
||||||
func (s *session) writePump() {
|
|
||||||
s.log.Debugf("Session %v - writePump start", s.Identifier())
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case msg, ok := <-s.writeChan:
|
|
||||||
s.conn.SetWriteDeadline(time.Now().Add(1 * time.Second))
|
|
||||||
if !ok {
|
|
||||||
s.log.Debug("writeChan was closed!")
|
|
||||||
s.conn.WriteMessage(websocket.CloseMessage, []byte{})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := s.conn.WriteMessage(websocket.TextMessage, msg); err != nil {
|
|
||||||
s.log.Debug(err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case <-s.shutdown:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.log.Debug("writePump exiting...")
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user