mirror of
https://github.com/taigrr/wails.git
synced 2026-04-09 08:31:31 -07:00
Compare commits
7 Commits
116-Add-br
...
update-com
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6fafd165de | ||
|
|
5ca7bfca66 | ||
|
|
3f32c45f77 | ||
|
|
f8c805649a | ||
|
|
3ac993b01f | ||
|
|
216c84b9cf | ||
|
|
e99fffe340 |
@@ -1,42 +0,0 @@
|
|||||||
{{ if .Versions -}}
|
|
||||||
<a name="unreleased"></a>
|
|
||||||
## [Unreleased]
|
|
||||||
|
|
||||||
{{ if .Unreleased.CommitGroups -}}
|
|
||||||
{{ range .Unreleased.CommitGroups -}}
|
|
||||||
### {{ .Title }}
|
|
||||||
{{ range .Commits -}}
|
|
||||||
- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }}
|
|
||||||
{{ end }}
|
|
||||||
{{ end -}}
|
|
||||||
{{ end -}}
|
|
||||||
{{ end -}}
|
|
||||||
|
|
||||||
{{ range .Versions }}
|
|
||||||
<a name="{{ .Tag.Name }}"></a>
|
|
||||||
## {{ if .Tag.Previous }}[{{ .Tag.Name }}]{{ else }}{{ .Tag.Name }}{{ end }} - {{ datetime "2006-01-02" .Tag.Date }}
|
|
||||||
{{ range .CommitGroups -}}
|
|
||||||
### {{ .Title }}
|
|
||||||
{{ range .Commits -}}
|
|
||||||
- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }}
|
|
||||||
{{ end }}
|
|
||||||
{{ end -}}
|
|
||||||
|
|
||||||
{{- if .NoteGroups -}}
|
|
||||||
{{ range .NoteGroups -}}
|
|
||||||
### {{ .Title }}
|
|
||||||
{{ range .Notes }}
|
|
||||||
{{ .Body }}
|
|
||||||
{{ end }}
|
|
||||||
{{ end -}}
|
|
||||||
{{ end -}}
|
|
||||||
{{ end -}}
|
|
||||||
|
|
||||||
{{- if .Versions }}
|
|
||||||
[Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ $latest := index .Versions 0 }}{{ $latest.Tag.Name }}...HEAD
|
|
||||||
{{ range .Versions -}}
|
|
||||||
{{ if .Tag.Previous -}}
|
|
||||||
[{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }}
|
|
||||||
{{ end -}}
|
|
||||||
{{ end -}}
|
|
||||||
{{ end -}}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
style: github
|
|
||||||
template: CHANGELOG.tpl.md
|
|
||||||
info:
|
|
||||||
title: CHANGELOG
|
|
||||||
repository_url: https://github.com/wailsapp/wails
|
|
||||||
options:
|
|
||||||
commits:
|
|
||||||
# filters:
|
|
||||||
# Type:
|
|
||||||
# - feat
|
|
||||||
# - fix
|
|
||||||
# - perf
|
|
||||||
# - refactor
|
|
||||||
commit_groups:
|
|
||||||
# title_maps:
|
|
||||||
# feat: Features
|
|
||||||
# fix: Bug Fixes
|
|
||||||
# perf: Performance Improvements
|
|
||||||
# refactor: Code Refactoring
|
|
||||||
header:
|
|
||||||
pattern: "^(\\w*)\\:\\s(.*)$"
|
|
||||||
pattern_maps:
|
|
||||||
- Type
|
|
||||||
- Subject
|
|
||||||
notes:
|
|
||||||
keywords:
|
|
||||||
- BREAKING CHANGE
|
|
||||||
35
.github/ISSUE_TEMPLATE/bug_report.md
vendored
35
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,35 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug report
|
|
||||||
about: Create a report to help us improve
|
|
||||||
title: ''
|
|
||||||
labels: bug
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
#####################################################
|
|
||||||
If you have a technical issue, please do not open a bug this way!
|
|
||||||
Please use the `wails issue` command!
|
|
||||||
#####################################################
|
|
||||||
|
|
||||||
**Description**
|
|
||||||
A clear and concise description of what the bug is.
|
|
||||||
|
|
||||||
**To Reproduce**
|
|
||||||
Steps to reproduce the behaviour:
|
|
||||||
1. Go to '...'
|
|
||||||
2. Click on '....'
|
|
||||||
3. Scroll down to '....'
|
|
||||||
4. See error
|
|
||||||
|
|
||||||
**Expected behaviour**
|
|
||||||
A clear and concise description of what you expected to happen.
|
|
||||||
|
|
||||||
**Screenshots**
|
|
||||||
If applicable, add screenshots to help explain your problem.
|
|
||||||
|
|
||||||
**System Details**
|
|
||||||
Please provide your platform, GO version and variables, etc
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context about the problem here.
|
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -15,5 +15,4 @@ examples/**/example*
|
|||||||
!examples/**/*.*
|
!examples/**/*.*
|
||||||
cmd/wails/wails
|
cmd/wails/wails
|
||||||
.DS_Store
|
.DS_Store
|
||||||
tmp
|
tmp
|
||||||
dist
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
# This is an example goreleaser.yaml file with some sane defaults.
|
|
||||||
# Make sure to check the documentation at http://goreleaser.com
|
|
||||||
|
|
||||||
builds:
|
|
||||||
- env:
|
|
||||||
- CGO_ENABLED=0
|
|
||||||
goos:
|
|
||||||
- windows
|
|
||||||
- linux
|
|
||||||
- darwin
|
|
||||||
goarch:
|
|
||||||
- 386
|
|
||||||
- amd64
|
|
||||||
ignore:
|
|
||||||
- goos: darwin
|
|
||||||
goarch: 386
|
|
||||||
main: ./cmd/wails/main.go
|
|
||||||
archive:
|
|
||||||
replacements:
|
|
||||||
darwin: Darwin
|
|
||||||
linux: Linux
|
|
||||||
windows: Windows
|
|
||||||
386: i386
|
|
||||||
amd64: x86_64
|
|
||||||
checksum:
|
|
||||||
name_template: 'checksums.txt'
|
|
||||||
snapshot:
|
|
||||||
name_template: "{{ .Tag }}-next"
|
|
||||||
changelog:
|
|
||||||
sort: asc
|
|
||||||
filters:
|
|
||||||
exclude:
|
|
||||||
- '^docs:'
|
|
||||||
- '^test:'
|
|
||||||
26
.vscode/launch.json
vendored
26
.vscode/launch.json
vendored
@@ -5,36 +5,14 @@
|
|||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "Wails Init",
|
"name": "Launch",
|
||||||
"type": "go",
|
"type": "go",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"mode": "auto",
|
"mode": "auto",
|
||||||
"program": "${workspaceFolder}/cmd/wails/main.go",
|
"program": "${workspaceFolder}/cmd/wails/main.go",
|
||||||
"env": {},
|
"env": {},
|
||||||
"cwd": "/tmp",
|
|
||||||
"args": [
|
"args": [
|
||||||
"init",
|
"setup"
|
||||||
"-name",
|
|
||||||
"runtime",
|
|
||||||
"-dir",
|
|
||||||
"runtime",
|
|
||||||
"-output",
|
|
||||||
"runtime",
|
|
||||||
"-template",
|
|
||||||
"vuebasic"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Wails Update Pre",
|
|
||||||
"type": "go",
|
|
||||||
"request": "launch",
|
|
||||||
"mode": "auto",
|
|
||||||
"program": "${workspaceFolder}/cmd/wails/main.go",
|
|
||||||
"env": {},
|
|
||||||
"cwd": "/tmp",
|
|
||||||
"args": [
|
|
||||||
"update",
|
|
||||||
"-pre"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"go.formatTool": "goimports"
|
|
||||||
}
|
|
||||||
28
CHANGELOG.md
28
CHANGELOG.md
@@ -1,28 +0,0 @@
|
|||||||
2019-06-18 **v0.16.0**
|
|
||||||
* React template FTW! - Thanks [admin_3.exe](https://github.com/bh90210)!
|
|
||||||
* Updated contributors
|
|
||||||
* Arch Linux detection without lsb-release
|
|
||||||
* Removed deprecated methods for dealing with JS/CSS in the backend
|
|
||||||
|
|
||||||
2019-05-29 **v0.14.11-pre**
|
|
||||||
* Windows fix for spinner
|
|
||||||
|
|
||||||
2019-05-29 **v0.14.10-pre**
|
|
||||||
* Windows fix for Vuetify
|
|
||||||
|
|
||||||
2019-05-29 **v0.14.9-pre**
|
|
||||||
* Vuetify project template 🎉
|
|
||||||
|
|
||||||
2019-05-29 **v0.14.8-pre**
|
|
||||||
* Updated Ubuntu npm install command
|
|
||||||
|
|
||||||
2019-05-22 **v0.14.7-pre**
|
|
||||||
* New projects are built automatically when initialised
|
|
||||||
* Go 1.12 is now a minimum requirement
|
|
||||||
|
|
||||||
2019-05-21 **v0.14.6-pre**
|
|
||||||
* Hotfix for module dependency issue
|
|
||||||
|
|
||||||
2019-05-20 **v0.14.5-pre**
|
|
||||||
* Added developer tooling - New Template Generator
|
|
||||||
* Documentation fixes - Thanks [admin_3.exe](https://github.com/bh90210)!
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
# Contributors
|
|
||||||
|
|
||||||
Wails is what it is because of the time and effort given by these great people. A huge thank you to each and every one!
|
|
||||||
|
|
||||||
* [Dustin Krysak](https://wiki.ubuntu.com/bashfulrobot)
|
|
||||||
* [Qais Patankar](https://github.com/qaisjp)
|
|
||||||
* [Anthony Lee](https://github.com/alee792)
|
|
||||||
* [Adrian Lanzafame](https://github.com/lanzafame)
|
|
||||||
* [0xflotus](https://github.com/0xflotus)
|
|
||||||
* [Michael D Henderson](https://github.com/mdhender)
|
|
||||||
* [fred2104](https://github.com/fishfishfish2104)
|
|
||||||
* [intelwalk](https://github.com/intelwalk)
|
|
||||||
* [Mark Stenglein](https://github.com/ocelotsloth)
|
|
||||||
* [admin_3.exe](https://github.com/bh90210)
|
|
||||||
125
README.md
125
README.md
@@ -1,124 +1 @@
|
|||||||
<p align="center" style="text-align: center">
|
# Coming Soon
|
||||||
<img src="https://github.com/wailsapp/docs/raw/master/.vuepress/public/media/logo_cropped.png" width="40%"><br/>
|
|
||||||
</p>
|
|
||||||
<p align="center">
|
|
||||||
A framework for building desktop applications using Go & Web Technologies.<br/><br/>
|
|
||||||
<a href="https://github.com/wailsapp/wails/blob/master/LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg"></a>
|
|
||||||
<a href="https://goreportcard.com/report/github.com/wailsapp/wails"><img src="https://goreportcard.com/badge/github.com/wailsapp/wails"/></a>
|
|
||||||
<a href="http://godoc.org/github.com/wailsapp/wails"><img src="https://img.shields.io/badge/godoc-reference-blue.svg"/></a>
|
|
||||||
<a href="https://www.codefactor.io/repository/github/wailsapp/wails"><img src="https://www.codefactor.io/repository/github/wailsapp/wails/badge" alt="CodeFactor" /></a>
|
|
||||||
<a href="https://github.com/wailsapp/wails/issues"><img src="https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat" alt="CodeFactor" /></a>
|
|
||||||
<a href="https://houndci.com"><img src="https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg"/></a>
|
|
||||||
<a href="https://github.com/avelino/awesome-go" rel="nofollow"><img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome"></a>
|
|
||||||
<a href="https://dashboard.guardrails.io/default/gh/wailsapp/wails"><img src="https://badges.guardrails.io/wailsapp/wails.svg?token=53657bc22ec360d7673c894fdd70568e918ec581d10d84427ed4de5fe1eeff1a"></a>
|
|
||||||
</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!
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Use standard Go libraries/frameworks for the backend
|
|
||||||
- Use any frontend technology to build your UI
|
|
||||||
- Quickly create Vue, Vuetify or React frontends for your Go programs
|
|
||||||
- Expose Go methods/functions to the frontend via a single bind command
|
|
||||||
- Uses native rendering engines - no embedded browser
|
|
||||||
- Shared events system
|
|
||||||
- Native file dialogs
|
|
||||||
- Powerful cli tool
|
|
||||||
- Multiplatform
|
|
||||||
|
|
||||||
## Project Status
|
|
||||||
|
|
||||||
Wails is currently in Beta. Please make sure you read the [Project Status](https://wails.app/project_status.html) if you are interested in using this project.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
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.12
|
|
||||||
- npm
|
|
||||||
|
|
||||||
### MacOS
|
|
||||||
|
|
||||||
Make sure you have the xcode command line tools installed. This can be done by running:
|
|
||||||
|
|
||||||
`xcode-select --install`
|
|
||||||
|
|
||||||
### Linux
|
|
||||||
|
|
||||||
#### Ubuntu 18.04
|
|
||||||
|
|
||||||
`sudo apt install pkg-config build-essential libgtk-3-dev libwebkit2gtk-4.0-dev`
|
|
||||||
|
|
||||||
#### Arch Linux
|
|
||||||
|
|
||||||
`sudo pacman -S webkit2gtk gtk3`
|
|
||||||
|
|
||||||
#### Red Hat Based Distros
|
|
||||||
|
|
||||||
`sudo yum install webkit2gtk-devel gtk3-devel`
|
|
||||||
|
|
||||||
Note: If you have successfully installed these dependencies on a different flavour of Linux, please consider submitting a PR.
|
|
||||||
|
|
||||||
### Windows
|
|
||||||
|
|
||||||
Windows requires gcc and related tooling. The recommended download is from [http://tdm-gcc.tdragon.net/download](http://tdm-gcc.tdragon.net/download). Once this is installed, you are good to go.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
**Ensure Go modules are enabled: GO111MODULE=on and go/bin is in your PATH variable.**
|
|
||||||
|
|
||||||
Installation is as simple as running the following command:
|
|
||||||
|
|
||||||
<pre style='color:white'>
|
|
||||||
go get github.com/wailsapp/wails/cmd/wails
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
## Next Steps
|
|
||||||
|
|
||||||
It is recommended at this stage to read the comprehensive documentation at [https://wails.app](https://wails.app).
|
|
||||||
|
|
||||||
## FAQ
|
|
||||||
|
|
||||||
* Is this an alternative to Electron?
|
|
||||||
|
|
||||||
Depends on your requirements. It's designed to make it easy for Go programmers to make lightweight desktop applications or add a frontend to their existing applications. Whilst Wails does not currently offer hooks into native elements such as menus, this may change in the future.
|
|
||||||
|
|
||||||
* Who is this project aimed at?
|
|
||||||
|
|
||||||
Go programmers who want to bundle an HTML/JS/CSS frontend with their applications, without resorting to creating a server and opening a browser to view it.
|
|
||||||
|
|
||||||
* What's with the name?
|
|
||||||
|
|
||||||
When I saw WebView, I thought "What I really want is tooling around building a WebView app, a bit like Rails is to Ruby". So initially it was a play on words (Webview on Rails). It just so happened to also be a homophone of the English name for the [Country](https://en.wikipedia.org/wiki/Wales) I am from. So it stuck.
|
|
||||||
|
|
||||||
## Shoulders of Giants
|
|
||||||
|
|
||||||
Without the following people, this project would never have existed:
|
|
||||||
|
|
||||||
* [Dustin Krysak](https://wiki.ubuntu.com/bashfulrobot) - His support and feedback has been immense. More patience than you can throw a stick at (Not long now Dustin!).
|
|
||||||
* [Serge Zaitsev](https://github.com/zserge) - Creator of [Webview](https://github.com/zserge/webview) which Wails uses for the windowing.
|
|
||||||
|
|
||||||
And without [these people](CONTRIBUTORS.md), it wouldn't be what it is today. A huge thank you to each and every one of you!
|
|
||||||
|
|
||||||
Special Mentions:
|
|
||||||
|
|
||||||
* [Bill Kennedy](https://twitter.com/goinggodotnet) - Go guru, encourager and all-round nice guy, whose infectious energy and inspiration powered me on when I had none left.
|
|
||||||
* [Mark Bates](https://github.com/markbates) - Creator of [Packr](https://github.com/gobuffalo/packr), inspiration for packing strategies which fed into some of the tooling.
|
|
||||||
|
|
||||||
This project was mainly coded to the following albums:
|
|
||||||
|
|
||||||
* [Manic Street Preachers - Resistance Is Futile](https://open.spotify.com/album/1R2rsEUqXjIvAbzM0yHrxA)
|
|
||||||
* [Manic Street Preachers - This Is My Truth, Tell Me Yours](https://open.spotify.com/album/4VzCL9kjhgGQeKCiojK1YN)
|
|
||||||
* [The Midnight - Endless Summer](https://open.spotify.com/album/4Krg8zvprquh7TVn9OxZn8)
|
|
||||||
* [Gary Newman - Savage (Songs from a Broken World)](https://open.spotify.com/album/3kMfsD07Q32HRWKRrpcexr)
|
|
||||||
* [Steve Vai - Passion & Warfare](https://open.spotify.com/album/0oL0OhrE2rYVns4IGj8h2m)
|
|
||||||
* [Ben Howard - Every Kingdom](https://open.spotify.com/album/1nJsbWm3Yy2DW1KIc1OKle)
|
|
||||||
* [Ben Howard - Noonday Dream](https://open.spotify.com/album/6astw05cTiXEc2OvyByaPs)
|
|
||||||
* [Adwaith - Melyn](https://open.spotify.com/album/2vBE40Rp60tl7rNqIZjaXM)
|
|
||||||
* [Gwidaith Hen Fran - Cedors Hen Wrach](https://open.spotify.com/album/3v2hrfNGINPLuDP0YDTOjm)
|
|
||||||
* [Metallica - Metallica](https://open.spotify.com/album/2Kh43m04B1UkVcpcRa1Zug)
|
|
||||||
* [Bloc Party - Silent Alarm](https://open.spotify.com/album/6SsIdN05HQg2GwYLfXuzLB)
|
|
||||||
* [Maxthor - Another World](https://open.spotify.com/album/3tklE2Fgw1hCIUstIwPBJF)
|
|
||||||
* [Alun Tan Lan - Y Distawrwydd](https://open.spotify.com/album/0c32OywcLpdJCWWMC6vB8v)
|
|
||||||
|
|
||||||
33
app.go
33
app.go
@@ -22,6 +22,11 @@ type App struct {
|
|||||||
bindingManager *bindingManager // Handles binding of Go code to renderer
|
bindingManager *bindingManager // Handles binding of Go code to renderer
|
||||||
eventManager *eventManager // Handles all the events
|
eventManager *eventManager // Handles all the events
|
||||||
runtime *Runtime // The runtime object for registered structs
|
runtime *Runtime // The runtime object for registered structs
|
||||||
|
|
||||||
|
// This is a list of all the JS/CSS that needs injecting
|
||||||
|
// It will get injected in order
|
||||||
|
jsCache []string
|
||||||
|
cssCache []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateApp creates the application window with the given configuration
|
// CreateApp creates the application window with the given configuration
|
||||||
@@ -65,11 +70,7 @@ func (a *App) Run() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
a.logLevel = "error"
|
a.logLevel = "error"
|
||||||
err := a.start()
|
return a.start()
|
||||||
if err != nil {
|
|
||||||
a.log.Error(err.Error())
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) start() error {
|
func (a *App) start() error {
|
||||||
@@ -106,8 +107,16 @@ func (a *App) start() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Inject CSS
|
||||||
|
a.renderer.AddCSSList(a.cssCache)
|
||||||
|
|
||||||
|
// Inject JS
|
||||||
|
a.renderer.AddJSList(a.jsCache)
|
||||||
|
|
||||||
// Run the renderer
|
// Run the renderer
|
||||||
return a.renderer.Run()
|
a.renderer.Run()
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind allows the user to bind the given object
|
// Bind allows the user to bind the given object
|
||||||
@@ -115,3 +124,15 @@ func (a *App) start() error {
|
|||||||
func (a *App) Bind(object interface{}) {
|
func (a *App) Bind(object interface{}) {
|
||||||
a.bindingManager.bind(object)
|
a.bindingManager.bind(object)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddJS adds a piece of Javascript to a cache that
|
||||||
|
// gets injected at runtime
|
||||||
|
func (a *App) AddJS(js string) {
|
||||||
|
a.jsCache = append(a.jsCache, js)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddCSS adds a CSS string to a cache that
|
||||||
|
// gets injected at runtime
|
||||||
|
func (a *App) AddCSS(js string) {
|
||||||
|
a.cssCache = append(a.cssCache, js)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package wails
|
package wails
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/cmd"
|
"github.com/wailsapp/wails/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -9,7 +11,6 @@ func (app *App) setupCli() *cmd.Cli {
|
|||||||
|
|
||||||
// Create a new cli
|
// Create a new cli
|
||||||
result := cmd.NewCli(app.config.Title, "Debug build")
|
result := cmd.NewCli(app.config.Title, "Debug build")
|
||||||
result.Version(cmd.Version)
|
|
||||||
|
|
||||||
// Setup cli to handle loglevel and headless flags
|
// Setup cli to handle loglevel and headless flags
|
||||||
result.
|
result.
|
||||||
@@ -20,6 +21,8 @@ func (app *App) setupCli() *cmd.Cli {
|
|||||||
// Banner
|
// Banner
|
||||||
result.PreRun(func(cli *cmd.Cli) error {
|
result.PreRun(func(cli *cmd.Cli) error {
|
||||||
log := cmd.NewLogger()
|
log := cmd.NewLogger()
|
||||||
|
log.PrintSmallBanner()
|
||||||
|
fmt.Println()
|
||||||
log.YellowUnderline(app.config.Title + " - Debug Build")
|
log.YellowUnderline(app.config.Title + " - Debug Build")
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ func (a *AppConfig) merge(in *AppConfig) error {
|
|||||||
a.HTML = strings.TrimSpace(inlineHTML)
|
a.HTML = strings.TrimSpace(inlineHTML)
|
||||||
|
|
||||||
// Deduce whether this is a full html page or a fragment
|
// Deduce whether this is a full html page or a fragment
|
||||||
// The document is determined to be a fragment if an HTML
|
// The document is determined to be a fragment if an HMTL
|
||||||
// tag exists and is located before the first div tag
|
// tag exists and is located before the first div tag
|
||||||
HTMLTagIndex := strings.Index(a.HTML, "<html")
|
HTMLTagIndex := strings.Index(a.HTML, "<html")
|
||||||
DivTagIndex := strings.Index(a.HTML, "<div")
|
DivTagIndex := strings.Index(a.HTML, "<div")
|
||||||
|
|||||||
@@ -153,11 +153,8 @@ func (b *boundFunction) setInputValue(index int, typ reflect.Type, val interface
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Translate javascript null values
|
// Do the conversion
|
||||||
if val == nil {
|
result = reflect.ValueOf(val).Convert(typ)
|
||||||
result = reflect.Zero(typ)
|
|
||||||
} else {
|
|
||||||
result = reflect.ValueOf(val).Convert(typ)
|
|
||||||
}
|
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
package wails
|
|
||||||
|
|
||||||
import "strings"
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
type internalMethods struct{
|
|
||||||
log *CustomLogger
|
|
||||||
browser *RuntimeBrowser
|
|
||||||
}
|
|
||||||
|
|
||||||
func newInternalMethods() *internalMethods {
|
|
||||||
return &internalMethods{
|
|
||||||
log: newCustomLogger("InternalCall"),
|
|
||||||
browser: newRuntimeBrowser(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *internalMethods) processCall(callData *callData) (interface{}, error) {
|
|
||||||
if !strings.HasPrefix(callData.BindingName, ".wails.") {
|
|
||||||
return nil, fmt.Errorf("Invalid call signature '%s'", callData.BindingName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Strip prefix
|
|
||||||
var splitCall = strings.Split(callData.BindingName,".")[2:]
|
|
||||||
if len(splitCall) != 2 {
|
|
||||||
return nil, fmt.Errorf("Invalid call signature '%s'", callData.BindingName)
|
|
||||||
}
|
|
||||||
|
|
||||||
group := splitCall[0]
|
|
||||||
switch group {
|
|
||||||
case "Browser":
|
|
||||||
return i.processBrowserCommand(splitCall[1], callData.Data)
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("Unknown internal command group '%s'", group)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *internalMethods) processBrowserCommand(command string, data interface{}) (interface{}, error) {
|
|
||||||
switch command {
|
|
||||||
case "OpenURL":
|
|
||||||
url := data.(string)
|
|
||||||
// Strip string quotes. Credit: https://stackoverflow.com/a/44222648
|
|
||||||
if url[0] == '"' {
|
|
||||||
url = url[1:]
|
|
||||||
}
|
|
||||||
if i := len(url)-1; url[i] == '"' {
|
|
||||||
url = url[:i]
|
|
||||||
}
|
|
||||||
i.log.Debugf("Calling Browser.OpenURL with '%s'", url)
|
|
||||||
return nil, i.browser.OpenURL(url)
|
|
||||||
case "OpenFile":
|
|
||||||
filename := data.(string)
|
|
||||||
// Strip string quotes. Credit: https://stackoverflow.com/a/44222648
|
|
||||||
if filename[0] == '"' {
|
|
||||||
filename = filename[1:]
|
|
||||||
}
|
|
||||||
if i := len(filename)-1; filename[i] == '"' {
|
|
||||||
filename = filename[:i]
|
|
||||||
}
|
|
||||||
i.log.Debugf("Calling Browser.OpenFile with '%s'", filename)
|
|
||||||
return nil, i.browser.OpenFile(filename)
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("Unknown Browser command '%s'", command)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -17,7 +17,6 @@ binding:
|
|||||||
type bindingManager struct {
|
type bindingManager struct {
|
||||||
methods map[string]*boundMethod
|
methods map[string]*boundMethod
|
||||||
functions map[string]*boundFunction
|
functions map[string]*boundFunction
|
||||||
internalMethods *internalMethods
|
|
||||||
initMethods []*boundMethod
|
initMethods []*boundMethod
|
||||||
log *CustomLogger
|
log *CustomLogger
|
||||||
renderer Renderer
|
renderer Renderer
|
||||||
@@ -28,10 +27,9 @@ type bindingManager struct {
|
|||||||
|
|
||||||
func newBindingManager() *bindingManager {
|
func newBindingManager() *bindingManager {
|
||||||
result := &bindingManager{
|
result := &bindingManager{
|
||||||
methods: make(map[string]*boundMethod),
|
methods: make(map[string]*boundMethod),
|
||||||
functions: make(map[string]*boundFunction),
|
functions: make(map[string]*boundFunction),
|
||||||
log: newCustomLogger("Bind"),
|
log: newCustomLogger("Bind"),
|
||||||
internalMethods: newInternalMethods(),
|
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -165,11 +163,6 @@ func (b *bindingManager) bind(object interface{}) {
|
|||||||
b.objectsToBind = append(b.objectsToBind, object)
|
b.objectsToBind = append(b.objectsToBind, object)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bindingManager) processInternalCall(callData *callData) (interface{}, error) {
|
|
||||||
// Strip prefix
|
|
||||||
return b.internalMethods.processCall(callData)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *bindingManager) processFunctionCall(callData *callData) (interface{}, error) {
|
func (b *bindingManager) processFunctionCall(callData *callData) (interface{}, error) {
|
||||||
// Return values
|
// Return values
|
||||||
var result []reflect.Value
|
var result []reflect.Value
|
||||||
@@ -261,8 +254,6 @@ func (b *bindingManager) processCall(callData *callData) (result interface{}, er
|
|||||||
result, err = b.processFunctionCall(callData)
|
result, err = b.processFunctionCall(callData)
|
||||||
case 2:
|
case 2:
|
||||||
result, err = b.processMethodCall(callData)
|
result, err = b.processMethodCall(callData)
|
||||||
case 3:
|
|
||||||
result, err = b.processInternalCall(callData)
|
|
||||||
default:
|
default:
|
||||||
result = nil
|
result = nil
|
||||||
err = fmt.Errorf("Invalid binding name '%s'", callData.BindingName)
|
err = fmt.Errorf("Invalid binding name '%s'", callData.BindingName)
|
||||||
|
|||||||
20
cmd/cli.go
20
cmd/cli.go
@@ -96,7 +96,6 @@ type Command struct {
|
|||||||
flagCount int
|
flagCount int
|
||||||
log *Logger
|
log *Logger
|
||||||
helpFlag bool
|
helpFlag bool
|
||||||
hidden bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCommand creates a new Command
|
// NewCommand creates a new Command
|
||||||
@@ -107,7 +106,6 @@ func NewCommand(name string, description string, app *Cli, parentCommandPath str
|
|||||||
SubCommandsMap: make(map[string]*Command),
|
SubCommandsMap: make(map[string]*Command),
|
||||||
App: app,
|
App: app,
|
||||||
log: NewLogger(),
|
log: NewLogger(),
|
||||||
hidden: false,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up command path
|
// Set up command path
|
||||||
@@ -197,7 +195,10 @@ func (c *Command) Action(callback Action) *Command {
|
|||||||
// PrintHelp - Output the help text for this command
|
// PrintHelp - Output the help text for this command
|
||||||
func (c *Command) PrintHelp() {
|
func (c *Command) PrintHelp() {
|
||||||
c.log.PrintBanner()
|
c.log.PrintBanner()
|
||||||
|
versionString := c.AppVersion
|
||||||
|
if versionString != "" {
|
||||||
|
versionString = " " + versionString
|
||||||
|
}
|
||||||
commandTitle := c.CommandPath
|
commandTitle := c.CommandPath
|
||||||
if c.Shortdescription != "" {
|
if c.Shortdescription != "" {
|
||||||
commandTitle += " - " + c.Shortdescription
|
commandTitle += " - " + c.Shortdescription
|
||||||
@@ -214,9 +215,6 @@ func (c *Command) PrintHelp() {
|
|||||||
c.log.White("Available commands:")
|
c.log.White("Available commands:")
|
||||||
fmt.Println("")
|
fmt.Println("")
|
||||||
for _, subcommand := range c.SubCommands {
|
for _, subcommand := range c.SubCommands {
|
||||||
if subcommand.isHidden() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
spacer := strings.Repeat(" ", 3+c.longestSubcommand-len(subcommand.Name))
|
spacer := strings.Repeat(" ", 3+c.longestSubcommand-len(subcommand.Name))
|
||||||
isDefault := ""
|
isDefault := ""
|
||||||
if subcommand.isDefaultCommand() {
|
if subcommand.isDefaultCommand() {
|
||||||
@@ -242,16 +240,6 @@ func (c *Command) isDefaultCommand() bool {
|
|||||||
return c.App.defaultCommand == c
|
return c.App.defaultCommand == c
|
||||||
}
|
}
|
||||||
|
|
||||||
// isHidden returns true if the command is a hidden command
|
|
||||||
func (c *Command) isHidden() bool {
|
|
||||||
return c.hidden
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hidden hides the command from the Help system
|
|
||||||
func (c *Command) Hidden() {
|
|
||||||
c.hidden = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command - Defines a subcommand
|
// Command - Defines a subcommand
|
||||||
func (c *Command) Command(name, description string) *Command {
|
func (c *Command) Command(name, description string) *Command {
|
||||||
result := NewCommand(name, description, c.App, c.CommandPath)
|
result := NewCommand(name, description, c.App, c.CommandPath)
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
84
cmd/fs.go
84
cmd/fs.go
@@ -1,19 +1,13 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/leaanthony/slicer"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// FSHelper - Wrapper struct for File System utility commands
|
// FSHelper - Wrapper struct for File System utility commands
|
||||||
@@ -47,14 +41,6 @@ func (fs *FSHelper) FileExists(path string) bool {
|
|||||||
return fi.Mode().IsRegular()
|
return fi.Mode().IsRegular()
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateFile creates a file at the given filename location with the contents
|
|
||||||
// set to the given data. It will create intermediary directories if needed.
|
|
||||||
func (fs *FSHelper) CreateFile(filename string, data []byte) error {
|
|
||||||
// Ensure directory exists
|
|
||||||
fs.MkDirs(filepath.Dir(filename))
|
|
||||||
return ioutil.WriteFile(filename, data, 0644)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MkDirs creates the given nested directories.
|
// MkDirs creates the given nested directories.
|
||||||
// Returns error on failure
|
// Returns error on failure
|
||||||
func (fs *FSHelper) MkDirs(fullPath string, mode ...os.FileMode) error {
|
func (fs *FSHelper) MkDirs(fullPath string, mode ...os.FileMode) error {
|
||||||
@@ -110,33 +96,11 @@ func (fs *FSHelper) RemoveFiles(files []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dir holds information about a directory
|
|
||||||
type Dir struct {
|
|
||||||
localPath string
|
|
||||||
fullPath string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Directory creates a new Dir struct with the given directory path
|
|
||||||
func (fs *FSHelper) Directory(dir string) (*Dir, error) {
|
|
||||||
fullPath, err := filepath.Abs(dir)
|
|
||||||
return &Dir{fullPath: fullPath}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// LocalDir creates a new Dir struct based on a path relative to the caller
|
|
||||||
func (fs *FSHelper) LocalDir(dir string) (*Dir, error) {
|
|
||||||
_, filename, _, _ := runtime.Caller(1)
|
|
||||||
fullPath, err := filepath.Abs(filepath.Join(path.Dir(filename), dir))
|
|
||||||
return &Dir{
|
|
||||||
localPath: dir,
|
|
||||||
fullPath: fullPath,
|
|
||||||
}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 (fs *FSHelper) GetSubdirs(dir string) (map[string]string, error) {
|
||||||
|
|
||||||
// Read in the directory information
|
// Read in the directory information
|
||||||
fileInfo, err := ioutil.ReadDir(d.fullPath)
|
fileInfo, err := ioutil.ReadDir(dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -148,65 +112,25 @@ func (d *Dir) GetSubdirs() (map[string]string, error) {
|
|||||||
// map["directoryName"] = "path/to/directoryName"
|
// map["directoryName"] = "path/to/directoryName"
|
||||||
for _, file := range fileInfo {
|
for _, file := range fileInfo {
|
||||||
if file.IsDir() {
|
if file.IsDir() {
|
||||||
subdirs[file.Name()] = filepath.Join(d.fullPath, file.Name())
|
subdirs[file.Name()] = filepath.Join(dir, file.Name())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return subdirs, nil
|
return subdirs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllFilenames returns all filename in and below this directory
|
|
||||||
func (d *Dir) GetAllFilenames() (*slicer.StringSlicer, error) {
|
|
||||||
result := slicer.String()
|
|
||||||
err := filepath.Walk(d.fullPath, func(dir string, info os.FileInfo, err error) error {
|
|
||||||
if dir == d.fullPath {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't copy template metadata
|
|
||||||
result.Add(dir)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// MkDir creates the given directory.
|
// MkDir creates the given directory.
|
||||||
// Returns error on failure
|
// Returns error on failure
|
||||||
func (fs *FSHelper) MkDir(dir string) error {
|
func (fs *FSHelper) MkDir(dir string) error {
|
||||||
return os.Mkdir(dir, 0700)
|
return os.Mkdir(dir, 0700)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveAsJSON saves the JSON representation of the given data to the given filename
|
|
||||||
func (fs *FSHelper) SaveAsJSON(data interface{}, filename string) error {
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
e := json.NewEncoder(&buf)
|
|
||||||
e.SetEscapeHTML(false)
|
|
||||||
e.SetIndent("", " ")
|
|
||||||
e.Encode(data)
|
|
||||||
|
|
||||||
err := ioutil.WriteFile(filename, buf.Bytes(), 0755)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadAsString will attempt to load the given file and return
|
// LoadAsString will attempt to load the given file and return
|
||||||
// its contents as a string
|
// its contents as a string
|
||||||
func (fs *FSHelper) LoadAsString(filename string) (string, error) {
|
func (fs *FSHelper) LoadAsString(filename string) (string, error) {
|
||||||
bytes, err := fs.LoadAsBytes(filename)
|
bytes, err := ioutil.ReadFile(filename)
|
||||||
return string(bytes), err
|
return string(bytes), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadAsBytes returns the contents of the file as a byte slice
|
|
||||||
func (fs *FSHelper) LoadAsBytes(filename string) ([]byte, error) {
|
|
||||||
return ioutil.ReadFile(filename)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FileMD5 returns the md5sum of the given file
|
// FileMD5 returns the md5sum of the given file
|
||||||
func (fs *FSHelper) FileMD5(filename string) (string, error) {
|
func (fs *FSHelper) FileMD5(filename string) (string, error) {
|
||||||
f, err := os.Open(filename)
|
f, err := os.Open(filename)
|
||||||
|
|||||||
108
cmd/github.go
108
cmd/github.go
@@ -1,108 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"sort"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GitHubHelper is a utility class for interacting with GitHub
|
|
||||||
type GitHubHelper struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGitHubHelper returns a new GitHub Helper
|
|
||||||
func NewGitHubHelper() *GitHubHelper {
|
|
||||||
return &GitHubHelper{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetVersionTags gets the list of tags on the Wails repo
|
|
||||||
// It retuns a list of sorted tags in descending order
|
|
||||||
func (g *GitHubHelper) GetVersionTags() ([]*SemanticVersion, error) {
|
|
||||||
|
|
||||||
result := []*SemanticVersion{}
|
|
||||||
var err error
|
|
||||||
|
|
||||||
resp, err := http.Get("https://api.github.com/repos/wailsapp/wails/tags")
|
|
||||||
if err != nil {
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
data := []map[string]interface{}{}
|
|
||||||
err = json.Unmarshal(body, &data)
|
|
||||||
if err != nil {
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert tag data to Version structs
|
|
||||||
for _, tag := range data {
|
|
||||||
version := tag["name"].(string)
|
|
||||||
semver, err := NewSemanticVersion(version)
|
|
||||||
if err != nil {
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
result = append(result, semver)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reverse Sort
|
|
||||||
sort.Sort(sort.Reverse(SemverCollection(result)))
|
|
||||||
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetLatestStableRelease gets the latest stable release on GitHub
|
|
||||||
func (g *GitHubHelper) GetLatestStableRelease() (result *SemanticVersion, err error) {
|
|
||||||
|
|
||||||
tags, err := g.GetVersionTags()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tag := range tags {
|
|
||||||
if tag.IsRelease() {
|
|
||||||
return tag, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("no release tag found")
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetLatestPreRelease gets the latest prerelease on GitHub
|
|
||||||
func (g *GitHubHelper) GetLatestPreRelease() (result *SemanticVersion, err error) {
|
|
||||||
|
|
||||||
tags, err := g.GetVersionTags()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tag := range tags {
|
|
||||||
if tag.IsPreRelease() {
|
|
||||||
return tag, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("no prerelease tag found")
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsValidTag returns true if the given string is a valid tag
|
|
||||||
func (g *GitHubHelper) IsValidTag(tagVersion string) (bool, error) {
|
|
||||||
if tagVersion[0] == 'v' {
|
|
||||||
tagVersion = tagVersion[1:]
|
|
||||||
}
|
|
||||||
tags, err := g.GetVersionTags()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tag := range tags {
|
|
||||||
if tag.String() == tagVersion {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
@@ -5,17 +5,15 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
mewn "github.com/leaanthony/mewn"
|
|
||||||
"github.com/leaanthony/slicer"
|
"github.com/leaanthony/slicer"
|
||||||
"github.com/leaanthony/spinner"
|
"github.com/leaanthony/spinner"
|
||||||
)
|
)
|
||||||
|
|
||||||
var fs = NewFSHelper()
|
|
||||||
|
|
||||||
// ValidateFrontendConfig checks if the frontend config is valid
|
// ValidateFrontendConfig checks if the frontend config is valid
|
||||||
func ValidateFrontendConfig(projectOptions *ProjectOptions) error {
|
func ValidateFrontendConfig(projectOptions *ProjectOptions) error {
|
||||||
if projectOptions.FrontEnd.Dir == "" {
|
if projectOptions.FrontEnd.Dir == "" {
|
||||||
@@ -36,7 +34,7 @@ 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() error {
|
func InstallGoDependencies() error {
|
||||||
depSpinner := spinner.New("Ensuring Dependencies are up to date...")
|
depSpinner := spinner.New("Installing Dependencies...")
|
||||||
depSpinner.SetSpinSpeed(50)
|
depSpinner.SetSpinSpeed(50)
|
||||||
depSpinner.Start()
|
depSpinner.Start()
|
||||||
err := NewProgramHelper().RunCommand("go get")
|
err := NewProgramHelper().RunCommand("go get")
|
||||||
@@ -77,14 +75,7 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
|
|||||||
packSpinner.Start()
|
packSpinner.Start()
|
||||||
|
|
||||||
buildCommand := slicer.String()
|
buildCommand := slicer.String()
|
||||||
buildCommand.Add("mewn")
|
buildCommand.AddSlice([]string{"mewn", "build"})
|
||||||
|
|
||||||
if buildMode == BuildModeBridge {
|
|
||||||
// Ignore errors
|
|
||||||
buildCommand.Add("-i")
|
|
||||||
}
|
|
||||||
|
|
||||||
buildCommand.Add("build")
|
|
||||||
|
|
||||||
if binaryName != "" {
|
if binaryName != "" {
|
||||||
buildCommand.Add("-o")
|
buildCommand.Add("-o")
|
||||||
@@ -117,18 +108,10 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
|
|||||||
}
|
}
|
||||||
packSpinner.Success()
|
packSpinner.Success()
|
||||||
|
|
||||||
// packageApp
|
|
||||||
if packageApp {
|
|
||||||
err = PackageApplication(projectOptions)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PackageApplication will attempt to package the application in a platform dependent way
|
// PackageApplication will attempt to package the application in a pltform dependent way
|
||||||
func PackageApplication(projectOptions *ProjectOptions) error {
|
func PackageApplication(projectOptions *ProjectOptions) error {
|
||||||
// Package app
|
// Package app
|
||||||
message := "Generating .app"
|
message := "Generating .app"
|
||||||
@@ -189,7 +172,7 @@ func CheckWindres() (err error) {
|
|||||||
}
|
}
|
||||||
programHelper := NewProgramHelper()
|
programHelper := NewProgramHelper()
|
||||||
if !programHelper.IsInstalled("windres") {
|
if !programHelper.IsInstalled("windres") {
|
||||||
return fmt.Errorf("windres not installed. It comes by default with mingw. Ensure you have installed mingw correctly")
|
return fmt.Errorf("windres not installed. It comes by default with mingw. Ensure you have installed mingw correctly.")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -204,7 +187,7 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if frontend deps have been updated
|
// Check if frontend deps have been updated
|
||||||
feSpinner := spinner.New("Ensuring frontend dependencies are up to date (This may take a while)")
|
feSpinner := spinner.New("Installing frontend dependencies (This may take a while)...")
|
||||||
feSpinner.SetSpinSpeed(50)
|
feSpinner.SetSpinSpeed(50)
|
||||||
feSpinner.Start()
|
feSpinner.Start()
|
||||||
|
|
||||||
@@ -249,32 +232,22 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
|
|||||||
ioutil.WriteFile(md5sumFile, []byte(packageJSONMD5), 0644)
|
ioutil.WriteFile(md5sumFile, []byte(packageJSONMD5), 0644)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Install the bridge library
|
|
||||||
err = InstallBridge(caller, projectDir, projectOptions)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build frontend
|
|
||||||
err = BuildFrontend(projectOptions.FrontEnd.Build)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// InstallBridge installs the relevant bridge javascript library
|
|
||||||
func InstallBridge(caller string, projectDir string, projectOptions *ProjectOptions) error {
|
|
||||||
bridgeFile := "wailsbridge.prod.js"
|
bridgeFile := "wailsbridge.prod.js"
|
||||||
if caller == "serve" {
|
if caller == "serve" {
|
||||||
bridgeFile = "wailsbridge.js"
|
bridgeFile = "wailsbridge.js"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy bridge to project
|
// Copy bridge to project
|
||||||
bridgeAssets := mewn.Group("../wailsruntimeassets/bridge/")
|
_, filename, _, _ := runtime.Caller(1)
|
||||||
bridgeFileData := bridgeAssets.Bytes(bridgeFile)
|
bridgeFileSource := filepath.Join(path.Dir(filename), "..", "..", "wailsruntimeassets", "bridge", bridgeFile)
|
||||||
bridgeFileTarget := filepath.Join(projectDir, projectOptions.FrontEnd.Dir, projectOptions.FrontEnd.Bridge, "wailsbridge.js")
|
bridgeFileTarget := filepath.Join(projectDir, projectOptions.FrontEnd.Dir, projectOptions.FrontEnd.Bridge, "wailsbridge.js")
|
||||||
err := fs.CreateFile(bridgeFileTarget, bridgeFileData)
|
err = fs.CopyFile(bridgeFileSource, bridgeFileTarget)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build frontend
|
||||||
|
err = BuildFrontend(projectOptions.FrontEnd.Build)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
59
cmd/linux.go
59
cmd/linux.go
@@ -2,9 +2,6 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -13,13 +10,9 @@ type LinuxDistribution int
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// Unknown is the catch-all distro
|
// Unknown is the catch-all distro
|
||||||
Unknown LinuxDistribution = iota
|
Unknown LinuxDistribution = 0
|
||||||
// Ubuntu distribution
|
// Ubuntu distribution
|
||||||
Ubuntu
|
Ubuntu LinuxDistribution = 1
|
||||||
// Arch linux distribution
|
|
||||||
Arch
|
|
||||||
// RedHat linux distribution
|
|
||||||
RedHat
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// DistroInfo contains all the information relating to a linux distribution
|
// DistroInfo contains all the information relating to a linux distribution
|
||||||
@@ -56,8 +49,6 @@ func GetLinuxDistroInfo() *DistroInfo {
|
|||||||
switch value {
|
switch value {
|
||||||
case "Ubuntu":
|
case "Ubuntu":
|
||||||
result.Distribution = Ubuntu
|
result.Distribution = Ubuntu
|
||||||
case "Arch", "ManjaroLinux":
|
|
||||||
result.Distribution = Arch
|
|
||||||
}
|
}
|
||||||
case "Description":
|
case "Description":
|
||||||
result.Description = value
|
result.Description = value
|
||||||
@@ -69,58 +60,20 @@ func GetLinuxDistroInfo() *DistroInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// check if /etc/os-release exists
|
|
||||||
} else if _, err := os.Stat("/etc/os-release"); !os.IsNotExist(err) {
|
|
||||||
// read /etc/os-release
|
|
||||||
osRelease, _ := ioutil.ReadFile("/etc/os-release")
|
|
||||||
// compile a regex to find NAME=distro
|
|
||||||
re := regexp.MustCompile(`^NAME=(.*)\n`)
|
|
||||||
// extract the distro name
|
|
||||||
osName := string(re.FindSubmatch(osRelease)[1])
|
|
||||||
// strip quotations
|
|
||||||
osName = strings.Trim(osName, "\"")
|
|
||||||
// Check distro name against list of distros
|
|
||||||
switch osName {
|
|
||||||
case "Fedora":
|
|
||||||
result.Distribution = RedHat
|
|
||||||
case "CentOS":
|
|
||||||
result.Distribution = RedHat
|
|
||||||
case "Arch Linux":
|
|
||||||
result.Distribution = Arch
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// DpkgInstalled uses dpkg to see if a package is installed
|
// DpkgInstalled uses dpkg to see if a package is installed
|
||||||
func DpkgInstalled(packageName string) (bool, error) {
|
func DpkgInstalled(packageName string) (bool, error) {
|
||||||
|
result := false
|
||||||
program := NewProgramHelper()
|
program := NewProgramHelper()
|
||||||
dpkg := program.FindProgram("dpkg")
|
dpkg := program.FindProgram("dpkg")
|
||||||
if dpkg == nil {
|
if dpkg == nil {
|
||||||
return false, fmt.Errorf("cannot check dependencies: dpkg not found")
|
return false, fmt.Errorf("cannot check dependencies: dpkg not found")
|
||||||
}
|
}
|
||||||
_, _, exitCode, _ := dpkg.Run("-L", packageName)
|
_, _, exitCode, _ := dpkg.Run("-L", packageName)
|
||||||
return exitCode == 0, nil
|
result = exitCode == 0
|
||||||
}
|
return result, nil
|
||||||
|
|
||||||
// PacmanInstalled uses pacman to see if a package is installed.
|
|
||||||
func PacmanInstalled(packageName string) (bool, error) {
|
|
||||||
program := NewProgramHelper()
|
|
||||||
pacman := program.FindProgram("pacman")
|
|
||||||
if pacman == nil {
|
|
||||||
return false, fmt.Errorf("cannot check dependencies: pacman not found")
|
|
||||||
}
|
|
||||||
_, _, exitCode, _ := pacman.Run("-Qs", packageName)
|
|
||||||
return exitCode == 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RpmInstalled uses rpm to see if a package is installed
|
|
||||||
func RpmInstalled(packageName string) (bool, error) {
|
|
||||||
program := NewProgramHelper()
|
|
||||||
rpm := program.FindProgram("rpm")
|
|
||||||
if rpm == nil {
|
|
||||||
return false, fmt.Errorf("cannot check dependencies: rpm not found")
|
|
||||||
}
|
|
||||||
_, _, exitCode, _ := rpm.Run("--query", packageName)
|
|
||||||
return exitCode == 0, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ func NewLogger() *Logger {
|
|||||||
return &Logger{errorOnly: false}
|
return &Logger{errorOnly: false}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetErrorOnly ensures that only errors are logged out
|
|
||||||
func (l *Logger) SetErrorOnly(errorOnly bool) {
|
func (l *Logger) SetErrorOnly(errorOnly bool) {
|
||||||
l.errorOnly = errorOnly
|
l.errorOnly = errorOnly
|
||||||
}
|
}
|
||||||
@@ -100,7 +99,6 @@ func (l *Logger) Error(format string, a ...interface{}) {
|
|||||||
color.New(color.FgHiRed).PrintfFunc()("Error: "+format+"\n", a...)
|
color.New(color.FgHiRed).PrintfFunc()("Error: "+format+"\n", a...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrintSmallBanner prints a condensed banner
|
|
||||||
func (l *Logger) PrintSmallBanner(message ...string) {
|
func (l *Logger) PrintSmallBanner(message ...string) {
|
||||||
yellow := color.New(color.FgYellow).SprintFunc()
|
yellow := color.New(color.FgYellow).SprintFunc()
|
||||||
red := color.New(color.FgRed).SprintFunc()
|
red := color.New(color.FgRed).SprintFunc()
|
||||||
|
|||||||
@@ -72,11 +72,11 @@ func (b *PackageHelper) Package(po *ProjectOptions) error {
|
|||||||
case "darwin":
|
case "darwin":
|
||||||
// Check we have the exe
|
// Check we have the exe
|
||||||
if !b.fs.FileExists(po.BinaryName) {
|
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 fmt.Errorf("cannot bundle non-existant 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, false)
|
return b.PackageWindows(po, true)
|
||||||
case "linux":
|
case "linux":
|
||||||
return fmt.Errorf("linux is not supported at this time. Please see https://github.com/wailsapp/wails/issues/2")
|
return fmt.Errorf("linux is not supported at this time. Please see https://github.com/wailsapp/wails/issues/2")
|
||||||
default:
|
default:
|
||||||
@@ -150,7 +150,6 @@ func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 {
|
||||||
basename := strings.TrimSuffix(po.BinaryName, ".exe")
|
basename := strings.TrimSuffix(po.BinaryName, ".exe")
|
||||||
|
|
||||||
@@ -199,7 +198,7 @@ func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
|
|||||||
|
|
||||||
// clean up
|
// clean up
|
||||||
if cleanUp {
|
if cleanUp {
|
||||||
filesToDelete := []string{tgtIconFile, tgtManifestFile, tgtRCFile, sysofile}
|
filesToDelete := []string{tgtIconFile, tgtManifestFile, tgtRCFile}
|
||||||
err := b.fs.RemoveFiles(filesToDelete)
|
err := b.fs.RemoveFiles(filesToDelete)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -255,5 +254,9 @@ func (b *PackageHelper) packageIconOSX(resourceDir string) error {
|
|||||||
|
|
||||||
}
|
}
|
||||||
defer dest.Close()
|
defer dest.Close()
|
||||||
return icns.Encode(dest, srcImg)
|
if err := icns.Encode(dest, srcImg); err != nil {
|
||||||
|
return err
|
||||||
|
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ func getRequiredProgramsLinux() *Prerequisites {
|
|||||||
case Ubuntu:
|
case Ubuntu:
|
||||||
result.Add(newPrerequisite("gcc", "Please install with `sudo apt install build-essentials` and try again"))
|
result.Add(newPrerequisite("gcc", "Please install with `sudo apt install build-essentials` and try again"))
|
||||||
result.Add(newPrerequisite("pkg-config", "Please install with `sudo apt install pkg-config` and try again"))
|
result.Add(newPrerequisite("pkg-config", "Please install with `sudo apt install pkg-config` and try again"))
|
||||||
result.Add(newPrerequisite("npm", "Please install with `sudo snap install node --channel=12/stable --classic` and try again"))
|
result.Add(newPrerequisite("npm", "Please install with `sudo apt install npm` and try again"))
|
||||||
|
|
||||||
default:
|
default:
|
||||||
result.Add(newPrerequisite("gcc", "Please install with your system package manager and try again"))
|
result.Add(newPrerequisite("gcc", "Please install with your system package manager and try again"))
|
||||||
@@ -97,12 +97,6 @@ func getRequiredLibrariesLinux() (*Prerequisites, error) {
|
|||||||
case Ubuntu:
|
case Ubuntu:
|
||||||
result.Add(newPrerequisite("libgtk-3-dev", "Please install with `sudo apt install libgtk-3-dev` and try again"))
|
result.Add(newPrerequisite("libgtk-3-dev", "Please install with `sudo apt install libgtk-3-dev` and try again"))
|
||||||
result.Add(newPrerequisite("libwebkit2gtk-4.0-dev", "Please install with `sudo apt install libwebkit2gtk-4.0-dev` and try again"))
|
result.Add(newPrerequisite("libwebkit2gtk-4.0-dev", "Please install with `sudo apt install libwebkit2gtk-4.0-dev` and try again"))
|
||||||
case Arch:
|
|
||||||
result.Add(newPrerequisite("gtk3", "Please install with `sudo pacman -S gtk3` and try again"))
|
|
||||||
result.Add(newPrerequisite("webkit2gtk", "Please install with `sudo pacman -S webkit2gtk` and try again"))
|
|
||||||
case RedHat:
|
|
||||||
result.Add(newPrerequisite("gtk3-devel", "Please install with `sudo yum install gtk3-devel` and try again"))
|
|
||||||
result.Add(newPrerequisite("webkit2gtk3-devel", "Please install with `sudo yum install webkit2gtk3-devel` and try again"))
|
|
||||||
default:
|
default:
|
||||||
result.Add(newPrerequisite("libgtk-3-dev", "Please install with your system package manager and try again"))
|
result.Add(newPrerequisite("libgtk-3-dev", "Please install with your system package manager and try again"))
|
||||||
result.Add(newPrerequisite("libwebkit2gtk-4.0-dev", "Please install with your system package manager and try again"))
|
result.Add(newPrerequisite("libwebkit2gtk-4.0-dev", "Please install with your system package manager and try again"))
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ func (p *Program) GetFullPathToBinary() (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run will execute the program with the given parameters
|
// Run will execute the program with the given parameters
|
||||||
// Returns stdout + stderr as strings and an error if one occurred
|
// Returns stdout + stderr as strings and an error if one occured
|
||||||
func (p *Program) Run(vars ...string) (stdout, stderr string, exitCode int, err error) {
|
func (p *Program) Run(vars ...string) (stdout, stderr string, exitCode int, err error) {
|
||||||
command, err := p.GetFullPathToBinary()
|
command, err := p.GetFullPathToBinary()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -92,7 +92,7 @@ func (p *Program) Run(vars ...string) (stdout, stderr string, exitCode int, err
|
|||||||
|
|
||||||
// InstallGoPackage installs the given Go package
|
// InstallGoPackage installs the given Go package
|
||||||
func (p *ProgramHelper) InstallGoPackage(packageName string) error {
|
func (p *ProgramHelper) InstallGoPackage(packageName string) error {
|
||||||
args := strings.Split("get "+packageName, " ")
|
args := strings.Split("get -u "+packageName, " ")
|
||||||
_, stderr, err := p.shell.Run("go", args...)
|
_, stderr, err := p.shell.Run("go", args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(stderr)
|
fmt.Println(stderr)
|
||||||
@@ -106,8 +106,17 @@ func (p *ProgramHelper) RunCommand(command string) error {
|
|||||||
return p.RunCommandArray(args)
|
return p.RunCommandArray(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *ProgramHelper) GetOutputFromCommand(command string) (string, string, error) {
|
||||||
|
args := strings.Split(command, " ")
|
||||||
|
if len(args) > 1 {
|
||||||
|
return p.shell.Run(args[0], args[1:]...)
|
||||||
|
} else {
|
||||||
|
return p.shell.Run(args[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 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) error {
|
||||||
program := 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(program)
|
program, err := exec.LookPath(program)
|
||||||
@@ -116,13 +125,8 @@ func (p *ProgramHelper) RunCommandArray(args []string, dir ...string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
args = args[1:]
|
args = args[1:]
|
||||||
var stderr string
|
|
||||||
// fmt.Printf("RunCommandArray = %s %+v\n", program, args)
|
// fmt.Printf("RunCommandArray = %s %+v\n", program, args)
|
||||||
if len(dir) > 0 {
|
_, stderr, err := p.shell.Run(program, args...)
|
||||||
_, stderr, err = p.shell.RunInDirectory(dir[0], program, args...)
|
|
||||||
} else {
|
|
||||||
_, stderr, err = p.shell.Run(program, args...)
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(stderr)
|
fmt.Println(stderr)
|
||||||
}
|
}
|
||||||
|
|||||||
148
cmd/project.go
148
cmd/project.go
@@ -4,12 +4,9 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/leaanthony/slicer"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type author struct {
|
type author struct {
|
||||||
@@ -50,14 +47,22 @@ func NewProjectHelper() *ProjectHelper {
|
|||||||
// GenerateProject generates a new project using the options given
|
// GenerateProject generates a new project using the options given
|
||||||
func (ph *ProjectHelper) GenerateProject(projectOptions *ProjectOptions) error {
|
func (ph *ProjectHelper) GenerateProject(projectOptions *ProjectOptions) error {
|
||||||
|
|
||||||
|
fs := NewFSHelper()
|
||||||
|
exists, err := ph.templates.TemplateExists(projectOptions.Template)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !exists {
|
||||||
|
return fmt.Errorf("template '%s' is invalid", projectOptions.Template)
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate project path
|
// Calculate project path
|
||||||
projectPath, err := filepath.Abs(projectOptions.OutputDirectory)
|
projectPath, err := filepath.Abs(projectOptions.OutputDirectory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = projectPath
|
|
||||||
|
|
||||||
if fs.DirExists(projectPath) {
|
if fs.DirExists(projectPath) {
|
||||||
return fmt.Errorf("directory '%s' already exists", projectPath)
|
return fmt.Errorf("directory '%s' already exists", projectPath)
|
||||||
}
|
}
|
||||||
@@ -84,6 +89,8 @@ func (ph *ProjectHelper) GenerateProject(projectOptions *ProjectOptions) error {
|
|||||||
// ph.GenerateWindowsResourceConfig(projectOptions)
|
// ph.GenerateWindowsResourceConfig(projectOptions)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
ph.log.Yellow("Project '%s' generated in directory '%s'!", projectOptions.Name, projectOptions.OutputDirectory)
|
||||||
|
ph.log.Yellow("To compile the project, run 'wails build' in the project directory.")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,14 +114,15 @@ func (ph *ProjectHelper) LoadProjectConfig(dir string) (*ProjectOptions, error)
|
|||||||
// NewProjectOptions creates a new default set of project options
|
// NewProjectOptions creates a new default set of project options
|
||||||
func (ph *ProjectHelper) NewProjectOptions() *ProjectOptions {
|
func (ph *ProjectHelper) NewProjectOptions() *ProjectOptions {
|
||||||
result := ProjectOptions{
|
result := ProjectOptions{
|
||||||
Name: "",
|
Name: "",
|
||||||
Description: "Enter your project description",
|
Description: "Enter your project description",
|
||||||
Version: "0.1.0",
|
Version: "0.1.0",
|
||||||
BinaryName: "",
|
BinaryName: "",
|
||||||
system: NewSystemHelper(),
|
system: NewSystemHelper(),
|
||||||
log: NewLogger(),
|
log: NewLogger(),
|
||||||
templates: NewTemplateHelper(),
|
templates: NewTemplateHelper(),
|
||||||
Author: &author{},
|
templateNameMap: make(map[string]string),
|
||||||
|
Author: &author{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populate system config
|
// Populate system config
|
||||||
@@ -129,25 +137,25 @@ 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
|
templateNameMap map[string]string // Converts template prompt text to template name
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defaults sets the default project template
|
// Defaults sets the default project template
|
||||||
func (po *ProjectOptions) Defaults() {
|
func (po *ProjectOptions) Defaults() {
|
||||||
po.Template = "vuebasic"
|
po.Template = "basic"
|
||||||
}
|
}
|
||||||
|
|
||||||
// PromptForInputs asks the user to input project details
|
// PromptForInputs asks the user to input project details
|
||||||
@@ -162,55 +170,48 @@ func (po *ProjectOptions) PromptForInputs() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process Templates
|
|
||||||
templateList := slicer.Interface()
|
|
||||||
options := slicer.String()
|
|
||||||
templateDetails, err := po.templates.GetTemplateDetails()
|
templateDetails, err := po.templates.GetTemplateDetails()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if po.Template != "" {
|
templates := []string{}
|
||||||
// Check template is valid if given
|
// Add a Custom Template
|
||||||
if templateDetails[po.Template] == nil {
|
// templates = append(templates, "Custom - Choose your own CSS framework")
|
||||||
keys := make([]string, 0, len(templateDetails))
|
for templateName, templateDetails := range templateDetails {
|
||||||
for k := range templateDetails {
|
templateText := templateName
|
||||||
keys = append(keys, k)
|
// Check if metadata json exists
|
||||||
|
if templateDetails.Metadata != nil {
|
||||||
|
shortdescription := templateDetails.Metadata["shortdescription"]
|
||||||
|
if shortdescription != "" {
|
||||||
|
templateText += " - " + shortdescription.(string)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("invalid template name '%s'. Valid options: %s", po.Template, strings.Join(keys, ", "))
|
|
||||||
}
|
}
|
||||||
po.selectedTemplate = templateDetails[po.Template]
|
templates = append(templates, templateText)
|
||||||
} else {
|
po.templateNameMap[templateText] = templateName
|
||||||
|
|
||||||
for _, templateDetail := range templateDetails {
|
|
||||||
templateList.Add(templateDetail)
|
|
||||||
options.Add(fmt.Sprintf("%s - %s", templateDetail.Metadata.Name, templateDetail.Metadata.ShortDescription))
|
|
||||||
}
|
|
||||||
|
|
||||||
templateIndex := 0
|
|
||||||
|
|
||||||
if len(options.AsSlice()) > 1 {
|
|
||||||
templateIndex = PromptSelection("Please select a template", options.AsSlice(), 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(templateList.AsSlice()) == 0 {
|
|
||||||
return fmt.Errorf("aborting: no templates found")
|
|
||||||
}
|
|
||||||
|
|
||||||
// After selection do this....
|
|
||||||
po.selectedTemplate = templateList.AsSlice()[templateIndex].(*TemplateDetails)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Template: " + po.selectedTemplate.Metadata.Name)
|
if po.Template != "" {
|
||||||
|
if _, ok := templateDetails[po.Template]; !ok {
|
||||||
|
po.log.Error("Template '%s' invalid.", po.Template)
|
||||||
|
templateSelected := PromptSelection("Select template", templates)
|
||||||
|
po.Template = templates[templateSelected]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
templateSelected := PromptSelection("Select template", templates)
|
||||||
|
po.Template = templates[templateSelected]
|
||||||
|
}
|
||||||
|
|
||||||
// Setup NPM Project name
|
// Setup NPM Project name
|
||||||
po.NPMProjectName = strings.ToLower(strings.Replace(po.Name, " ", "_", -1))
|
po.NPMProjectName = strings.ToLower(strings.Replace(po.Name, " ", "_", -1))
|
||||||
|
|
||||||
// Fix template name
|
// Fix template name
|
||||||
po.Template = strings.Split(po.selectedTemplate.Path, string(os.PathSeparator))[0]
|
if po.templateNameMap[po.Template] != "" {
|
||||||
|
po.Template = po.templateNameMap[po.Template]
|
||||||
|
}
|
||||||
|
|
||||||
// // Populate template details
|
// Populate template details
|
||||||
templateMetadata := po.selectedTemplate.Metadata
|
templateMetadata := templateDetails[po.Template].Metadata
|
||||||
|
|
||||||
err = processTemplateMetadata(templateMetadata, po)
|
err = processTemplateMetadata(templateMetadata, po)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -282,6 +283,7 @@ func processProjectName(po *ProjectOptions) {
|
|||||||
po.Name = Prompt("The name of the project", "My Project")
|
po.Name = Prompt("The name of the project", "My Project")
|
||||||
}
|
}
|
||||||
fmt.Println("Project Name: " + po.Name)
|
fmt.Println("Project Name: " + po.Name)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func processBinaryName(po *ProjectOptions) {
|
func processBinaryName(po *ProjectOptions) {
|
||||||
@@ -297,36 +299,36 @@ func processBinaryName(po *ProjectOptions) {
|
|||||||
fmt.Println("Output binary Name: " + po.BinaryName)
|
fmt.Println("Output binary Name: " + po.BinaryName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func processTemplateMetadata(templateMetadata *TemplateMetadata, po *ProjectOptions) error {
|
func processTemplateMetadata(templateMetadata map[string]interface{}, po *ProjectOptions) error {
|
||||||
if templateMetadata.FrontendDir != "" {
|
if templateMetadata["frontenddir"] != nil {
|
||||||
po.FrontEnd = &frontend{}
|
po.FrontEnd = &frontend{}
|
||||||
po.FrontEnd.Dir = templateMetadata.FrontendDir
|
po.FrontEnd.Dir = templateMetadata["frontenddir"].(string)
|
||||||
}
|
}
|
||||||
if templateMetadata.Install != "" {
|
if templateMetadata["install"] != nil {
|
||||||
if po.FrontEnd == nil {
|
if po.FrontEnd == nil {
|
||||||
return fmt.Errorf("install set in template metadata but not frontenddir")
|
return fmt.Errorf("install set in template metadata but not frontenddir")
|
||||||
}
|
}
|
||||||
po.FrontEnd.Install = templateMetadata.Install
|
po.FrontEnd.Install = templateMetadata["install"].(string)
|
||||||
}
|
}
|
||||||
if templateMetadata.Build != "" {
|
if templateMetadata["build"] != nil {
|
||||||
if po.FrontEnd == nil {
|
if po.FrontEnd == nil {
|
||||||
return fmt.Errorf("build set in template metadata but not frontenddir")
|
return fmt.Errorf("build set in template metadata but not frontenddir")
|
||||||
}
|
}
|
||||||
po.FrontEnd.Build = templateMetadata.Build
|
po.FrontEnd.Build = templateMetadata["build"].(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
if templateMetadata.Bridge != "" {
|
if templateMetadata["bridge"] != nil {
|
||||||
if po.FrontEnd == nil {
|
if po.FrontEnd == nil {
|
||||||
return fmt.Errorf("bridge set in template metadata but not frontenddir")
|
return fmt.Errorf("bridge set in template metadata but not frontenddir")
|
||||||
}
|
}
|
||||||
po.FrontEnd.Bridge = templateMetadata.Bridge
|
po.FrontEnd.Bridge = templateMetadata["bridge"].(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
if templateMetadata.Serve != "" {
|
if templateMetadata["serve"] != nil {
|
||||||
if po.FrontEnd == nil {
|
if po.FrontEnd == nil {
|
||||||
return fmt.Errorf("serve set in template metadata but not frontenddir")
|
return fmt.Errorf("serve set in template metadata but not frontenddir")
|
||||||
}
|
}
|
||||||
po.FrontEnd.Serve = templateMetadata.Serve
|
po.FrontEnd.Serve = templateMetadata["serve"].(string)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +1,25 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"runtime"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Prompt asks the user for a value
|
// Prompt asks the user for a value
|
||||||
func Prompt(question string, defaultValue ...string) string {
|
func Prompt(question string, defaultValue ...string) string {
|
||||||
var answer string
|
var answer string
|
||||||
|
haveDefault := len(defaultValue) > 0 && defaultValue[0] != ""
|
||||||
|
|
||||||
if len(defaultValue) > 0 {
|
if haveDefault {
|
||||||
answer = defaultValue[0]
|
question = fmt.Sprintf("%s (%s)", question, defaultValue[0])
|
||||||
question = fmt.Sprintf("%s (%s)", question, answer)
|
|
||||||
}
|
}
|
||||||
fmt.Printf(question + ": ")
|
fmt.Printf(question + ": ")
|
||||||
reader := bufio.NewReader(os.Stdin)
|
fmt.Scanln(&answer)
|
||||||
input, _ := reader.ReadString('\n')
|
if haveDefault {
|
||||||
EOL := "\n"
|
if len(answer) == 0 {
|
||||||
if runtime.GOOS == "windows" {
|
answer = defaultValue[0]
|
||||||
EOL = "\r\n"
|
}
|
||||||
}
|
}
|
||||||
input = strings.Replace(input, EOL, "", -1)
|
|
||||||
|
|
||||||
if input != "" {
|
|
||||||
answer = input
|
|
||||||
}
|
|
||||||
|
|
||||||
return answer
|
return answer
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,29 +34,18 @@ func PromptRequired(question string, defaultValue ...string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PromptSelection asks the user to choose an option
|
// PromptSelection asks the user to choose an option
|
||||||
func PromptSelection(question string, options []string, optionalDefaultValue ...int) int {
|
func PromptSelection(question string, options []string) int {
|
||||||
|
|
||||||
defaultValue := -1
|
|
||||||
message := "Please choose an option"
|
|
||||||
fmt.Println(question + ":")
|
fmt.Println(question + ":")
|
||||||
|
|
||||||
if len(optionalDefaultValue) > 0 {
|
|
||||||
defaultValue = optionalDefaultValue[0] + 1
|
|
||||||
message = fmt.Sprintf("%s [%d]", message, defaultValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
for index, option := range options {
|
for index, option := range options {
|
||||||
fmt.Printf(" %d: %s\n", index+1, option)
|
fmt.Printf(" %d: %s\n", index+1, option)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
selectedValue := -1
|
selectedValue := -1
|
||||||
|
|
||||||
for {
|
for {
|
||||||
choice := Prompt(message)
|
choice := Prompt("Please choose an option")
|
||||||
if choice == "" && defaultValue > -1 {
|
|
||||||
selectedValue = defaultValue - 1
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// index
|
// index
|
||||||
number, err := strconv.Atoi(choice)
|
number, err := strconv.Atoi(choice)
|
||||||
|
|||||||
@@ -1,98 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/masterminds/semver"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SemanticVersion is a struct containing a semantic version
|
|
||||||
type SemanticVersion struct {
|
|
||||||
Version *semver.Version
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSemanticVersion creates a new SemanticVersion object with the given version string
|
|
||||||
func NewSemanticVersion(version string) (*SemanticVersion, error) {
|
|
||||||
semverVersion, err := semver.NewVersion(version)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &SemanticVersion{
|
|
||||||
Version: semverVersion,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsRelease returns true if it's a release version
|
|
||||||
func (s *SemanticVersion) IsRelease() bool {
|
|
||||||
return len(s.Version.Prerelease()) == 0 && len(s.Version.Metadata()) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsPreRelease returns true if it's a prerelease version
|
|
||||||
func (s *SemanticVersion) IsPreRelease() bool {
|
|
||||||
return len(s.Version.Prerelease()) > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SemanticVersion) String() string {
|
|
||||||
return s.Version.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsGreaterThan returns true if this version is greater than the given version
|
|
||||||
func (s *SemanticVersion) IsGreaterThan(version *SemanticVersion) (bool, error) {
|
|
||||||
// Set up new constraint
|
|
||||||
constraint, err := semver.NewConstraint("> " + version.Version.String())
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the desired one is greater than the requested on
|
|
||||||
success, msgs := constraint.Validate(s.Version)
|
|
||||||
if !success {
|
|
||||||
return false, msgs[0]
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsGreaterThanOrEqual returns true if this version is greater than or equal the given version
|
|
||||||
func (s *SemanticVersion) IsGreaterThanOrEqual(version *SemanticVersion) (bool, error) {
|
|
||||||
// Set up new constraint
|
|
||||||
constraint, err := semver.NewConstraint(">= " + version.Version.String())
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the desired one is greater than the requested on
|
|
||||||
success, msgs := constraint.Validate(s.Version)
|
|
||||||
if !success {
|
|
||||||
return false, msgs[0]
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MainVersion returns the main version of any version+prerelease+metadata
|
|
||||||
// EG: MainVersion("1.2.3-pre") => "1.2.3"
|
|
||||||
func (s *SemanticVersion) MainVersion() *SemanticVersion {
|
|
||||||
mainVersion := fmt.Sprintf("%d.%d.%d", s.Version.Major(), s.Version.Minor(), s.Version.Patch())
|
|
||||||
result, _ := NewSemanticVersion(mainVersion)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// SemverCollection is a collection of SemanticVersion objects
|
|
||||||
type SemverCollection []*SemanticVersion
|
|
||||||
|
|
||||||
// Len returns the length of a collection. The number of Version instances
|
|
||||||
// on the slice.
|
|
||||||
func (c SemverCollection) Len() int {
|
|
||||||
return len(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Less is needed for the sort interface to compare two Version objects on the
|
|
||||||
// slice. If checks if one is less than the other.
|
|
||||||
func (c SemverCollection) Less(i, j int) bool {
|
|
||||||
return c[i].Version.LessThan(c[j].Version)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Swap is needed for the sort interface to replace the Version objects
|
|
||||||
// at two different positions in the slice.
|
|
||||||
func (c SemverCollection) Swap(i, j int) {
|
|
||||||
c[i], c[j] = c[j], c[i]
|
|
||||||
}
|
|
||||||
1
cmd/setup.go
Normal file
1
cmd/setup.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package cmd
|
||||||
16
cmd/shell.go
16
cmd/shell.go
@@ -2,7 +2,6 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"os"
|
|
||||||
"os/exec"
|
"os/exec"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,21 +17,6 @@ func NewShellHelper() *ShellHelper {
|
|||||||
// 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")
|
|
||||||
var stdo, stde bytes.Buffer
|
|
||||||
cmd.Stdout = &stdo
|
|
||||||
cmd.Stderr = &stde
|
|
||||||
err = cmd.Run()
|
|
||||||
stdout = string(stdo.Bytes())
|
|
||||||
stderr = string(stde.Bytes())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// RunInDirectory runs the given command in the given directory
|
|
||||||
func (sh *ShellHelper) RunInDirectory(dir string, command string, vars ...string) (stdout, stderr string, err error) {
|
|
||||||
cmd := exec.Command(command, vars...)
|
|
||||||
cmd.Dir = dir
|
|
||||||
cmd.Env = append(os.Environ(), "GO111MODULE=on")
|
|
||||||
var stdo, stde bytes.Buffer
|
var stdo, stde bytes.Buffer
|
||||||
cmd.Stdout = &stdo
|
cmd.Stdout = &stdo
|
||||||
cmd.Stderr = &stde
|
cmd.Stderr = &stde
|
||||||
|
|||||||
@@ -68,17 +68,6 @@ func (s *SystemHelper) ConfigFileIsValid() bool {
|
|||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAuthor returns a formatted string of the user's name and email
|
|
||||||
func (s *SystemHelper) GetAuthor() (string, error) {
|
|
||||||
var config *SystemConfig
|
|
||||||
config, err := s.LoadConfig()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprintf("%s <%s>", config.Name, config.Email), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BackupConfig attempts to backup the system config file
|
// BackupConfig attempts to backup the system config file
|
||||||
func (s *SystemHelper) BackupConfig() (string, error) {
|
func (s *SystemHelper) BackupConfig() (string, error) {
|
||||||
now := strconv.FormatInt(time.Now().UTC().UnixNano(), 10)
|
now := strconv.FormatInt(time.Now().UTC().UnixNano(), 10)
|
||||||
@@ -92,24 +81,21 @@ func (s *SystemHelper) BackupConfig() (string, error) {
|
|||||||
|
|
||||||
func (s *SystemHelper) setup() error {
|
func (s *SystemHelper) setup() error {
|
||||||
|
|
||||||
systemConfig := make(map[string]string)
|
|
||||||
|
|
||||||
// Try to load current values - ignore errors
|
// Try to load current values - ignore errors
|
||||||
config, _ := s.LoadConfig()
|
config, err := s.LoadConfig()
|
||||||
|
defaultName := ""
|
||||||
|
defaultEmail := ""
|
||||||
|
if config != nil {
|
||||||
|
defaultName = config.Name
|
||||||
|
defaultEmail = config.Email
|
||||||
|
}
|
||||||
|
|
||||||
if config.Name != "" {
|
systemConfig := make(map[string]string)
|
||||||
systemConfig["name"] = PromptRequired("What is your name", config.Name)
|
systemConfig["name"] = PromptRequired("What is your name", defaultName)
|
||||||
} else {
|
systemConfig["email"] = PromptRequired("What is your email address", defaultEmail)
|
||||||
systemConfig["name"] = PromptRequired("What is your name")
|
|
||||||
}
|
|
||||||
if config.Email != "" {
|
|
||||||
systemConfig["email"] = PromptRequired("What is your email address", config.Email)
|
|
||||||
} else {
|
|
||||||
systemConfig["email"] = PromptRequired("What is your email address")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the directory
|
// Create the directory
|
||||||
err := s.fs.MkDirs(s.wailsSystemDir)
|
err = s.fs.MkDirs(s.wailsSystemDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -256,7 +242,7 @@ func CheckDependencies(logger *Logger) (bool, error) {
|
|||||||
bin := programHelper.FindProgram(program.Name)
|
bin := programHelper.FindProgram(program.Name)
|
||||||
if bin == nil {
|
if bin == nil {
|
||||||
errors = true
|
errors = true
|
||||||
logger.Error("Program '%s' not found. %s", program.Name, program.Help)
|
logger.Red("Program '%s' not found. %s", program.Name, program.Help)
|
||||||
} else {
|
} else {
|
||||||
logger.Green("Program '%s' found: %s", program.Name, bin.Path)
|
logger.Green("Program '%s' found: %s", program.Name, bin.Path)
|
||||||
}
|
}
|
||||||
@@ -279,30 +265,7 @@ func CheckDependencies(logger *Logger) (bool, error) {
|
|||||||
}
|
}
|
||||||
if !installed {
|
if !installed {
|
||||||
errors = true
|
errors = true
|
||||||
logger.Error("Library '%s' not found. %s", library.Name, library.Help)
|
logger.Red("Library '%s' not found. %s", library.Name, library.Help)
|
||||||
} else {
|
|
||||||
logger.Green("Library '%s' installed.", library.Name)
|
|
||||||
}
|
|
||||||
case Arch:
|
|
||||||
installed, err := PacmanInstalled(library.Name)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if !installed {
|
|
||||||
errors = true
|
|
||||||
logger.Error("Library '%s' not found. %s", library.Name, library.Help)
|
|
||||||
} else {
|
|
||||||
logger.Green("Library '%s' installed.", library.Name)
|
|
||||||
}
|
|
||||||
case RedHat:
|
|
||||||
|
|
||||||
installed, err := RpmInstalled(library.Name)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if !installed {
|
|
||||||
errors = true
|
|
||||||
logger.Error("Library '%s' not found. %s", library.Name, library.Help)
|
|
||||||
} else {
|
} else {
|
||||||
logger.Green("Library '%s' installed.", library.Name)
|
logger.Green("Library '%s' installed.", library.Name)
|
||||||
}
|
}
|
||||||
|
|||||||
370
cmd/templates.go
370
cmd/templates.go
@@ -5,94 +5,91 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"os"
|
||||||
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/kennygrant/sanitize"
|
|
||||||
"github.com/leaanthony/slicer"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TemplateMetadata holds all the metadata for a Wails template
|
const templateSuffix = ".template"
|
||||||
type TemplateMetadata struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Version string `json:"version"`
|
|
||||||
ShortDescription string `json:"shortdescription"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
Install string `json:"install"`
|
|
||||||
Build string `json:"build"`
|
|
||||||
Author string `json:"author"`
|
|
||||||
Created string `json:"created"`
|
|
||||||
FrontendDir string `json:"frontenddir"`
|
|
||||||
Serve string `json:"serve"`
|
|
||||||
Bridge string `json:"bridge"`
|
|
||||||
WailsDir string `json:"wailsdir"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// TemplateDetails holds information about a specific template
|
// TemplateHelper helps with creating projects
|
||||||
type TemplateDetails struct {
|
|
||||||
Name string
|
|
||||||
Path string
|
|
||||||
Metadata *TemplateMetadata
|
|
||||||
fs *FSHelper
|
|
||||||
}
|
|
||||||
|
|
||||||
// TemplateHelper is a utility object to help with processing templates
|
|
||||||
type TemplateHelper struct {
|
type TemplateHelper struct {
|
||||||
templateDir *Dir
|
system *SystemHelper
|
||||||
fs *FSHelper
|
fs *FSHelper
|
||||||
|
templateDir string
|
||||||
|
// templates map[string]string
|
||||||
|
templateSuffix string
|
||||||
metadataFilename string
|
metadataFilename string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Template defines a single template
|
||||||
|
type Template struct {
|
||||||
|
Name string
|
||||||
|
Dir string
|
||||||
|
Metadata map[string]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
// NewTemplateHelper creates a new template helper
|
// NewTemplateHelper creates a new template helper
|
||||||
func NewTemplateHelper() *TemplateHelper {
|
func NewTemplateHelper() *TemplateHelper {
|
||||||
|
result := TemplateHelper{
|
||||||
templateDir, err := fs.LocalDir("./templates")
|
system: NewSystemHelper(),
|
||||||
if err != nil {
|
fs: NewFSHelper(),
|
||||||
log.Fatal("Unable to find the template directory. Please reinstall Wails.")
|
templateSuffix: ".template",
|
||||||
}
|
|
||||||
|
|
||||||
return &TemplateHelper{
|
|
||||||
templateDir: templateDir,
|
|
||||||
metadataFilename: "template.json",
|
metadataFilename: "template.json",
|
||||||
}
|
}
|
||||||
|
// Calculate template base dir
|
||||||
|
_, filename, _, _ := runtime.Caller(1)
|
||||||
|
result.templateDir = filepath.Join(path.Dir(filename), "templates")
|
||||||
|
// result.templateDir = filepath.Join(result.system.homeDir, "go", "src", "github.com", "wailsapp", "wails", "cmd", "templates")
|
||||||
|
return &result
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsValidTemplate returns true if the given tempalte name resides on disk
|
// GetTemplateNames returns a map of all available templates
|
||||||
func (t *TemplateHelper) IsValidTemplate(templateName string) bool {
|
func (t *TemplateHelper) GetTemplateNames() (map[string]string, error) {
|
||||||
pathToTemplate := filepath.Join(t.templateDir.fullPath, templateName)
|
templateDirs, err := t.fs.GetSubdirs(t.templateDir)
|
||||||
return t.fs.DirExists(pathToTemplate)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SanitizeFilename sanitizes the given string to make a valid filename
|
|
||||||
func (t *TemplateHelper) SanitizeFilename(name string) string {
|
|
||||||
return sanitize.Name(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateNewTemplate creates a new template based on the given directory name and string
|
|
||||||
func (t *TemplateHelper) CreateNewTemplate(dirname string, details *TemplateMetadata) (string, error) {
|
|
||||||
|
|
||||||
// Check if this template has already been created
|
|
||||||
if t.IsValidTemplate(dirname) {
|
|
||||||
return "", fmt.Errorf("cannot create template in directory '%s' - already exists", dirname)
|
|
||||||
}
|
|
||||||
|
|
||||||
targetDir := filepath.Join(t.templateDir.fullPath, dirname)
|
|
||||||
err := t.fs.MkDir(targetDir)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
targetMetadata := filepath.Join(targetDir, t.metadataFilename)
|
return templateDirs, nil
|
||||||
err = t.fs.SaveAsJSON(details, targetMetadata)
|
}
|
||||||
|
|
||||||
return targetDir, err
|
// GetTemplateDetails returns a map of Template structs containing details
|
||||||
|
// of the found templates
|
||||||
|
func (t *TemplateHelper) GetTemplateDetails() (map[string]*Template, error) {
|
||||||
|
templateDirs, err := t.fs.GetSubdirs(t.templateDir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make(map[string]*Template)
|
||||||
|
|
||||||
|
for name, dir := range templateDirs {
|
||||||
|
result[name] = &Template{
|
||||||
|
Dir: dir,
|
||||||
|
}
|
||||||
|
metadata, err := t.LoadMetadata(dir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result[name].Metadata = metadata
|
||||||
|
if metadata["name"] != nil {
|
||||||
|
result[name].Name = metadata["name"].(string)
|
||||||
|
} else {
|
||||||
|
// Ignore bad templates?
|
||||||
|
result[name] = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadMetadata loads the template's 'metadata.json' file
|
// LoadMetadata loads the template's 'metadata.json' file
|
||||||
func (t *TemplateHelper) LoadMetadata(dir string) (*TemplateMetadata, error) {
|
func (t *TemplateHelper) LoadMetadata(dir string) (map[string]interface{}, error) {
|
||||||
templateFile := filepath.Join(dir, t.metadataFilename)
|
templateFile := filepath.Join(dir, t.metadataFilename)
|
||||||
result := &TemplateMetadata{}
|
result := make(map[string]interface{})
|
||||||
if !t.fs.FileExists(templateFile) {
|
if !t.fs.FileExists(templateFile) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@@ -104,48 +101,14 @@ func (t *TemplateHelper) LoadMetadata(dir string) (*TemplateMetadata, error) {
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTemplateDetails returns a map of Template structs containing details
|
// TemplateExists returns true if the given template name exists
|
||||||
// of the found templates
|
func (t *TemplateHelper) TemplateExists(templateName string) (bool, error) {
|
||||||
func (t *TemplateHelper) GetTemplateDetails() (map[string]*TemplateDetails, error) {
|
templates, err := t.GetTemplateNames()
|
||||||
|
|
||||||
// Get the subdirectory details
|
|
||||||
templateDirs, err := t.templateDir.GetSubdirs()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
_, exists := templates[templateName]
|
||||||
result := make(map[string]*TemplateDetails)
|
return exists, nil
|
||||||
|
|
||||||
for name, dir := range templateDirs {
|
|
||||||
result[name] = &TemplateDetails{
|
|
||||||
Path: dir,
|
|
||||||
}
|
|
||||||
_ = &TemplateMetadata{}
|
|
||||||
metadata, err := t.LoadMetadata(dir)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
result[name].Metadata = metadata
|
|
||||||
if metadata.Name != "" {
|
|
||||||
result[name].Name = metadata.Name
|
|
||||||
} else {
|
|
||||||
// Ignore bad templates?
|
|
||||||
result[name] = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTemplateFilenames returns all the filenames of the given template
|
|
||||||
func (t *TemplateHelper) GetTemplateFilenames(template *TemplateDetails) (*slicer.StringSlicer, error) {
|
|
||||||
|
|
||||||
// Get the subdirectory details
|
|
||||||
templateDir, err := t.fs.Directory(template.Path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return templateDir.GetAllFilenames()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// InstallTemplate installs the template given in the project options to the
|
// InstallTemplate installs the template given in the project options to the
|
||||||
@@ -153,61 +116,162 @@ func (t *TemplateHelper) GetTemplateFilenames(template *TemplateDetails) (*slice
|
|||||||
func (t *TemplateHelper) InstallTemplate(projectPath string, projectOptions *ProjectOptions) error {
|
func (t *TemplateHelper) InstallTemplate(projectPath string, projectOptions *ProjectOptions) error {
|
||||||
|
|
||||||
// Get template files
|
// Get template files
|
||||||
templateFilenames, err := t.GetTemplateFilenames(projectOptions.selectedTemplate)
|
template, err := t.getTemplateFiles(projectOptions.Template)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
templatePath := projectOptions.selectedTemplate.Path
|
// Copy files to target
|
||||||
|
err = template.Install(projectPath, projectOptions)
|
||||||
templateJSONFilename := filepath.Join(templatePath, t.metadataFilename)
|
|
||||||
|
|
||||||
templateFiles := templateFilenames.Filter(func(filename string) bool {
|
|
||||||
filename = filepath.FromSlash(filename)
|
|
||||||
return strings.HasPrefix(filename, templatePath) && filename != templateJSONFilename
|
|
||||||
})
|
|
||||||
|
|
||||||
templateFiles.Each(func(templateFile string) {
|
|
||||||
|
|
||||||
// Setup filenames
|
|
||||||
relativeFilename := strings.TrimPrefix(templateFile, templatePath)[1:]
|
|
||||||
targetFilename, err := filepath.Abs(filepath.Join(projectOptions.OutputDirectory, relativeFilename))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
filedata, err := t.fs.LoadAsBytes(templateFile)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// If file is a template, process it
|
|
||||||
if strings.HasSuffix(templateFile, ".template") {
|
|
||||||
templateData := string(filedata)
|
|
||||||
tmpl := template.New(templateFile)
|
|
||||||
tmpl.Parse(templateData)
|
|
||||||
var tpl bytes.Buffer
|
|
||||||
err = tmpl.Execute(&tpl, projectOptions)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove template suffix
|
|
||||||
targetFilename = strings.TrimSuffix(targetFilename, ".template")
|
|
||||||
|
|
||||||
// Set the filedata to the template result
|
|
||||||
filedata = tpl.Bytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normal file, just copy it
|
|
||||||
err = fs.CreateFile(targetFilename, filedata)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// templateFiles categorises files found in a template
|
||||||
|
type templateFiles struct {
|
||||||
|
BaseDir string
|
||||||
|
StandardFiles []string
|
||||||
|
Templates []string
|
||||||
|
Dirs []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// newTemplateFiles returns a new TemplateFiles struct
|
||||||
|
func (t *TemplateHelper) newTemplateFiles(dir string) *templateFiles {
|
||||||
|
pathsep := string(os.PathSeparator)
|
||||||
|
// Ensure base directory has trailing slash
|
||||||
|
if !strings.HasSuffix(dir, pathsep) {
|
||||||
|
dir = dir + pathsep
|
||||||
|
}
|
||||||
|
return &templateFiles{
|
||||||
|
BaseDir: dir,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddStandardFile adds the given file to the list of standard files
|
||||||
|
func (t *templateFiles) AddStandardFile(filename string) {
|
||||||
|
localPath := strings.TrimPrefix(filename, t.BaseDir)
|
||||||
|
t.StandardFiles = append(t.StandardFiles, localPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTemplate adds the given file to the list of template files
|
||||||
|
func (t *templateFiles) AddTemplate(filename string) {
|
||||||
|
localPath := strings.TrimPrefix(filename, t.BaseDir)
|
||||||
|
t.Templates = append(t.Templates, localPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddDir adds the given directory to the list of template dirs
|
||||||
|
func (t *templateFiles) AddDir(dir string) {
|
||||||
|
localPath := strings.TrimPrefix(dir, t.BaseDir)
|
||||||
|
t.Dirs = append(t.Dirs, localPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getTemplateFiles returns a struct categorising files in
|
||||||
|
// the template directory
|
||||||
|
func (t *TemplateHelper) getTemplateFiles(templateName string) (*templateFiles, error) {
|
||||||
|
|
||||||
|
templates, err := t.GetTemplateNames()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
templateDir := templates[templateName]
|
||||||
|
result := t.newTemplateFiles(templateDir)
|
||||||
|
var localPath string
|
||||||
|
err = filepath.Walk(templateDir, func(dir string, info os.FileInfo, err error) error {
|
||||||
|
if dir == templateDir {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't copy template metadata
|
||||||
|
localPath = strings.TrimPrefix(dir, templateDir+string(filepath.Separator))
|
||||||
|
if localPath == t.metadataFilename {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Categorise the file
|
||||||
|
switch {
|
||||||
|
case info.IsDir():
|
||||||
|
result.AddDir(dir)
|
||||||
|
case strings.HasSuffix(info.Name(), templateSuffix):
|
||||||
|
result.AddTemplate(dir)
|
||||||
|
default:
|
||||||
|
result.AddStandardFile(dir)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error processing template '%s' in path '%q': %v", templateName, templateDir, err)
|
||||||
|
}
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Install the template files into the given project path
|
||||||
|
func (t *templateFiles) Install(projectPath string, projectOptions *ProjectOptions) error {
|
||||||
|
|
||||||
|
fs := NewFSHelper()
|
||||||
|
|
||||||
|
// Create directories
|
||||||
|
var targetDir string
|
||||||
|
for _, dirname := range t.Dirs {
|
||||||
|
targetDir = filepath.Join(projectPath, dirname)
|
||||||
|
fs.MkDir(targetDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy standard files
|
||||||
|
var targetFile, sourceFile string
|
||||||
|
var err error
|
||||||
|
for _, filename := range t.StandardFiles {
|
||||||
|
sourceFile = filepath.Join(t.BaseDir, filename)
|
||||||
|
targetFile = filepath.Join(projectPath, filename)
|
||||||
|
|
||||||
|
err = fs.CopyFile(sourceFile, targetFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do we have template files?
|
||||||
|
if len(t.Templates) > 0 {
|
||||||
|
|
||||||
|
// Iterate over the templates
|
||||||
|
var templateFile string
|
||||||
|
var tmpl *template.Template
|
||||||
|
for _, filename := range t.Templates {
|
||||||
|
|
||||||
|
// Load template text
|
||||||
|
templateFile = filepath.Join(t.BaseDir, filename)
|
||||||
|
templateText, err := fs.LoadAsString(templateFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply template
|
||||||
|
tmpl = template.New(templateFile)
|
||||||
|
tmpl.Parse(templateText)
|
||||||
|
|
||||||
|
// Write the template to a buffer
|
||||||
|
var tpl bytes.Buffer
|
||||||
|
err = tmpl.Execute(&tpl, projectOptions)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("ERROR!!! " + err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save buffer to disk
|
||||||
|
targetFilename := strings.TrimSuffix(filename, templateSuffix)
|
||||||
|
targetFile = filepath.Join(projectPath, targetFilename)
|
||||||
|
err = ioutil.WriteFile(targetFile, tpl.Bytes(), 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
|
||||||
|
|
||||||
# dependencies
|
|
||||||
/node_modules
|
|
||||||
/.pnp
|
|
||||||
.pnp.js
|
|
||||||
|
|
||||||
# testing
|
|
||||||
/coverage
|
|
||||||
|
|
||||||
# production
|
|
||||||
/build
|
|
||||||
|
|
||||||
# misc
|
|
||||||
.DS_Store
|
|
||||||
.env.local
|
|
||||||
.env.development.local
|
|
||||||
.env.test.local
|
|
||||||
.env.production.local
|
|
||||||
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
|
||||||
|
|
||||||
## Available Scripts
|
|
||||||
|
|
||||||
In the project directory, you can run:
|
|
||||||
|
|
||||||
### `npm start`
|
|
||||||
|
|
||||||
Runs the app in the development mode.<br>
|
|
||||||
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
|
|
||||||
|
|
||||||
The page will reload if you make edits.<br>
|
|
||||||
You will also see any lint errors in the console.
|
|
||||||
|
|
||||||
### `npm test`
|
|
||||||
|
|
||||||
Launches the test runner in the interactive watch mode.<br>
|
|
||||||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
|
||||||
|
|
||||||
### `npm run build`
|
|
||||||
|
|
||||||
Builds the app for production to the `build` folder.<br>
|
|
||||||
It correctly bundles React in production mode and optimizes the build for the best performance.
|
|
||||||
|
|
||||||
The build is minified and the filenames include the hashes.<br>
|
|
||||||
Your app is ready to be deployed!
|
|
||||||
|
|
||||||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
|
||||||
|
|
||||||
### `npm run eject`
|
|
||||||
|
|
||||||
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
|
|
||||||
|
|
||||||
If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
|
||||||
|
|
||||||
Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
|
|
||||||
|
|
||||||
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
|
|
||||||
|
|
||||||
## Learn More
|
|
||||||
|
|
||||||
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
|
||||||
|
|
||||||
To learn React, check out the [React documentation](https://reactjs.org/).
|
|
||||||
|
|
||||||
### Code Splitting
|
|
||||||
|
|
||||||
This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
|
|
||||||
|
|
||||||
### Analyzing the Bundle Size
|
|
||||||
|
|
||||||
This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
|
|
||||||
|
|
||||||
### Making a Progressive Web App
|
|
||||||
|
|
||||||
This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
|
|
||||||
|
|
||||||
### Advanced Configuration
|
|
||||||
|
|
||||||
This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
|
|
||||||
|
|
||||||
### Deployment
|
|
||||||
|
|
||||||
This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
|
|
||||||
|
|
||||||
### `npm run build` fails to minify
|
|
||||||
|
|
||||||
This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "{{.NPMProjectName}}",
|
|
||||||
"author": "{{.Author.Name}}<{{.Author.Email}}>",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"private": true,
|
|
||||||
"dependencies": {
|
|
||||||
"react": "^16.8.6",
|
|
||||||
"react-dom": "^16.8.6",
|
|
||||||
"wails-react-scripts": "3.0.1-2",
|
|
||||||
"react-modal": "3.8.1"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"start": "react-scripts start",
|
|
||||||
"build": "react-scripts build",
|
|
||||||
"test": "react-scripts test",
|
|
||||||
"eject": "react-scripts eject"
|
|
||||||
},
|
|
||||||
"eslintConfig": {
|
|
||||||
"extends": "react-app"
|
|
||||||
},
|
|
||||||
"browserslist": {
|
|
||||||
"production": [
|
|
||||||
">0.2%",
|
|
||||||
"not dead",
|
|
||||||
"not op_mini all"
|
|
||||||
],
|
|
||||||
"development": [
|
|
||||||
"last 1 chrome version",
|
|
||||||
"last 1 firefox version",
|
|
||||||
"last 1 safari version"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.8 KiB |
@@ -1,38 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<meta name="theme-color" content="#000000" />
|
|
||||||
<!--
|
|
||||||
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/
|
|
||||||
-->
|
|
||||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
|
||||||
<!--
|
|
||||||
Notice the use of %PUBLIC_URL% in the tags above.
|
|
||||||
It will be replaced with the URL of the `public` folder during the build.
|
|
||||||
Only files inside the `public` folder can be referenced from the HTML.
|
|
||||||
|
|
||||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
|
||||||
work correctly both with client-side routing and a non-root public URL.
|
|
||||||
Learn how to configure a non-root public URL by running `npm run build`.
|
|
||||||
-->
|
|
||||||
<title>React App</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
||||||
<div id="app"></div>
|
|
||||||
<!--
|
|
||||||
This HTML file is a template.
|
|
||||||
If you open it directly in the browser, you will see an empty page.
|
|
||||||
|
|
||||||
You can add webfonts, meta tags, or analytics to this file.
|
|
||||||
The build step will place the bundled scripts into the <body> tag.
|
|
||||||
|
|
||||||
To begin the development, run `npm start` or `yarn start`.
|
|
||||||
To create a production bundle, use `npm run build` or `yarn build`.
|
|
||||||
-->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"short_name": "React App",
|
|
||||||
"name": "Create React App Sample",
|
|
||||||
"icons": [
|
|
||||||
{
|
|
||||||
"src": "favicon.ico",
|
|
||||||
"sizes": "64x64 32x32 24x24 16x16",
|
|
||||||
"type": "image/x-icon"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"start_url": ".",
|
|
||||||
"display": "standalone",
|
|
||||||
"theme_color": "#000000",
|
|
||||||
"background_color": "#ffffff"
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
.App {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.App-logo {
|
|
||||||
animation: App-logo-spin infinite 20s linear;
|
|
||||||
height: 40vmin;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.App-header {
|
|
||||||
background-color: #282c34;
|
|
||||||
min-height: 100vh;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
font-size: calc(10px + 2vmin);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.App-link {
|
|
||||||
color: #61dafb;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes App-logo-spin {
|
|
||||||
from {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import logo from './logo.png';
|
|
||||||
import './App.css';
|
|
||||||
import HelloWorld from './components/HelloWorld';
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<div id="app" className="App">
|
|
||||||
<header className="App-header">
|
|
||||||
<img src={logo} className="App-logo" alt="logo" />
|
|
||||||
<p>
|
|
||||||
Welcome to your new <code>wails/react</code> project.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<HelloWorld />
|
|
||||||
</header>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default App;
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import ReactDOM from 'react-dom';
|
|
||||||
import App from './App';
|
|
||||||
|
|
||||||
it('renders without crashing', () => {
|
|
||||||
const div = document.createElement('div');
|
|
||||||
ReactDOM.render(<App />, div);
|
|
||||||
ReactDOM.unmountComponentAtNode(div);
|
|
||||||
});
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import Modal from 'react-modal';
|
|
||||||
|
|
||||||
class HelloWorld extends React.Component {
|
|
||||||
constructor(props, context) {
|
|
||||||
super();
|
|
||||||
this.state = {
|
|
||||||
showModal: false
|
|
||||||
};
|
|
||||||
|
|
||||||
this.handleOpenModal = this.handleOpenModal.bind(this);
|
|
||||||
this.handleCloseModal = this.handleCloseModal.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleOpenModal () {
|
|
||||||
this.setState({ showModal: true });
|
|
||||||
|
|
||||||
window.backend.basic().then(result =>
|
|
||||||
this.setState({
|
|
||||||
result
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleCloseModal () {
|
|
||||||
this.setState({ showModal: false });
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
startAsync() {
|
|
||||||
this.setState({
|
|
||||||
loading: true
|
|
||||||
});
|
|
||||||
|
|
||||||
window.backend.basic().then(result =>
|
|
||||||
this.setState({
|
|
||||||
loading: false,
|
|
||||||
result
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { loading, result } = this.state;
|
|
||||||
return (
|
|
||||||
<div className="App">
|
|
||||||
<button onClick={this.handleOpenModal} type="button">
|
|
||||||
Hello
|
|
||||||
</button>
|
|
||||||
<Modal
|
|
||||||
isOpen={this.state.showModal}
|
|
||||||
contentLabel="Minimal Modal Example"
|
|
||||||
>
|
|
||||||
<p>{result}</p>
|
|
||||||
<button onClick={this.handleCloseModal}>Close Modal</button>
|
|
||||||
</Modal>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default HelloWorld;
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
|
|
||||||
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
|
|
||||||
sans-serif;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
|
||||||
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
|
|
||||||
monospace;
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import ReactDOM from 'react-dom';
|
|
||||||
import './index.css';
|
|
||||||
import App from './App';
|
|
||||||
|
|
||||||
import Bridge from "./wailsbridge";
|
|
||||||
|
|
||||||
Bridge.Start(() => {
|
|
||||||
ReactDOM.render(<App />, document.getElementById('app'));
|
|
||||||
});
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 301 KiB |
@@ -1,135 +0,0 @@
|
|||||||
// This optional code is used to register a service worker.
|
|
||||||
// register() is not called by default.
|
|
||||||
|
|
||||||
// This lets the app load faster on subsequent visits in production, and gives
|
|
||||||
// it offline capabilities. However, it also means that developers (and users)
|
|
||||||
// will only see deployed updates on subsequent visits to a page, after all the
|
|
||||||
// existing tabs open on the page have been closed, since previously cached
|
|
||||||
// resources are updated in the background.
|
|
||||||
|
|
||||||
// To learn more about the benefits of this model and instructions on how to
|
|
||||||
// opt-in, read https://bit.ly/CRA-PWA
|
|
||||||
|
|
||||||
const isLocalhost = Boolean(
|
|
||||||
window.location.hostname === 'localhost' ||
|
|
||||||
// [::1] is the IPv6 localhost address.
|
|
||||||
window.location.hostname === '[::1]' ||
|
|
||||||
// 127.0.0.1/8 is considered localhost for IPv4.
|
|
||||||
window.location.hostname.match(
|
|
||||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
export function register(config) {
|
|
||||||
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
|
||||||
// The URL constructor is available in all browsers that support SW.
|
|
||||||
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
|
|
||||||
if (publicUrl.origin !== window.location.origin) {
|
|
||||||
// Our service worker won't work if PUBLIC_URL is on a different origin
|
|
||||||
// from what our page is served on. This might happen if a CDN is used to
|
|
||||||
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener('load', () => {
|
|
||||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
|
||||||
|
|
||||||
if (isLocalhost) {
|
|
||||||
// This is running on localhost. Let's check if a service worker still exists or not.
|
|
||||||
checkValidServiceWorker(swUrl, config);
|
|
||||||
|
|
||||||
// Add some additional logging to localhost, pointing developers to the
|
|
||||||
// service worker/PWA documentation.
|
|
||||||
navigator.serviceWorker.ready.then(() => {
|
|
||||||
console.log(
|
|
||||||
'This web app is being served cache-first by a service ' +
|
|
||||||
'worker. To learn more, visit https://bit.ly/CRA-PWA'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Is not localhost. Just register service worker
|
|
||||||
registerValidSW(swUrl, config);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerValidSW(swUrl, config) {
|
|
||||||
navigator.serviceWorker
|
|
||||||
.register(swUrl)
|
|
||||||
.then(registration => {
|
|
||||||
registration.onupdatefound = () => {
|
|
||||||
const installingWorker = registration.installing;
|
|
||||||
if (installingWorker == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
installingWorker.onstatechange = () => {
|
|
||||||
if (installingWorker.state === 'installed') {
|
|
||||||
if (navigator.serviceWorker.controller) {
|
|
||||||
// At this point, the updated precached content has been fetched,
|
|
||||||
// but the previous service worker will still serve the older
|
|
||||||
// content until all client tabs are closed.
|
|
||||||
console.log(
|
|
||||||
'New content is available and will be used when all ' +
|
|
||||||
'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
|
|
||||||
);
|
|
||||||
|
|
||||||
// Execute callback
|
|
||||||
if (config && config.onUpdate) {
|
|
||||||
config.onUpdate(registration);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// At this point, everything has been precached.
|
|
||||||
// It's the perfect time to display a
|
|
||||||
// "Content is cached for offline use." message.
|
|
||||||
console.log('Content is cached for offline use.');
|
|
||||||
|
|
||||||
// Execute callback
|
|
||||||
if (config && config.onSuccess) {
|
|
||||||
config.onSuccess(registration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Error during service worker registration:', error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkValidServiceWorker(swUrl, config) {
|
|
||||||
// Check if the service worker can be found. If it can't reload the page.
|
|
||||||
fetch(swUrl)
|
|
||||||
.then(response => {
|
|
||||||
// Ensure service worker exists, and that we really are getting a JS file.
|
|
||||||
const contentType = response.headers.get('content-type');
|
|
||||||
if (
|
|
||||||
response.status === 404 ||
|
|
||||||
(contentType != null && contentType.indexOf('javascript') === -1)
|
|
||||||
) {
|
|
||||||
// No service worker found. Probably a different app. Reload the page.
|
|
||||||
navigator.serviceWorker.ready.then(registration => {
|
|
||||||
registration.unregister().then(() => {
|
|
||||||
window.location.reload();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Service worker found. Proceed as normal.
|
|
||||||
registerValidSW(swUrl, config);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
console.log(
|
|
||||||
'No internet connection found. App is running in offline mode.'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function unregister() {
|
|
||||||
if ('serviceWorker' in navigator) {
|
|
||||||
navigator.serviceWorker.ready.then(registration => {
|
|
||||||
registration.unregister();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
/*
|
|
||||||
Wails Bridge (c) 2019-present Lea Anthony
|
|
||||||
|
|
||||||
This prod version is to get around having to rewrite your code
|
|
||||||
for production. When doing a release build, this file will be used
|
|
||||||
instead of the full version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default {
|
|
||||||
// The main function
|
|
||||||
// Passes the main Wails object to the callback if given.
|
|
||||||
Start: function(callback) {
|
|
||||||
if (callback) {
|
|
||||||
window.wails.events.on("wails:ready", callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
module {{.BinaryName}}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/leaanthony/mewn"
|
|
||||||
"github.com/wailsapp/wails"
|
|
||||||
)
|
|
||||||
|
|
||||||
func basic() string {
|
|
||||||
return "World!"
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
|
|
||||||
js := mewn.String("./frontend/build/static/js/main.js")
|
|
||||||
css := mewn.String("./frontend/build/static/css/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,14 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "React JS",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"shortdescription": "Create React App v3 template",
|
|
||||||
"description": "Create React App v3 standar tooling",
|
|
||||||
"install": "npm install",
|
|
||||||
"build": "npm run build",
|
|
||||||
"author": "bh90210 <ktc@pm.me>",
|
|
||||||
"created": "2019-06-07 18:23:48.666414555 +0300 EEST m=+223.934866008",
|
|
||||||
"frontenddir": "frontend",
|
|
||||||
"serve": "npm run start",
|
|
||||||
"bridge": "src",
|
|
||||||
"wailsdir": ""
|
|
||||||
}
|
|
||||||
11109
cmd/templates/vuebasic/frontend/package-lock.json
generated
Normal file
11109
cmd/templates/vuebasic/frontend/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
1
cmd/templates/vuebasic/frontend/package.json.md5
Normal file
1
cmd/templates/vuebasic/frontend/package.json.md5
Normal file
@@ -0,0 +1 @@
|
|||||||
|
2b79f883dc856221fc3265755d610e40
|
||||||
BIN
cmd/templates/vuebasic/frontend/public/favicon.ico
Normal file
BIN
cmd/templates/vuebasic/frontend/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
17
cmd/templates/vuebasic/frontend/public/index.html
Normal file
17
cmd/templates/vuebasic/frontend/public/index.html
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||||
|
<title>my-vue-app-01</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<noscript>
|
||||||
|
<strong>We're sorry but my-vue-app-01 doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||||
|
</noscript>
|
||||||
|
<div id="app"></div>
|
||||||
|
<!-- built files will be auto injected -->
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -2,7 +2,6 @@ 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;
|
|
||||||
|
|
||||||
import Bridge from "./wailsbridge";
|
import Bridge from "./wailsbridge";
|
||||||
|
|
||||||
|
|||||||
@@ -11,15 +11,12 @@ func basic() string {
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
js := mewn.String("./frontend/dist/app.js")
|
|
||||||
css := mewn.String("./frontend/dist/app.css")
|
|
||||||
|
|
||||||
app := wails.CreateApp(&wails.AppConfig{
|
app := wails.CreateApp(&wails.AppConfig{
|
||||||
Width: 1024,
|
Width: 1024,
|
||||||
Height: 768,
|
Height: 768,
|
||||||
Title: "{{.Name}}",
|
Title: "{{.Name}}",
|
||||||
JS: js,
|
JS: mewn.String("./frontend/dist/app.js"),
|
||||||
CSS: css,
|
CSS: mewn.String("./frontend/dist/app.css"),
|
||||||
Colour: "#131313",
|
Colour: "#131313",
|
||||||
})
|
})
|
||||||
app.Bind(basic)
|
app.Bind(basic)
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"esversion": 6
|
|
||||||
}
|
|
||||||
21
cmd/templates/vuetify-basic/frontend/.gitignore
vendored
21
cmd/templates/vuetify-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'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,52 +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": {
|
|
||||||
"babel-polyfill": "^6.26.0",
|
|
||||||
"core-js": "^2.6.4",
|
|
||||||
"material-design-icons-iconfont": "^5.0.1",
|
|
||||||
"vue": "^2.5.22",
|
|
||||||
"vuetify": "^1.5.14"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@vue/cli-plugin-babel": "^3.4.0",
|
|
||||||
"@vue/cli-plugin-eslint": "^3.4.0",
|
|
||||||
"@vue/cli-service": "^3.4.0",
|
|
||||||
"babel-eslint": "^10.0.1",
|
|
||||||
"eslint": "^5.8.0",
|
|
||||||
"eslint-plugin-vue": "^5.0.0",
|
|
||||||
"eventsource-polyfill": "^0.9.6",
|
|
||||||
"vue-template-compiler": "^2.5.21",
|
|
||||||
"webpack-hot-middleware": "^2.24.3"
|
|
||||||
},
|
|
||||||
"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" dark>
|
|
||||||
<v-navigation-drawer v-model="drawer" clipped fixed app>
|
|
||||||
<v-list dense>
|
|
||||||
<v-list-tile>
|
|
||||||
<v-list-tile-action>
|
|
||||||
<v-icon>dashboard</v-icon>
|
|
||||||
</v-list-tile-action>
|
|
||||||
<v-list-tile-content>
|
|
||||||
<v-list-tile-title>Dashboard</v-list-tile-title>
|
|
||||||
</v-list-tile-content>
|
|
||||||
</v-list-tile>
|
|
||||||
<v-list-tile>
|
|
||||||
<v-list-tile-action>
|
|
||||||
<v-icon>settings</v-icon>
|
|
||||||
</v-list-tile-action>
|
|
||||||
<v-list-tile-content>
|
|
||||||
<v-list-tile-title>Settings</v-list-tile-title>
|
|
||||||
</v-list-tile-content>
|
|
||||||
</v-list-tile>
|
|
||||||
</v-list>
|
|
||||||
</v-navigation-drawer>
|
|
||||||
<v-toolbar app fixed clipped-left>
|
|
||||||
<v-toolbar-side-icon @click.stop="drawer = !drawer"></v-toolbar-side-icon>
|
|
||||||
<v-toolbar-title>Application</v-toolbar-title>
|
|
||||||
</v-toolbar>
|
|
||||||
<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,83 +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" dark @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" flat @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,21 +0,0 @@
|
|||||||
import 'babel-polyfill';
|
|
||||||
import Vue from "vue";
|
|
||||||
|
|
||||||
// Setup Vuetify
|
|
||||||
import Vuetify from 'vuetify';
|
|
||||||
Vue.use(Vuetify);
|
|
||||||
import 'vuetify/dist/vuetify.min.css';
|
|
||||||
import 'material-design-icons-iconfont';
|
|
||||||
|
|
||||||
import App from "./App.vue";
|
|
||||||
|
|
||||||
Vue.config.productionTip = false;
|
|
||||||
Vue.config.devtools = true;
|
|
||||||
|
|
||||||
import Bridge from "./wailsbridge";
|
|
||||||
|
|
||||||
Bridge.Start(() => {
|
|
||||||
new Vue({
|
|
||||||
render: h => h(App)
|
|
||||||
}).$mount("#app");
|
|
||||||
});
|
|
||||||
@@ -1,43 +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,
|
|
||||||
host: "localhost"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
module {{.BinaryName}}
|
|
||||||
@@ -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": "Vuetify Basic",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"shortdescription": "Vuetify + Webpack",
|
|
||||||
"description": "Basic template using Vuetify and bundled using Webpack",
|
|
||||||
"install": "npm install",
|
|
||||||
"build": "npm run build",
|
|
||||||
"author": "lea <lea.anthony@gmail.com>",
|
|
||||||
"created": "2019-05-25 09:39:40.009307 +1000 AEST m=+59.539991073",
|
|
||||||
"frontenddir": "frontend",
|
|
||||||
"serve": "npm run serve",
|
|
||||||
"bridge": "src",
|
|
||||||
"wailsdir": ""
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
// Version - Wails version
|
// Version - Wails version
|
||||||
const Version = "v0.16.0"
|
// ...oO(There must be a better way)
|
||||||
|
const Version = "v0.9.5"
|
||||||
|
|||||||
@@ -18,13 +18,11 @@ func init() {
|
|||||||
|
|
||||||
setupCommand.Action(func() error {
|
setupCommand.Action(func() error {
|
||||||
|
|
||||||
logger.PrintBanner()
|
logger.PrintBanner();
|
||||||
|
|
||||||
var err error
|
|
||||||
|
|
||||||
system := cmd.NewSystemHelper()
|
system := cmd.NewSystemHelper()
|
||||||
err = system.Initialise()
|
err := system.Initialise()
|
||||||
if err == nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,15 +39,13 @@ Create your first project by running 'wails init'.`
|
|||||||
|
|
||||||
// Check we have a cgo capable environment
|
// Check we have a cgo capable environment
|
||||||
logger.Yellow("Checking for prerequisites...")
|
logger.Yellow("Checking for prerequisites...")
|
||||||
var requiredProgramErrors bool
|
errors, err := checkRequiredPrograms()
|
||||||
requiredProgramErrors, err = checkRequiredPrograms()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Linux has library deps
|
// Linux has library deps
|
||||||
var libraryErrors bool
|
errors, err = checkLibraries()
|
||||||
libraryErrors, err = checkLibraries()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -62,8 +58,6 @@ Create your first project by running 'wails init'.`
|
|||||||
|
|
||||||
logger.White("")
|
logger.White("")
|
||||||
|
|
||||||
// Check for errors
|
|
||||||
var errors = libraryErrors || requiredProgramErrors
|
|
||||||
if !errors {
|
if !errors {
|
||||||
logger.Yellow(successMessage)
|
logger.Yellow(successMessage)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,121 +0,0 @@
|
|||||||
// +build dev
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/wailsapp/wails/cmd"
|
|
||||||
"gopkg.in/AlecAivazis/survey.v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
var templateHelper = cmd.NewTemplateHelper()
|
|
||||||
|
|
||||||
var qs = []*survey.Question{
|
|
||||||
{
|
|
||||||
Name: "Name",
|
|
||||||
Prompt: &survey.Input{Message: "Please enter the name of your template (eg: React/Webpack Basic):"},
|
|
||||||
Validate: survey.Required,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "ShortDescription",
|
|
||||||
Prompt: &survey.Input{Message: "Please enter a short description for the template (eg: React with Webpack 4):"},
|
|
||||||
Validate: survey.Required,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "Description",
|
|
||||||
Prompt: &survey.Input{Message: "Please enter a long description:"},
|
|
||||||
Validate: survey.Required,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "FrontendDir",
|
|
||||||
Prompt: &survey.Input{Message: "Please enter the name of the directory the frontend code resides (eg: frontend):"},
|
|
||||||
Validate: survey.Required,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "Install",
|
|
||||||
Prompt: &survey.Input{Message: "Please enter the install command (eg: npm install):"},
|
|
||||||
Validate: survey.Required,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "Build",
|
|
||||||
Prompt: &survey.Input{Message: "Please enter the build command (eg: npm run build):"},
|
|
||||||
Validate: survey.Required,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "Serve",
|
|
||||||
Prompt: &survey.Input{Message: "Please enter the serve command (eg: npm run serve):"},
|
|
||||||
Validate: survey.Required,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "Bridge",
|
|
||||||
Prompt: &survey.Input{Message: "Please enter the name of the directory to copy the wails bridge runtime (eg: src):"},
|
|
||||||
Validate: survey.Required,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func newTemplate(devCommand *cmd.Command) {
|
|
||||||
|
|
||||||
commandDescription := `This command scaffolds everything needed to develop a new template.`
|
|
||||||
newTemplate := devCommand.Command("newtemplate", "Generate a new template").
|
|
||||||
LongDescription(commandDescription)
|
|
||||||
|
|
||||||
newTemplate.Action(func() error {
|
|
||||||
logger.PrintSmallBanner("Generating new project template")
|
|
||||||
fmt.Println()
|
|
||||||
|
|
||||||
var answers cmd.TemplateMetadata
|
|
||||||
|
|
||||||
// perform the questions
|
|
||||||
err := survey.Ask(qs, &answers)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
dirname := templateHelper.SanitizeFilename(answers.Name)
|
|
||||||
prompt := []*survey.Question{{
|
|
||||||
Prompt: &survey.Input{
|
|
||||||
Message: "Please enter a directory name for the template:",
|
|
||||||
Default: dirname,
|
|
||||||
},
|
|
||||||
Validate: func(val interface{}) error {
|
|
||||||
err := survey.Required(val)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if templateHelper.IsValidTemplate(val.(string)) {
|
|
||||||
return fmt.Errorf("template directory already exists")
|
|
||||||
}
|
|
||||||
if templateHelper.SanitizeFilename(val.(string)) != val.(string) {
|
|
||||||
return fmt.Errorf("invalid directory name '%s'", val.(string))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
err = survey.Ask(prompt, &dirname)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
answers.Version = "1.0.0"
|
|
||||||
answers.Created = time.Now().String()
|
|
||||||
|
|
||||||
// Get Author info from system info
|
|
||||||
system := cmd.NewSystemHelper()
|
|
||||||
author, err := system.GetAuthor()
|
|
||||||
if err == nil {
|
|
||||||
answers.Author = author
|
|
||||||
}
|
|
||||||
|
|
||||||
templateDirectory, err := templateHelper.CreateNewTemplate(dirname, &answers)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Green("Created new template '%s' in directory '%s'", answers.Name, templateDirectory)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
// +build dev
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
|
|
||||||
commandDescription := `This command provides access to developer tooling.`
|
|
||||||
devCommand := app.Command("dev", "A selection of developer tools").
|
|
||||||
LongDescription(commandDescription)
|
|
||||||
|
|
||||||
// Add subcommands
|
|
||||||
newTemplate(devCommand)
|
|
||||||
|
|
||||||
devCommand.Action(func() error {
|
|
||||||
devCommand.PrintHelp()
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
20
cmd/wails/10_version.go
Normal file
20
cmd/wails/10_version.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
|
||||||
|
commandDescription := `Outputs the current version of the wails cli tool.`
|
||||||
|
|
||||||
|
versionCommand := app.Command("version", "Print Wails cli version").
|
||||||
|
LongDescription(commandDescription)
|
||||||
|
|
||||||
|
versionCommand.Action(func() error {
|
||||||
|
fmt.Println(cmd.Version)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
49
cmd/wails/12_report.go
Normal file
49
cmd/wails/12_report.go
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
|
||||||
|
commandDescription := `Generates a report to help resolve issues.`
|
||||||
|
|
||||||
|
versionCommand := app.Command("report", "Generates Report").
|
||||||
|
LongDescription(commandDescription)
|
||||||
|
|
||||||
|
versionCommand.Action(func() error {
|
||||||
|
modules := os.Getenv("GO111MODULE")
|
||||||
|
if modules == "" {
|
||||||
|
modules = "(Not set)"
|
||||||
|
}
|
||||||
|
fmt.Println("Please copy and paste this report when creating issues")
|
||||||
|
fmt.Println("------------------------------------------------------")
|
||||||
|
fmt.Printf("Wails Version: %s\n", cmd.Version)
|
||||||
|
fmt.Println("Go:")
|
||||||
|
fmt.Printf(" GOOS : %s\n", runtime.GOOS)
|
||||||
|
fmt.Printf(" GOARCH : %s\n", runtime.GOARCH)
|
||||||
|
fmt.Printf(" Version : %s\n", runtime.Version())
|
||||||
|
fmt.Println("Environment:")
|
||||||
|
fmt.Printf(" Shell : %s\n", getShell())
|
||||||
|
fmt.Printf(" GO111MODULE: %s\n", modules)
|
||||||
|
fmt.Println("------------------------------------------------------")
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func getShell() string {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "windows":
|
||||||
|
return os.Getenv("COMSPEC")
|
||||||
|
case "linux":
|
||||||
|
return os.Getenv("SHELL")
|
||||||
|
case "darwin":
|
||||||
|
return os.Getenv("SHELL")
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,10 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/leaanthony/spinner"
|
|
||||||
"github.com/wailsapp/wails/cmd"
|
"github.com/wailsapp/wails/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -53,33 +50,11 @@ Any flags that are required and not given will be prompted for.`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
genSpinner := spinner.NewSpinner()
|
|
||||||
genSpinner.SetSpinSpeed(50)
|
|
||||||
genSpinner.Start("Generating project...")
|
|
||||||
|
|
||||||
// Generate the project
|
// Generate the project
|
||||||
err = projectHelper.GenerateProject(projectOptions)
|
err = projectHelper.GenerateProject(projectOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
genSpinner.Error()
|
logger.Error(err.Error())
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
genSpinner.Success()
|
|
||||||
|
|
||||||
// Build the project
|
|
||||||
cwd, _ := os.Getwd()
|
|
||||||
projectDir := filepath.Join(cwd, projectOptions.OutputDirectory)
|
|
||||||
program := cmd.NewProgramHelper()
|
|
||||||
buildSpinner := spinner.NewSpinner()
|
|
||||||
buildSpinner.SetSpinSpeed(50)
|
|
||||||
buildSpinner.Start("Building project (this may take a while)...")
|
|
||||||
err = program.RunCommandArray([]string{"wails", "build"}, projectDir)
|
|
||||||
if err != nil {
|
|
||||||
buildSpinner.Error(err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
buildSpinner.Success()
|
|
||||||
logger.Yellow("Project '%s' built in directory '%s'!", projectOptions.Name, projectOptions.OutputDirectory)
|
|
||||||
|
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,9 +26,6 @@ func init() {
|
|||||||
initCmd.Action(func() error {
|
initCmd.Action(func() error {
|
||||||
|
|
||||||
message := "Building Application"
|
message := "Building Application"
|
||||||
if packageApp {
|
|
||||||
message = "Packaging Application"
|
|
||||||
}
|
|
||||||
if forceRebuild {
|
if forceRebuild {
|
||||||
message += " (force rebuild)"
|
message += " (force rebuild)"
|
||||||
}
|
}
|
||||||
@@ -43,7 +40,7 @@ func init() {
|
|||||||
fs := cmd.NewFSHelper()
|
fs := cmd.NewFSHelper()
|
||||||
err := projectOptions.LoadConfig(fs.Cwd())
|
err := projectOptions.LoadConfig(fs.Cwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Unable to find 'project.json'. Please check you are in a Wails project directory")
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate config
|
// Validate config
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ func init() {
|
|||||||
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("f", "Force rebuild of application components", &forceRebuild)
|
BoolFlag("f", "Force rebuild of application components", &forceRebuild)
|
||||||
|
|
||||||
@@ -24,28 +24,19 @@ func init() {
|
|||||||
logger.PrintSmallBanner(message)
|
logger.PrintSmallBanner(message)
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
|
||||||
// Check Mewn is installed
|
|
||||||
err := cmd.CheckMewn()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Project options
|
// Project options
|
||||||
projectOptions := &cmd.ProjectOptions{}
|
projectOptions := &cmd.ProjectOptions{}
|
||||||
|
|
||||||
// Check we are in project directory
|
// Check we are in project directory
|
||||||
// Check project.json loads correctly
|
// Check project.json loads correctly
|
||||||
fs := cmd.NewFSHelper()
|
fs := cmd.NewFSHelper()
|
||||||
err = projectOptions.LoadConfig(fs.Cwd())
|
err := projectOptions.LoadConfig(fs.Cwd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save project directory
|
// Check Mewn is installed
|
||||||
projectDir := fs.Cwd()
|
err = cmd.CheckMewn()
|
||||||
|
|
||||||
// Install the bridge library
|
|
||||||
err = cmd.InstallBridge("serve", projectDir, projectOptions)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,25 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/leaanthony/spinner"
|
"github.com/leaanthony/spinner"
|
||||||
"github.com/mitchellh/go-homedir"
|
|
||||||
"github.com/wailsapp/wails/cmd"
|
"github.com/wailsapp/wails/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
||||||
var prereleaseRequired bool
|
|
||||||
var specificVersion string
|
|
||||||
|
|
||||||
// var forceRebuild = false
|
// var forceRebuild = false
|
||||||
checkSpinner := spinner.NewSpinner()
|
checkSpinner := spinner.NewSpinner()
|
||||||
checkSpinner.SetSpinSpeed(50)
|
checkSpinner.SetSpinSpeed(50)
|
||||||
|
|
||||||
commandDescription := `This command allows you to update your version of Wails.`
|
commandDescription := `This command checks if there are updates to Wails.`
|
||||||
updateCmd := app.Command("update", "Update to newer [pre]releases or specific versions").
|
updateCmd := app.Command("update", "Check for Updates.").
|
||||||
LongDescription(commandDescription).
|
LongDescription(commandDescription)
|
||||||
BoolFlag("pre", "Update to latest Prerelease", &prereleaseRequired).
|
|
||||||
StringFlag("version", "Install a specific version (Overrides other flags)", &specificVersion)
|
|
||||||
|
|
||||||
updateCmd.Action(func() error {
|
updateCmd.Action(func() error {
|
||||||
|
|
||||||
@@ -32,133 +29,53 @@ func init() {
|
|||||||
|
|
||||||
// Get versions
|
// Get versions
|
||||||
checkSpinner.Start(message)
|
checkSpinner.Start(message)
|
||||||
|
resp, err := http.Get("https://api.github.com/repos/wailsapp/wails/tags")
|
||||||
github := cmd.NewGitHubHelper()
|
|
||||||
var desiredVersion *cmd.SemanticVersion
|
|
||||||
var err error
|
|
||||||
var valid bool
|
|
||||||
|
|
||||||
if len(specificVersion) > 0 {
|
|
||||||
// Check if this is a valid version
|
|
||||||
valid, err = github.IsValidTag(specificVersion)
|
|
||||||
if err == nil {
|
|
||||||
if !valid {
|
|
||||||
err = fmt.Errorf("version '%s' is invalid", specificVersion)
|
|
||||||
} else {
|
|
||||||
desiredVersion, err = cmd.NewSemanticVersion(specificVersion)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if prereleaseRequired {
|
|
||||||
desiredVersion, err = github.GetLatestPreRelease()
|
|
||||||
} else {
|
|
||||||
desiredVersion, err = github.GetLatestStableRelease()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
checkSpinner.Error(err.Error())
|
checkSpinner.Error(err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
checkSpinner.Success()
|
checkSpinner.Success()
|
||||||
fmt.Println()
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
fmt.Println(" Current Version : " + cmd.Version)
|
checkSpinner.Error(err.Error())
|
||||||
|
return err
|
||||||
if len(specificVersion) > 0 {
|
|
||||||
fmt.Printf(" Desired Version : v%s\n", desiredVersion)
|
|
||||||
} else {
|
|
||||||
if prereleaseRequired {
|
|
||||||
fmt.Printf(" Latest Prerelease : v%s\n", desiredVersion)
|
|
||||||
} else {
|
|
||||||
fmt.Printf(" Latest Release : v%s\n", desiredVersion)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return updateToVersion(desiredVersion, len(specificVersion) > 0)
|
data := []map[string]interface{}{}
|
||||||
})
|
err = json.Unmarshal(body, &data)
|
||||||
}
|
|
||||||
|
|
||||||
func updateToVersion(targetVersion *cmd.SemanticVersion, force bool) error {
|
|
||||||
|
|
||||||
var targetVersionString = "v" + targetVersion.String()
|
|
||||||
|
|
||||||
// Early exit
|
|
||||||
if targetVersionString == cmd.Version {
|
|
||||||
logger.Green("Looks like you're up to date!")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var desiredVersion string
|
|
||||||
|
|
||||||
if !force {
|
|
||||||
|
|
||||||
compareVersion := cmd.Version
|
|
||||||
|
|
||||||
currentVersion, err := cmd.NewSemanticVersion(compareVersion)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var success bool
|
latestVersion := data[0]["name"].(string)
|
||||||
|
fmt.Println()
|
||||||
// Release -> Pre-Release = Massage current version to prerelease format
|
fmt.Println("Current Version: " + cmd.Version)
|
||||||
if targetVersion.IsPreRelease() && currentVersion.IsRelease() {
|
fmt.Println(" Latest Version: " + latestVersion)
|
||||||
testVersion, err := cmd.NewSemanticVersion(compareVersion + "-0")
|
if latestVersion != cmd.Version {
|
||||||
|
updateSpinner := spinner.NewSpinner()
|
||||||
|
updateSpinner.SetSpinSpeed(40)
|
||||||
|
updateSpinner.Start("Updating to : " + latestVersion)
|
||||||
|
err = cmd.NewProgramHelper().RunCommandArray([]string{"go", "get", "-u", "-a", "github.com/wailsapp/wails/cmd/wails"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
updateSpinner.Error(err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
success, _ = targetVersion.IsGreaterThan(testVersion)
|
version, _, err := cmd.NewProgramHelper().GetOutputFromCommand("wails version")
|
||||||
}
|
version = strings.TrimSpace(version)
|
||||||
// Pre-Release -> Release = Massage target version to prerelease format
|
|
||||||
if targetVersion.IsRelease() && currentVersion.IsPreRelease() {
|
|
||||||
// We are ok with greater than or equal
|
|
||||||
mainversion := currentVersion.MainVersion()
|
|
||||||
targetVersion, err = cmd.NewSemanticVersion(targetVersion.String())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
updateSpinner.Error(err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
success, _ = targetVersion.IsGreaterThanOrEqual(mainversion)
|
if version != latestVersion {
|
||||||
|
updateSpinner.Error()
|
||||||
|
logger.Yellow("Weird! Wails was supposed to update to %s but seems to be at %s instead.", latestVersion, version)
|
||||||
|
} else {
|
||||||
|
updateSpinner.Success()
|
||||||
|
logger.Green("Success! Wails updated to " + version)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.Yellow("Looks like you're up to date!")
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
// Release -> Release = Standard check
|
})
|
||||||
if (targetVersion.IsRelease() && currentVersion.IsRelease()) ||
|
|
||||||
(targetVersion.IsPreRelease() && currentVersion.IsPreRelease()) {
|
|
||||||
|
|
||||||
success, _ = targetVersion.IsGreaterThan(currentVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare
|
|
||||||
if !success {
|
|
||||||
logger.Red("The requested version is lower than the current version.")
|
|
||||||
logger.Red("If this is what you really want to do, use `wails update -version %s`", targetVersionString)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
desiredVersion = "v" + targetVersion.String()
|
|
||||||
|
|
||||||
} else {
|
|
||||||
desiredVersion = "v" + targetVersion.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println()
|
|
||||||
updateSpinner := spinner.NewSpinner()
|
|
||||||
updateSpinner.SetSpinSpeed(40)
|
|
||||||
updateSpinner.Start("Installing Wails " + desiredVersion)
|
|
||||||
|
|
||||||
// Run command in non module directory
|
|
||||||
homeDir, err := homedir.Dir()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("Cannot find home directory! Please file a bug report!")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = cmd.NewProgramHelper().RunCommandArray([]string{"go", "get", "github.com/wailsapp/wails/cmd/wails@" + desiredVersion}, homeDir)
|
|
||||||
if err != nil {
|
|
||||||
updateSpinner.Error(err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
updateSpinner.Success()
|
|
||||||
fmt.Println()
|
|
||||||
logger.Green("Wails updated to " + desiredVersion)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/pkg/browser"
|
|
||||||
|
|
||||||
"github.com/wailsapp/wails/cmd"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
|
|
||||||
commandDescription := `Generates an issue in Github using the given title, description and system report.`
|
|
||||||
|
|
||||||
initCommand := app.Command("issue", "Generates an issue in Github").
|
|
||||||
LongDescription(commandDescription)
|
|
||||||
|
|
||||||
initCommand.Action(func() error {
|
|
||||||
|
|
||||||
logger.PrintSmallBanner("Generate Issue")
|
|
||||||
fmt.Println()
|
|
||||||
message := `Thanks for taking the time to submit an issue!
|
|
||||||
|
|
||||||
To help you in this process, we will ask for some information, add Go/Wails details automatically, then prepare the issue for your editing and submission.
|
|
||||||
`
|
|
||||||
|
|
||||||
logger.Yellow(message)
|
|
||||||
|
|
||||||
title := cmd.Prompt("Issue Title")
|
|
||||||
description := cmd.Prompt("Issue Description")
|
|
||||||
|
|
||||||
var str strings.Builder
|
|
||||||
|
|
||||||
gomodule, exists := os.LookupEnv("GO111MODULE")
|
|
||||||
if !exists {
|
|
||||||
gomodule = "(Not Set)"
|
|
||||||
}
|
|
||||||
|
|
||||||
str.WriteString("\n| Name | Value |\n| ----- | ----- |\n")
|
|
||||||
str.WriteString(fmt.Sprintf("| Wails Version | %s |\n", cmd.Version))
|
|
||||||
str.WriteString(fmt.Sprintf("| Go Version | %s |\n", runtime.Version()))
|
|
||||||
str.WriteString(fmt.Sprintf("| Platform | %s |\n", runtime.GOOS))
|
|
||||||
str.WriteString(fmt.Sprintf("| Arch | %s |\n", runtime.GOARCH))
|
|
||||||
str.WriteString(fmt.Sprintf("| GO111MODULE | %s |\n", gomodule))
|
|
||||||
|
|
||||||
fmt.Println()
|
|
||||||
fmt.Println("Processing template and preparing for upload.")
|
|
||||||
|
|
||||||
// Grab issue template
|
|
||||||
resp, err := http.Get("https://raw.githubusercontent.com/wailsapp/wails/master/.github/ISSUE_TEMPLATE/bug_report.md")
|
|
||||||
if err != nil {
|
|
||||||
logger.Red("Unable to read in issue template. Are you online?")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
template, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
body := string(template)
|
|
||||||
body = "**Description**\n" + (strings.Split(body, "**Description**")[1])
|
|
||||||
fullURL := "https://github.com/wailsapp/wails/issues/new?"
|
|
||||||
body = strings.Replace(body, "A clear and concise description of what the bug is.", description, -1)
|
|
||||||
body = strings.Replace(body, "Please provide your platform, GO version and variables, etc", str.String(), -1)
|
|
||||||
params := "title=" + title + "&body=" + body
|
|
||||||
|
|
||||||
fmt.Println("Opening browser to file issue.")
|
|
||||||
browser.OpenURL(fullURL + url.PathEscape(params))
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
// +build windows
|
|
||||||
|
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Credit: https://stackoverflow.com/a/52579002
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
stdout := windows.Handle(os.Stdout.Fd())
|
|
||||||
var originalMode uint32
|
|
||||||
|
|
||||||
_ = windows.GetConsoleMode(stdout, &originalMode)
|
|
||||||
_ = windows.SetConsoleMode(stdout, originalMode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
|
||||||
}
|
|
||||||
@@ -87,7 +87,7 @@ func (e *eventManager) start(renderer Renderer) {
|
|||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
|
|
||||||
// Run main loop in separate goroutine
|
// Run main loop in seperate goroutine
|
||||||
go func() {
|
go func() {
|
||||||
wg.Done()
|
wg.Done()
|
||||||
e.log.Info("Listening")
|
e.log.Info("Listening")
|
||||||
@@ -126,7 +126,7 @@ func (e *eventManager) start(renderer Renderer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove expired listeners in place
|
// Remove expired listners in place
|
||||||
if len(listenersToRemove) > 0 {
|
if len(listenersToRemove) > 0 {
|
||||||
listeners := e.listeners[event.Name][:0]
|
listeners := e.listeners[event.Name][:0]
|
||||||
for _, listener := range listeners {
|
for _, listener := range listeners {
|
||||||
|
|||||||
23
go.mod
23
go.mod
@@ -1,7 +1,6 @@
|
|||||||
module github.com/wailsapp/wails
|
module github.com/wailsapp/wails
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Masterminds/semver v1.4.2 // indirect
|
|
||||||
github.com/dchest/cssmin v0.0.0-20151210170030-fb8d9b44afdc // indirect
|
github.com/dchest/cssmin v0.0.0-20151210170030-fb8d9b44afdc // indirect
|
||||||
github.com/dchest/htmlmin v0.0.0-20150526090704-e254725e81ac
|
github.com/dchest/htmlmin v0.0.0-20150526090704-e254725e81ac
|
||||||
github.com/dchest/jsmin v0.0.0-20160823214000-faeced883947 // indirect
|
github.com/dchest/jsmin v0.0.0-20160823214000-faeced883947 // indirect
|
||||||
@@ -9,23 +8,17 @@ require (
|
|||||||
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
|
||||||
github.com/jackmordaunt/icns v1.0.0
|
github.com/jackmordaunt/icns v1.0.0
|
||||||
github.com/kennygrant/sanitize v1.2.4
|
github.com/leaanthony/mewn v0.9.1
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
|
github.com/leaanthony/slicer v1.0.0
|
||||||
github.com/leaanthony/mewn v0.10.7
|
github.com/leaanthony/spinner v0.5.0
|
||||||
github.com/leaanthony/slicer v1.3.1
|
|
||||||
github.com/leaanthony/spinner v0.5.3
|
|
||||||
github.com/masterminds/semver v1.4.2
|
|
||||||
github.com/mattn/go-colorable v0.1.1 // indirect
|
github.com/mattn/go-colorable v0.1.1 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.7 // indirect
|
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
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/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.3.0
|
||||||
github.com/stretchr/testify v1.3.0 // indirect
|
github.com/stretchr/testify v1.3.0 // indirect
|
||||||
github.com/wailsapp/webview v0.2.7
|
github.com/wailsapp/webview v0.2.5
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 // indirect
|
golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f // indirect
|
||||||
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5 // indirect
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd // indirect
|
||||||
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862
|
golang.org/x/sys v0.0.0-20190222171317-cd391775e71e // indirect
|
||||||
gopkg.in/AlecAivazis/survey.v1 v1.8.4
|
|
||||||
)
|
)
|
||||||
|
|||||||
77
go.sum
77
go.sum
@@ -1,7 +1,3 @@
|
|||||||
github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc=
|
|
||||||
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
|
||||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
|
|
||||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
|
|
||||||
github.com/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=
|
||||||
@@ -15,85 +11,66 @@ 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=
|
||||||
github.com/go-playground/colors v1.2.0/go.mod h1:miw1R2JIE19cclPxsXqNdzLZsk4DP4iF+m88bRc7kfM=
|
github.com/go-playground/colors v1.2.0/go.mod h1:miw1R2JIE19cclPxsXqNdzLZsk4DP4iF+m88bRc7kfM=
|
||||||
|
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||||
|
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ=
|
|
||||||
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
|
|
||||||
github.com/jackmordaunt/icns v1.0.0 h1:RYSxplerf/l/DUd09AHtITwckkv/mqjVv4DjYdPmAMQ=
|
github.com/jackmordaunt/icns v1.0.0 h1:RYSxplerf/l/DUd09AHtITwckkv/mqjVv4DjYdPmAMQ=
|
||||||
github.com/jackmordaunt/icns v1.0.0/go.mod h1:7TTQVEuGzVVfOPPlLNHJIkzA6CoV7aH1Dv9dW351oOo=
|
github.com/jackmordaunt/icns v1.0.0/go.mod h1:7TTQVEuGzVVfOPPlLNHJIkzA6CoV7aH1Dv9dW351oOo=
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
|
||||||
github.com/kennygrant/sanitize v1.2.4 h1:gN25/otpP5vAsO2djbMhF/LQX6R7+O1TB4yv8NzpJ3o=
|
|
||||||
github.com/kennygrant/sanitize v1.2.4/go.mod h1:LGsjYYtgxbetdg5owWB2mpgUL6e2nfw2eObZ0u0qvak=
|
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
github.com/leaanthony/mewn v0.9.1 h1:+qmAnR5nETU/00o5wvYJ7w9Y36R9uIBRB9I15E9Ru8A=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/leaanthony/mewn v0.9.1/go.mod h1:CRkTx8unLiSSilu/Sd7i1LwrdaAL+3eQ3ses99qGMEQ=
|
||||||
github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
|
github.com/leaanthony/slicer v1.0.0 h1:BV2CySexcZ20qyHp5qBTxQhsazR6e8MBTF1EHmGu1xw=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/leaanthony/slicer v1.0.0/go.mod h1:VMB/HGvr3uR3MRpFWHWAm0w+DHQLzPHYe2pKfpFlQIQ=
|
||||||
github.com/leaanthony/mewn v0.10.7 h1:jCcNJyIUOpwj+I5SuATvCugDjHkoo+j6ubEOxxrxmPA=
|
github.com/leaanthony/spinner v0.5.0 h1:HQykt/iTy7fmINEREtRbWrt+8j4MxC8dtvWBxEWM9oA=
|
||||||
github.com/leaanthony/mewn v0.10.7/go.mod h1:CRkTx8unLiSSilu/Sd7i1LwrdaAL+3eQ3ses99qGMEQ=
|
github.com/leaanthony/spinner v0.5.0/go.mod h1:8TSFz9SL1AUC4XSbEFYE6SfN5Mlus51qYluVGrie9ww=
|
||||||
github.com/leaanthony/slicer v1.3.1 h1:n2iIV2sxvL/3bpnmVY0vBjXf3yYFWcB6CYLVMrzJxRw=
|
|
||||||
github.com/leaanthony/slicer v1.3.1/go.mod h1:VMB/HGvr3uR3MRpFWHWAm0w+DHQLzPHYe2pKfpFlQIQ=
|
|
||||||
github.com/leaanthony/spinner v0.5.3 h1:IMTvgdQCec5QA4qRy0wil4XsRP+QcG1OwLWVK/LPZ5Y=
|
|
||||||
github.com/leaanthony/spinner v0.5.3/go.mod h1:oHlrvWicr++CVV7ALWYi+qHk/XNA91D9IJ48IqmpVUo=
|
|
||||||
github.com/leaanthony/synx v0.1.0 h1:R0lmg2w6VMb8XcotOwAe5DLyzwjLrskNkwU7LLWsyL8=
|
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/masterminds/semver v1.4.2 h1:BgrAYDjlAebjtOwS7C/1QZoh5WgyXx4b59ydc+Ph8xI=
|
|
||||||
github.com/masterminds/semver v1.4.2/go.mod h1:s7KNT9fnd7edGzwwP7RBX4H0v/CYd5qdOLfkL1V75yg=
|
|
||||||
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
|
github.com/mattn/go-colorable v0.0.9 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=
|
||||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
|
||||||
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
|
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
|
||||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
|
github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw=
|
||||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc=
|
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
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/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
|
||||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
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/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/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||||
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
|
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
|
github.com/ribice/glice v0.0.0-20181011133736-685f13fa9b12/go.mod h1:A+ednilkKNW0CJGLsrLkq0D49M4EhlCi8gvnkwoZFn0=
|
||||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
github.com/sirupsen/logrus v1.3.0 h1:hI/7Q+DtNZ2kINb6qt/lS+IyXnHQe9e90POfeewL/ME=
|
||||||
|
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
|
||||||
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/wailsapp/webview v0.2.7 h1:fN5L5H9Oivg9IJPk7uaXQnjqB68Fny11ZWkIaTIZHmk=
|
github.com/wailsapp/webview v0.2.5 h1:/VacryPEUeMBb2VHHOjpoIze6ki8tW3qYX04MnI0b7o=
|
||||||
github.com/wailsapp/webview v0.2.7/go.mod h1:XO9HJbKWokDxUYTWQEBCYg95n/To1v7PxvanDNVf8hY=
|
github.com/wailsapp/webview v0.2.5/go.mod h1:XO9HJbKWokDxUYTWQEBCYg95n/To1v7PxvanDNVf8hY=
|
||||||
github.com/zserge/webview v0.0.0-20190123072648-16c93bcaeaeb/go.mod h1:a1CV8KR4Dd1eP2g+mEijGOp+HKczwdKHWyx0aPHKvo4=
|
github.com/zserge/webview v0.0.0-20190123072648-16c93bcaeaeb/go.mod h1:a1CV8KR4Dd1eP2g+mEijGOp+HKczwdKHWyx0aPHKvo4=
|
||||||
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 h1:u+LnwYTOOW7Ukr/fppxEb1Nwz0AtPflrblfvUudpo+I=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/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-20190222235706-ffb98f73852f h1:qWFY9ZxP3tfI37wYIs/MnIAqK0vlXp1xnYEa5HxFSSY=
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk=
|
golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/net v0.0.0-20181220203305-927f97764cc3 h1:eH6Eip3UpmR+yM/qI9Ijluzb1bNv/cAU/n+6l8tRSis=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5 h1:6M3SDHlHHDCx2PcQw3S4KsR170vGqDhJDOmpVd4Hjak=
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd h1:HuTn7WObtcDo9uEEU7rEqL0jYthdXAmZ6PP+meazmaU=
|
||||||
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
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 h1:pf3XwC90UUdNPYWZdFjhGBE7DUFuK3Ct1zWmZ65QN30=
|
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb h1:pf3XwC90UUdNPYWZdFjhGBE7DUFuK3Ct1zWmZ65QN30=
|
||||||
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
|
||||||
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-20190222171317-cd391775e71e h1:oF7qaQxUH6KzFdKN4ww7NpPdo53SZi4UlcksLrb2y/o=
|
||||||
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862 h1:rM0ROo5vb9AdYJi1110yjWGMej9ITfKddS89P3Fkhug=
|
golang.org/x/sys v0.0.0-20190222171317-cd391775e71e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
gopkg.in/AlecAivazis/survey.v1 v1.8.4 h1:10xXXN3wgIhPheb5NI58zFgZv32Ana7P3Tl4shW+0Qc=
|
|
||||||
gopkg.in/AlecAivazis/survey.v1 v1.8.4/go.mod h1:iBNOmqKz/NUbZx3bA+4hAGLRC7fSK7tgtVDT4tB22XA=
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package wails
|
package wails
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ipcResponse contains the response data from an RPC call
|
// ipcResponse contains the response data from an RPC call
|
||||||
@@ -37,9 +37,7 @@ func newSuccessResponse(callbackID string, data interface{}) *ipcResponse {
|
|||||||
// Serialise formats the response to a string
|
// Serialise formats the response to a string
|
||||||
func (i *ipcResponse) Serialise() (string, error) {
|
func (i *ipcResponse) Serialise() (string, error) {
|
||||||
b, err := json.Marshal(i)
|
b, err := json.Marshal(i)
|
||||||
if err != nil {
|
result := strings.Replace(string(b), "\\", "\\\\", -1)
|
||||||
return "", err
|
result = strings.Replace(result, "'", "\\'", -1)
|
||||||
}
|
|
||||||
result := hex.EncodeToString(b)
|
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ type Renderer interface {
|
|||||||
// Events
|
// Events
|
||||||
NotifyEvent(eventData *eventData) error
|
NotifyEvent(eventData *eventData) error
|
||||||
|
|
||||||
|
// Injection
|
||||||
|
AddJSList(js []string)
|
||||||
|
AddCSSList(css []string)
|
||||||
|
|
||||||
// Dialog Runtime
|
// Dialog Runtime
|
||||||
SelectFile() string
|
SelectFile() string
|
||||||
SelectDirectory() string
|
SelectDirectory() string
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/dchest/htmlmin"
|
"github.com/dchest/htmlmin"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
@@ -37,14 +36,15 @@ type Headless struct {
|
|||||||
appConfig *AppConfig
|
appConfig *AppConfig
|
||||||
eventManager *eventManager
|
eventManager *eventManager
|
||||||
bindingCache []string
|
bindingCache []string
|
||||||
|
frameworkJS string
|
||||||
|
frameworkCSS string
|
||||||
|
jsCache []string
|
||||||
|
cssCache []string
|
||||||
|
|
||||||
// Headless specific
|
// Headless specific
|
||||||
initialisationJS []string
|
initialisationJS []string
|
||||||
server *http.Server
|
server *http.Server
|
||||||
theConnection *websocket.Conn
|
theConnection *websocket.Conn
|
||||||
|
|
||||||
// Mutex for writing to the socket
|
|
||||||
lock sync.Mutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialise the Headless Renderer
|
// Initialise the Headless Renderer
|
||||||
@@ -53,7 +53,7 @@ func (h *Headless) Initialise(appConfig *AppConfig, ipcManager *ipcManager, even
|
|||||||
h.appConfig = appConfig
|
h.appConfig = appConfig
|
||||||
h.eventManager = eventManager
|
h.eventManager = eventManager
|
||||||
ipcManager.bindRenderer(h)
|
ipcManager.bindRenderer(h)
|
||||||
h.log = newCustomLogger("Bridge")
|
h.log = newCustomLogger("Headless")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,10 +103,6 @@ func (h *Headless) wsBridgeHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *Headless) sendMessage(conn *websocket.Conn, msg string) {
|
func (h *Headless) sendMessage(conn *websocket.Conn, msg string) {
|
||||||
|
|
||||||
h.lock.Lock()
|
|
||||||
defer h.lock.Unlock()
|
|
||||||
|
|
||||||
if err := conn.WriteMessage(websocket.TextMessage, []byte(msg)); err != nil {
|
if err := conn.WriteMessage(websocket.TextMessage, []byte(msg)); err != nil {
|
||||||
h.log.Error(err.Error())
|
h.log.Error(err.Error())
|
||||||
}
|
}
|
||||||
@@ -149,8 +145,8 @@ func (h *Headless) Run() error {
|
|||||||
h.server = &http.Server{Addr: ":34115"}
|
h.server = &http.Server{Addr: ":34115"}
|
||||||
http.HandleFunc("/bridge", h.wsBridgeHandler)
|
http.HandleFunc("/bridge", h.wsBridgeHandler)
|
||||||
|
|
||||||
h.log.Info("Bridge mode started.")
|
h.log.Info("Headless mode started.")
|
||||||
h.log.Info("The frontend will connect automatically.")
|
h.log.Info("The Wails bridge will connect automatically.")
|
||||||
|
|
||||||
err := h.server.ListenAndServe()
|
err := h.server.ListenAndServe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -168,24 +164,36 @@ func (h *Headless) NewBinding(methodName string) error {
|
|||||||
// SelectFile is unsupported for Headless but required
|
// SelectFile is unsupported for Headless but required
|
||||||
// for the Renderer interface
|
// for the Renderer interface
|
||||||
func (h *Headless) SelectFile() string {
|
func (h *Headless) SelectFile() string {
|
||||||
h.log.Warn("SelectFile() unsupported in bridge mode")
|
h.log.Error("SelectFile() unsupported in headless mode")
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelectDirectory is unsupported for Headless but required
|
// SelectDirectory is unsupported for Headless but required
|
||||||
// for the Renderer interface
|
// for the Renderer interface
|
||||||
func (h *Headless) SelectDirectory() string {
|
func (h *Headless) SelectDirectory() string {
|
||||||
h.log.Warn("SelectDirectory() unsupported in bridge mode")
|
h.log.Error("SelectDirectory() unsupported in headless mode")
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelectSaveFile is unsupported for Headless but required
|
// SelectSaveFile is unsupported for Headless but required
|
||||||
// for the Renderer interface
|
// for the Renderer interface
|
||||||
func (h *Headless) SelectSaveFile() string {
|
func (h *Headless) SelectSaveFile() string {
|
||||||
h.log.Warn("SelectSaveFile() unsupported in bridge mode")
|
h.log.Error("SelectSaveFile() unsupported in headless mode")
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddJSList adds a slice of JS strings to the list of js
|
||||||
|
// files injected at startup
|
||||||
|
func (h *Headless) AddJSList(jsCache []string) {
|
||||||
|
h.jsCache = jsCache
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddCSSList adds a slice of CSS strings to the list of css
|
||||||
|
// files injected at startup
|
||||||
|
func (h *Headless) AddCSSList(cssCache []string) {
|
||||||
|
h.cssCache = cssCache
|
||||||
|
}
|
||||||
|
|
||||||
// Callback sends a callback to the frontend
|
// Callback sends a callback to the frontend
|
||||||
func (h *Headless) Callback(data string) error {
|
func (h *Headless) Callback(data string) error {
|
||||||
return h.evalJS(data, callbackMessage)
|
return h.evalJS(data, callbackMessage)
|
||||||
@@ -229,23 +237,23 @@ func (h *Headless) SetColour(colour string) error {
|
|||||||
// Fullscreen is unsupported for Headless but required
|
// Fullscreen is unsupported for Headless but required
|
||||||
// for the Renderer interface
|
// for the Renderer interface
|
||||||
func (h *Headless) Fullscreen() {
|
func (h *Headless) Fullscreen() {
|
||||||
h.log.Warn("Fullscreen() unsupported in bridge mode")
|
h.log.Warn("Fullscreen() unsupported in headless mode")
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnFullscreen is unsupported for Headless but required
|
// UnFullscreen is unsupported for Headless but required
|
||||||
// for the Renderer interface
|
// for the Renderer interface
|
||||||
func (h *Headless) UnFullscreen() {
|
func (h *Headless) UnFullscreen() {
|
||||||
h.log.Warn("UnFullscreen() unsupported in bridge mode")
|
h.log.Warn("UnFullscreen() unsupported in headless mode")
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTitle is currently unsupported for Headless but required
|
// SetTitle is currently unsupported for Headless but required
|
||||||
// for the Renderer interface
|
// for the Renderer interface
|
||||||
func (h *Headless) SetTitle(title string) {
|
func (h *Headless) SetTitle(title string) {
|
||||||
h.log.WarnFields("SetTitle() unsupported in bridge mode", Fields{"title": title})
|
h.log.WarnFields("SetTitle() unsupported in headless mode", Fields{"title": title})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close is unsupported for Headless but required
|
// Close is unsupported for Headless but required
|
||||||
// for the Renderer interface
|
// for the Renderer interface
|
||||||
func (h *Headless) Close() {
|
func (h *Headless) Close() {
|
||||||
h.log.Warn("Close() unsupported in bridge mode")
|
h.log.Warn("Close() unsupported in headless mode")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,13 @@ type webViewRenderer struct {
|
|||||||
config *AppConfig
|
config *AppConfig
|
||||||
eventManager *eventManager
|
eventManager *eventManager
|
||||||
bindingCache []string
|
bindingCache []string
|
||||||
|
frameworkJS string
|
||||||
|
frameworkCSS string
|
||||||
|
|
||||||
|
// This is a list of all the JS/CSS that needs injecting
|
||||||
|
// It will get injected in order
|
||||||
|
jsCache []string
|
||||||
|
cssCache []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialise sets up the WebView
|
// Initialise sets up the WebView
|
||||||
@@ -115,7 +122,7 @@ func (w *webViewRenderer) evalJSSync(js string) error {
|
|||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
exit := false
|
exit := false
|
||||||
// We are done when we receive the Callback ID
|
// We are done when we recieve the Callback ID
|
||||||
w.log.Debug("SyncJS: sending with ID = " + ID)
|
w.log.Debug("SyncJS: sending with ID = " + ID)
|
||||||
w.eventManager.On(ID, func(...interface{}) {
|
w.eventManager.On(ID, func(...interface{}) {
|
||||||
w.log.Debug("SyncJS: Got callback ID = " + ID)
|
w.log.Debug("SyncJS: Got callback ID = " + ID)
|
||||||
@@ -168,13 +175,13 @@ func (w *webViewRenderer) Run() error {
|
|||||||
w.evalJSSync(binding)
|
w.evalJSSync(binding)
|
||||||
}
|
}
|
||||||
|
|
||||||
// // Inject Framework
|
// Inject Framework
|
||||||
// if w.frameworkJS != "" {
|
if w.frameworkJS != "" {
|
||||||
// w.evalJSSync(w.frameworkJS)
|
w.evalJSSync(w.frameworkJS)
|
||||||
// }
|
}
|
||||||
// if w.frameworkCSS != "" {
|
if w.frameworkCSS != "" {
|
||||||
// w.injectCSS(w.frameworkCSS)
|
w.injectCSS(w.frameworkCSS)
|
||||||
// }
|
}
|
||||||
|
|
||||||
// Inject user CSS
|
// Inject user CSS
|
||||||
if w.config.CSS != "" {
|
if w.config.CSS != "" {
|
||||||
@@ -192,6 +199,16 @@ func (w *webViewRenderer) Run() error {
|
|||||||
w.injectCSS(defaultCSS)
|
w.injectCSS(defaultCSS)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Inject all the CSS files that have been added
|
||||||
|
for _, css := range w.cssCache {
|
||||||
|
w.injectCSS(css)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inject all the JS files that have been added
|
||||||
|
for _, js := range w.jsCache {
|
||||||
|
w.evalJSSync(js)
|
||||||
|
}
|
||||||
|
|
||||||
// Inject user JS
|
// Inject user JS
|
||||||
if w.config.JS != "" {
|
if w.config.JS != "" {
|
||||||
outputJS := fmt.Sprintf("%.45s", w.config.JS)
|
outputJS := fmt.Sprintf("%.45s", w.config.JS)
|
||||||
@@ -272,6 +289,17 @@ func (w *webViewRenderer) SelectSaveFile() string {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddJS adds a piece of Javascript to a cache that
|
||||||
|
// gets injected at runtime
|
||||||
|
func (w *webViewRenderer) AddJSList(jsCache []string) {
|
||||||
|
w.jsCache = jsCache
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddCSSList sets the cssCache to the given list of strings
|
||||||
|
func (w *webViewRenderer) AddCSSList(cssCache []string) {
|
||||||
|
w.cssCache = cssCache
|
||||||
|
}
|
||||||
|
|
||||||
// Callback sends a callback to the frontend
|
// Callback sends a callback to the frontend
|
||||||
func (w *webViewRenderer) Callback(data string) error {
|
func (w *webViewRenderer) Callback(data string) error {
|
||||||
callbackCMD := fmt.Sprintf("window.wails._.callback('%s');", data)
|
callbackCMD := fmt.Sprintf("window.wails._.callback('%s');", data)
|
||||||
|
|||||||
20
runtime.go
20
runtime.go
@@ -2,21 +2,17 @@ package wails
|
|||||||
|
|
||||||
// Runtime is the Wails Runtime Interface, given to a user who has defined the WailsInit method
|
// Runtime is the Wails Runtime Interface, given to a user who has defined the WailsInit method
|
||||||
type Runtime struct {
|
type Runtime struct {
|
||||||
Events *RuntimeEvents
|
Events *RuntimeEvents
|
||||||
Log *RuntimeLog
|
Log *RuntimeLog
|
||||||
Dialog *RuntimeDialog
|
Dialog *RuntimeDialog
|
||||||
Window *RuntimeWindow
|
Window *RuntimeWindow
|
||||||
Browser *RuntimeBrowser
|
|
||||||
FileSystem *RuntimeFileSystem
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRuntime(eventManager *eventManager, renderer Renderer) *Runtime {
|
func newRuntime(eventManager *eventManager, renderer Renderer) *Runtime {
|
||||||
return &Runtime{
|
return &Runtime{
|
||||||
Events: newRuntimeEvents(eventManager),
|
Events: newRuntimeEvents(eventManager),
|
||||||
Log: newRuntimeLog(),
|
Log: newRuntimeLog(),
|
||||||
Dialog: newRuntimeDialog(renderer),
|
Dialog: newRuntimeDialog(renderer),
|
||||||
Window: newRuntimeWindow(renderer),
|
Window: newRuntimeWindow(renderer),
|
||||||
Browser: newRuntimeBrowser(),
|
|
||||||
FileSystem: newRuntimeFileSystem(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
package wails
|
|
||||||
|
|
||||||
import "github.com/pkg/browser"
|
|
||||||
|
|
||||||
// GlobalRuntimeBrowser is the global instance of the RuntimeBrowser object
|
|
||||||
// Why? Because we need to use it in both the runtime and from the frontend
|
|
||||||
var GlobalRuntimeBrowser = newRuntimeBrowser()
|
|
||||||
|
|
||||||
// RuntimeBrowser exposes browser methods to the runtime
|
|
||||||
type RuntimeBrowser struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func newRuntimeBrowser() *RuntimeBrowser {
|
|
||||||
return &RuntimeBrowser{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OpenURL opens the given url in the system's default browser
|
|
||||||
func (r *RuntimeBrowser) OpenURL(url string) error {
|
|
||||||
return browser.OpenURL(url)
|
|
||||||
}
|
|
||||||
|
|
||||||
// OpenFile opens the given file in the system's default browser
|
|
||||||
func (r *RuntimeBrowser) OpenFile(filePath string) error {
|
|
||||||
return browser.OpenFile(filePath)
|
|
||||||
}
|
|
||||||
@@ -18,5 +18,5 @@ func (r *RuntimeEvents) On(eventName string, callback func(optionalData ...inter
|
|||||||
|
|
||||||
// Emit pass through
|
// Emit pass through
|
||||||
func (r *RuntimeEvents) Emit(eventName string, optionalData ...interface{}) {
|
func (r *RuntimeEvents) Emit(eventName string, optionalData ...interface{}) {
|
||||||
r.eventManager.Emit(eventName, optionalData...)
|
r.eventManager.Emit(eventName, optionalData)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
package wails
|
|
||||||
|
|
||||||
import homedir "github.com/mitchellh/go-homedir"
|
|
||||||
|
|
||||||
// RuntimeFileSystem exposes file system utilities to the runtime
|
|
||||||
type RuntimeFileSystem struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func newRuntimeFileSystem() *RuntimeFileSystem {
|
|
||||||
return &RuntimeFileSystem{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// HomeDir returns the user's home directory
|
|
||||||
func (r *RuntimeFileSystem) HomeDir() (string, error) {
|
|
||||||
return homedir.Dir()
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
if [ "$#" != "1" ]; then
|
|
||||||
echo "Tag required"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
TAG=${1}
|
|
||||||
cat << EOF > cmd/version.go
|
|
||||||
package cmd
|
|
||||||
|
|
||||||
// Version - Wails version
|
|
||||||
const Version = "${TAG}"
|
|
||||||
EOF
|
|
||||||
git add cmd/version.go
|
|
||||||
git commit cmd/version.go -m "Bump to ${TAG}"
|
|
||||||
git tag ${TAG}
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -29,7 +29,7 @@ window.wailsbridge = {
|
|||||||
'<div class="wails-reconnect-overlay"><div class="wails-reconnect-overlay-content"><div class="wails-reconnect-overlay-title">Wails Bridge</div><br><div class="wails-reconnect-overlay-loadingspinner"></div><br><div id="wails-reconnect-overlay-message">Waiting for backend</div></div></div>',
|
'<div class="wails-reconnect-overlay"><div class="wails-reconnect-overlay-content"><div class="wails-reconnect-overlay-title">Wails Bridge</div><br><div class="wails-reconnect-overlay-loadingspinner"></div><br><div id="wails-reconnect-overlay-message">Waiting for backend</div></div></div>',
|
||||||
overlayCSS:
|
overlayCSS:
|
||||||
".wails-reconnect-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.6);font-family:sans-serif;display:none;z-index:999999}.wails-reconnect-overlay-content{padding:20px 30px;text-align:center;width:20em;position:relative;height:14em;border-radius:1em;margin:5% auto 0;background-color:#fff;box-shadow:1px 1px 20px 3px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC8AAAAuCAMAAACPpbA7AAAAqFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQAAAAAAAAEBAQAAAAAAAAAAAAEBAQEBAQDAwMBAQEAAAABAQEAAAAAAAAAAAABAQEAAAAAAAACAgICAgIBAQEAAAAAAAAAAAAAAAAAAAAAAAABAQEAAAACAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBQWKCj6oAAAAN3RSTlMALiIqDhkGBAswJjP0GxP6NR4W9/ztjRDMhWU50G9g5eHXvbZ9XEI9xZTcqZl2aldKo55QwoCvZUgzhAAAAs9JREFUSMeNleeWqjAUhU0BCaH3Itiw9zKT93+zG02QK1hm/5HF+jzZJ6fQe6cyXE+jg9X7o9wxuylIIf4Tv2V3+bOrEXnf8dwQ/KQIGDN2/S+4OmVCVXL/ScBnfibxURqIByP/hONE8r8T+bDMlQ98KSl7Y8hzjpS8v1qtDh8u5f8KQpGpfnPPhqG8JeogN37Hq9eaN2xRhIwAaGnvws8F1ShxqK5ob2twYi1FAMD4rXsYtnC/JEiRbl4cUrCWhnMCLRFemXezXbb59QK4WASOsm6n2W1+4CBT2JmtzQ6fsrbGubR/NFbd2g5Y179+5w/GEHaKsHjYCet7CgrXU3txarNC7YxOVJtIj4/ERzMdZfzc31hp+8cD6eGILgarZY9uZ12hAs03vfBD9C171gS5Omz7OcvxALQIn4u8RRBBBcsi9WW2woO9ipLgfzpYlggg3ZRdROUC8KT7QLqq3W9KB5BbdFVg4929kdwp6+qaZnMCCNBdj+NyN1W885Ry/AL3D4AQbsVV4noCiM/C83kyYq80XlDAYQtralOiDzoRAHlotWl8q2tjvYlOgcg1A8jEApZa+C06TBdAz2Qv0wu11I/zZOyJQ6EwGez2P2b8PIQr1hwwnAZsAxwA4UAYOyXUxM/xp6tHAn4GUmPGM9R28oVxgC0e/zQJJI6DyhyZ1r7uzRQhpcW7x7vTaWSzKSG6aep77kroTEl3U81uSVaUTtgEINfC8epx+Q4F9SpplHG84Ek6m4RAq9/TLkOBrxyeuddZhHvGIp1XXfFy3Z3vtwNblKGiDn+J+92vwwABHghj7HnzlS1H5kB49AZvdGCFgiBPq69qfXPr3y++yilF0ON4R8eR7spAsLpZ95NqAW5tab1c4vkZm6aleajchMwYTdILQQTwE2OV411ZM9WztDjPql12caBi6gDpUKmDd4U1XNdQxZ4LIXQ5/Tr4P7I9tYcFrDK3AAAAAElFTkSuQmCC);background-repeat:no-repeat;background-position:center}.wails-reconnect-overlay-title{font-size:2em}.wails-reconnect-overlay-message{font-size:1.3em}.wails-reconnect-overlay-loadingspinner{pointer-events:none;width:2.5em;height:2.5em;border:.4em solid transparent;border-color:#3E67EC #eee #eee;border-radius:50%;animation:loadingspin 1s linear infinite;margin:auto;padding:2.5em}@keyframes loadingspin{100%{transform:rotate(360deg)}}",
|
".wails-reconnect-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.6);font-family:sans-serif;display:none;z-index:999999}.wails-reconnect-overlay-content{padding:20px 30px;text-align:center;width:20em;position:relative;height:14em;border-radius:1em;margin:5% auto 0;background-color:#fff;box-shadow:1px 1px 20px 3px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC8AAAAuCAMAAACPpbA7AAAAqFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQAAAAAAAAEBAQAAAAAAAAAAAAEBAQEBAQDAwMBAQEAAAABAQEAAAAAAAAAAAABAQEAAAAAAAACAgICAgIBAQEAAAAAAAAAAAAAAAAAAAAAAAABAQEAAAACAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBQWKCj6oAAAAN3RSTlMALiIqDhkGBAswJjP0GxP6NR4W9/ztjRDMhWU50G9g5eHXvbZ9XEI9xZTcqZl2aldKo55QwoCvZUgzhAAAAs9JREFUSMeNleeWqjAUhU0BCaH3Itiw9zKT93+zG02QK1hm/5HF+jzZJ6fQe6cyXE+jg9X7o9wxuylIIf4Tv2V3+bOrEXnf8dwQ/KQIGDN2/S+4OmVCVXL/ScBnfibxURqIByP/hONE8r8T+bDMlQ98KSl7Y8hzjpS8v1qtDh8u5f8KQpGpfnPPhqG8JeogN37Hq9eaN2xRhIwAaGnvws8F1ShxqK5ob2twYi1FAMD4rXsYtnC/JEiRbl4cUrCWhnMCLRFemXezXbb59QK4WASOsm6n2W1+4CBT2JmtzQ6fsrbGubR/NFbd2g5Y179+5w/GEHaKsHjYCet7CgrXU3txarNC7YxOVJtIj4/ERzMdZfzc31hp+8cD6eGILgarZY9uZ12hAs03vfBD9C171gS5Omz7OcvxALQIn4u8RRBBBcsi9WW2woO9ipLgfzpYlggg3ZRdROUC8KT7QLqq3W9KB5BbdFVg4929kdwp6+qaZnMCCNBdj+NyN1W885Ry/AL3D4AQbsVV4noCiM/C83kyYq80XlDAYQtralOiDzoRAHlotWl8q2tjvYlOgcg1A8jEApZa+C06TBdAz2Qv0wu11I/zZOyJQ6EwGez2P2b8PIQr1hwwnAZsAxwA4UAYOyXUxM/xp6tHAn4GUmPGM9R28oVxgC0e/zQJJI6DyhyZ1r7uzRQhpcW7x7vTaWSzKSG6aep77kroTEl3U81uSVaUTtgEINfC8epx+Q4F9SpplHG84Ek6m4RAq9/TLkOBrxyeuddZhHvGIp1XXfFy3Z3vtwNblKGiDn+J+92vwwABHghj7HnzlS1H5kB49AZvdGCFgiBPq69qfXPr3y++yilF0ON4R8eR7spAsLpZ95NqAW5tab1c4vkZm6aleajchMwYTdILQQTwE2OV411ZM9WztDjPql12caBi6gDpUKmDd4U1XNdQxZ4LIXQ5/Tr4P7I9tYcFrDK3AAAAAElFTkSuQmCC);background-repeat:no-repeat;background-position:center}.wails-reconnect-overlay-title{font-size:2em}.wails-reconnect-overlay-message{font-size:1.3em}.wails-reconnect-overlay-loadingspinner{pointer-events:none;width:2.5em;height:2.5em;border:.4em solid transparent;border-color:#3E67EC #eee #eee;border-radius:50%;animation:loadingspin 1s linear infinite;margin:auto;padding:2.5em}@keyframes loadingspin{100%{transform:rotate(360deg)}}",
|
||||||
log: function (message) {
|
log: function(message) {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
console.log(
|
console.log(
|
||||||
"%c wails bridge %c " + message + " ",
|
"%c wails bridge %c " + message + " ",
|
||||||
@@ -102,7 +102,7 @@ function startBridge() {
|
|||||||
|
|
||||||
// Bridge external.invoke
|
// Bridge external.invoke
|
||||||
window.external = {
|
window.external = {
|
||||||
invoke: function (msg) {
|
invoke: function(msg) {
|
||||||
window.wailsbridge.websocket.send(msg);
|
window.wailsbridge.websocket.send(msg);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -111,7 +111,6 @@ function startBridge() {
|
|||||||
// Removes it if second parameter is true.
|
// Removes it if second parameter is true.
|
||||||
function addScript(script, remove) {
|
function addScript(script, remove) {
|
||||||
var s = document.createElement("script");
|
var s = document.createElement("script");
|
||||||
s.setAttribute('type', 'text/javascript');
|
|
||||||
s.textContent = script;
|
s.textContent = script;
|
||||||
document.head.appendChild(s);
|
document.head.appendChild(s);
|
||||||
|
|
||||||
@@ -143,11 +142,11 @@ function startBridge() {
|
|||||||
// Try to connect to the backend every 300ms (default value).
|
// Try to connect to the backend every 300ms (default value).
|
||||||
// Change this value in the main wailsbridge object.
|
// Change this value in the main wailsbridge object.
|
||||||
function connect() {
|
function connect() {
|
||||||
window.wailsbridge.connectTimer = setInterval(function () {
|
window.wailsbridge.connectTimer = setInterval(function() {
|
||||||
if (window.wailsbridge.websocket == null) {
|
if (window.wailsbridge.websocket == null) {
|
||||||
window.wailsbridge.websocket = new WebSocket(window.wailsbridge.wsURL);
|
window.wailsbridge.websocket = new WebSocket(window.wailsbridge.wsURL);
|
||||||
window.wailsbridge.websocket.onopen = handleConnect;
|
window.wailsbridge.websocket.onopen = handleConnect;
|
||||||
window.wailsbridge.websocket.onerror = function (e) {
|
window.wailsbridge.websocket.onerror = function(e) {
|
||||||
e.stopImmediatePropagation();
|
e.stopImmediatePropagation();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -160,6 +159,7 @@ function startBridge() {
|
|||||||
|
|
||||||
function handleMessage(message) {
|
function handleMessage(message) {
|
||||||
// As a bridge we ignore js and css injections
|
// As a bridge we ignore js and css injections
|
||||||
|
|
||||||
switch (message.data[0]) {
|
switch (message.data[0]) {
|
||||||
// Wails library - inject!
|
// Wails library - inject!
|
||||||
case "w":
|
case "w":
|
||||||
@@ -167,7 +167,7 @@ function startBridge() {
|
|||||||
|
|
||||||
// Now wails runtime is loaded, wails for the ready event
|
// Now wails runtime is loaded, wails for the ready event
|
||||||
// and callback to the main app
|
// and callback to the main app
|
||||||
window.wails.events.on("wails:loaded", function () {
|
window.wails.events.on("wails:loaded", function() {
|
||||||
window.wailsbridge.log("Wails Ready");
|
window.wailsbridge.log("Wails Ready");
|
||||||
if (window.wailsbridge.callback) {
|
if (window.wailsbridge.callback) {
|
||||||
window.wailsbridge.log("Notifying application");
|
window.wailsbridge.log("Notifying application");
|
||||||
@@ -189,6 +189,7 @@ function startBridge() {
|
|||||||
// Call back
|
// Call back
|
||||||
case "c":
|
case "c":
|
||||||
var callbackData = message.data.slice(1);
|
var callbackData = message.data.slice(1);
|
||||||
|
window.wailsbridge.log("Callback = " + callbackData);
|
||||||
window.wails._.callback(callbackData);
|
window.wails._.callback(callbackData);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -204,7 +205,7 @@ function startBridge() {
|
|||||||
export default {
|
export default {
|
||||||
// The main function
|
// The main function
|
||||||
// Passes the main Wails object to the callback if given.
|
// Passes the main Wails object to the callback if given.
|
||||||
Start: function (callback) {
|
Start: function(callback) {
|
||||||
// Save the callback
|
// Save the callback
|
||||||
window.wailsbridge.callback = callback;
|
window.wailsbridge.callback = callback;
|
||||||
|
|
||||||
|
|||||||
2
wailsruntimeassets/default/wails.min.js
vendored
2
wailsruntimeassets/default/wails.min.js
vendored
@@ -1 +1 @@
|
|||||||
!function(){var e;function n(e){try{return new Function("var "+e),!0}catch(e){return!1}}window.wails=window.wails||{},window.backend={},e=window.crypto?function(){var e=new Uint32Array(1);return window.crypto.getRandomValues(e)[0]}:function(){return 9007199254740991*Math.random()};var a=window.backend;var t={};function r(n,a,r){return null!=r&&null!=r||(r=0),new Promise(function(i,o){var l;do{l=n+"-"+e()}while(t[l]);if(r>0)var c=setTimeout(function(){o(Error("Call to "+n+" timed out. Request ID: "+l))},r);t[l]={timeoutHandle:c,reject:o,resolve:i};try{var s=JSON.stringify(a);message={type:"call",callbackid:l,payload:{bindingName:n,data:s}};var u=JSON.stringify(message);external.invoke(u)}catch(e){console.error(e)}})}function i(e,n){return r(".wails."+e,n)}var o={};function l(e,n){n={type:"log",payload:{level:e,message:n}},external.invoke(JSON.stringify(n))}window.wails.events={emit:function(e){var n=JSON.stringify([].slice.apply(arguments).slice(1));message={type:"event",payload:{name:e,data:n}},external.invoke(JSON.stringify(message))},on:function(e,n){o[e]=o[e]||[],o[e].push(n)}},window.wails.Browser={OpenURL:function(e){return i("Browser.OpenURL",e)},OpenFile:function(e){return i("Browser.OpenFile",e)}},window.wails.log={debug:function(e){l("debug",e)},info:function(e){l("info",e)},warning:function(e){l("warning",e)},error:function(e){l("error",e)},fatal:function(e){l("fatal",e)}},window.wails._={newBinding:function(e){var t,i=e.split(".").splice(1),o=i.pop(),l=function(e){var t=a;for(var r in e){var i=e[r];if(!n(i))return[null,new Error(i+" is not a valid javascript identifier.")];t[i]||(t[i]={}),t=t[i]}return[t,null]}(i),c=l[0];if(null!=(t=l[1]))return t;c[o]=function(){var n=0;function a(){var a=[].slice.call(arguments);return r(e,a,n)}return a.setTimeout=function(e){n=e},a.getTimeout=function(){return n},a}()},callback:function(e){var n;e=decodeURIComponent(e.replace(/\s+/g,"").replace(/[0-9a-f]{2}/g,"%$&"));try{n=JSON.parse(e)}catch(n){return wails.log.debug("Invalid JSON passed to callback: "+n.message),void wails.log.debug("Message: "+e)}if(callbackID=n.callbackid,callbackData=t[callbackID],callbackData)return clearTimeout(callbackData.timeoutHandle),delete t[callbackID],n.error?callbackData.reject(n.error):callbackData.resolve(n.data);console.error("Callback '"+callbackID+"' not registed!!!")},notify:function(e,n){o[e]&&o[e].forEach(function(a){var t=[];if(n)try{t=JSON.parse(n)}catch(n){wails.log.error("Invalid JSON data sent to notify. Event name = "+e)}a.apply(null,t)})},sendLogMessage:l,callbacks:t,injectCSS:function(e){var n=document.createElement("style");n.setAttribute("type","text/css"),n.styleSheet?n.styleSheet.cssText=e:n.appendChild(document.createTextNode(e)),(document.head||document.getElementsByTagName("head")[0]).appendChild(n)},addScript:function(e,n){var a=document.createElement("script");a.text=e,document.body.appendChild(a),window.wails.events.emit(n)}},window.wails.events.emit("wails:loaded")}();
|
(function(){window.wails=window.wails||{};window.backend={};function cryptoRandom(){var array=new Uint32Array(1);return window.crypto.getRandomValues(array)[0]}function basicRandom(){return Math.random()*9007199254740991}var randomFunc;if(window.crypto){randomFunc=cryptoRandom}else{randomFunc=basicRandom}function isValidIdentifier(name){try{new Function("var "+name);return true}catch(e){return false}}function addScript(js,callbackID){var script=document.createElement("script");script.text=js;document.body.appendChild(script);window.wails.events.emit(callbackID)}function injectCSS(css){var elem=document.createElement('style');elem.setAttribute('type','text/css');if(elem.styleSheet){elem.styleSheet.cssText=css}else{elem.appendChild(document.createTextNode(css))}var head=document.head||document.getElementsByTagName('head')[0];head.appendChild(elem)}var bindingsBasePath=window.backend;function addBindingPath(pathSections){var currentPath=bindingsBasePath;for(var sectionIndex in pathSections){var section=pathSections[sectionIndex];if(!isValidIdentifier(section)){var errMessage=section+" is not a valid javascript identifier.";var err=new Error(errMessage);return[null,err]}if(!currentPath[section]){currentPath[section]={}}currentPath=currentPath[section]}return[currentPath,null]}function newBinding(bindingName){var bindingSections=bindingName.split('.').splice(1);var callName=bindingSections.pop();var pathToBinding;var err;var bs=addBindingPath(bindingSections);var pathToBinding=bs[0];var err=bs[1];if(err!=null){return err}pathToBinding[callName]=function(){var timeout=0;function dynamic(){var args=[].slice.call(arguments);return call(bindingName,args,timeout)}dynamic.setTimeout=function(newTimeout){timeout=newTimeout};dynamic.getTimeout=function(){return timeout};return dynamic}()}var callbacks={};function call(bindingName,data,timeout){if(timeout==null||timeout==undefined){timeout=0}return new Promise(function(resolve,reject){var callbackID;do{callbackID=bindingName+"-"+randomFunc()}while(callbacks[callbackID]);if(timeout>0){var timeoutHandle=setTimeout(function(){reject(Error("Call to "+bindingName+" timed out. Request ID: "+callbackID))},timeout)}callbacks[callbackID]={timeoutHandle:timeoutHandle,reject:reject,resolve:resolve};try{var payloaddata=JSON.stringify(data);message={type:"call",callbackid:callbackID,payload:{bindingName:bindingName,data:payloaddata}};var payload=JSON.stringify(message);external.invoke(payload)}catch(e){console.error(e)}})}function callback(incomingMessage){var message;try{message=JSON.parse(incomingMessage)}catch(e){wails.log.debug("Invalid JSON passed to callback: "+e.message);wails.log.debug("Message: "+incomingMessage);return}callbackID=message.callbackid;callbackData=callbacks[callbackID];if(!callbackData){console.error("Callback '"+callbackID+"' not registed!!!");return}clearTimeout(callbackData.timeoutHandle);delete callbacks[callbackID];if(message.error){return callbackData.reject(message.error)}return callbackData.resolve(message.data)}var eventListeners={};function on(eventName,callback){eventListeners[eventName]=eventListeners[eventName]||[];eventListeners[eventName].push(callback)}function notify(eventName,data){if(eventListeners[eventName]){eventListeners[eventName].forEach(function(element){var parsedData=[];if(data){try{parsedData=JSON.parse(data)}catch(e){wails.log.error("Invalid JSON data sent to notify. Event name = "+eventName)}}element.apply(null,parsedData)})}}function emit(eventName){var data=JSON.stringify([].slice.apply(arguments).slice(1));message={type:"event",payload:{name:eventName,data:data}};external.invoke(JSON.stringify(message))}window.wails.events={emit:emit,on:on};function sendLogMessage(level,message){message={type:"log",payload:{level:level,message:message}};external.invoke(JSON.stringify(message))}function logDebug(message){sendLogMessage("debug",message)}function logInfo(message){sendLogMessage("info",message)}function logWarning(message){sendLogMessage("warning",message)}function logError(message){sendLogMessage("error",message)}function logFatal(message){sendLogMessage("fatal",message)}window.wails.log={debug:logDebug,info:logInfo,warning:logWarning,error:logError,fatal:logFatal};window.wails._={newBinding:newBinding,callback:callback,notify:notify,sendLogMessage:sendLogMessage,callbacks:callbacks,injectCSS:injectCSS,addScript:addScript};window.wails.events.emit("wails:loaded");})();
|
||||||
@@ -10,8 +10,8 @@
|
|||||||
function cryptoRandom() {
|
function cryptoRandom() {
|
||||||
var array = new Uint32Array(1);
|
var array = new Uint32Array(1);
|
||||||
return window.crypto.getRandomValues(array)[0];
|
return window.crypto.getRandomValues(array)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// LOLRandom
|
// LOLRandom
|
||||||
function basicRandom() {
|
function basicRandom() {
|
||||||
@@ -200,18 +200,9 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// systemCall is used to call wails methods from the frontend
|
|
||||||
function systemCall(method, data) {
|
|
||||||
return call(".wails." + method, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called by the backend to return data to a previously called
|
// Called by the backend to return data to a previously called
|
||||||
// binding invocation
|
// binding invocation
|
||||||
function callback(incomingMessage) {
|
function callback(incomingMessage) {
|
||||||
|
|
||||||
// Decode the message - Credit: https://stackoverflow.com/a/13865680
|
|
||||||
incomingMessage = decodeURIComponent(incomingMessage.replace(/\s+/g, '').replace(/[0-9a-f]{2}/g, '%$&'));
|
|
||||||
|
|
||||||
// Parse the message
|
// Parse the message
|
||||||
var message;
|
var message;
|
||||||
try {
|
try {
|
||||||
@@ -252,7 +243,7 @@
|
|||||||
// notify informs frontend listeners that an event was emitted with the given data
|
// notify informs frontend listeners that an event was emitted with the given data
|
||||||
function notify(eventName, data) {
|
function notify(eventName, data) {
|
||||||
if (eventListeners[eventName]) {
|
if (eventListeners[eventName]) {
|
||||||
eventListeners[eventName].forEach(function (element) {
|
eventListeners[eventName].forEach(function(element) {
|
||||||
var parsedData = [];
|
var parsedData = [];
|
||||||
// Parse data if we have it
|
// Parse data if we have it
|
||||||
if (data) {
|
if (data) {
|
||||||
@@ -290,22 +281,6 @@
|
|||||||
|
|
||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
|
||||||
/************************* Browser **************************/
|
|
||||||
|
|
||||||
|
|
||||||
function OpenURL(url) {
|
|
||||||
return systemCall("Browser.OpenURL", url);
|
|
||||||
}
|
|
||||||
|
|
||||||
function OpenFile(filename) {
|
|
||||||
return systemCall("Browser.OpenFile", filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
window.wails.Browser = {
|
|
||||||
OpenURL,
|
|
||||||
OpenFile,
|
|
||||||
};
|
|
||||||
|
|
||||||
/************************* Logging **************************/
|
/************************* Logging **************************/
|
||||||
|
|
||||||
// Sends a log message to the backend with the given
|
// Sends a log message to the backend with the given
|
||||||
@@ -357,8 +332,8 @@
|
|||||||
callbacks: callbacks,
|
callbacks: callbacks,
|
||||||
injectCSS: injectCSS,
|
injectCSS: injectCSS,
|
||||||
addScript: addScript,
|
addScript: addScript,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user