Compare commits

...

119 Commits

Author SHA1 Message Date
Lea Anthony
8432f725a9 chore: updated go mod files 2019-05-20 18:45:01 +10:00
Lea Anthony
7015b80888 feat: new template generator 2019-05-20 18:44:14 +10:00
Lea Anthony
1ac16d1933 fix: minor fixes 2019-05-18 07:34:39 +10:00
Lea Anthony
0f36a88f0e feat: add Manjaro support 2019-05-18 07:18:34 +10:00
Lea Anthony
b30031d025 feat: multiple template support 2019-05-18 07:15:15 +10:00
Lea Anthony
cd152f0cd7 Merge branch 'master' into v0.14.0-pre 2019-05-12 15:15:11 +10:00
Lea Anthony
12280b51b9 chore: version bump 2019-05-12 15:12:10 +10:00
Lea Anthony
29256c5766 fix: update check 2019-05-12 15:11:40 +10:00
Lea Anthony
8b13c0b197 chore: update version 2019-05-12 15:02:50 +10:00
Lea Anthony
50e2037fba fix: same version comparison 2019-05-12 14:55:39 +10:00
Lea Anthony
f86c10af02 fix: update logic 2019-05-12 14:48:25 +10:00
Lea Anthony
00e165b139 Merge branch 'v0.13.0-pre' into v0.13.0 2019-05-12 14:20:40 +10:00
Lea Anthony
02199bbe9d fix: updating from pre to release 2019-05-12 14:20:04 +10:00
Lea Anthony
d591a55140 docs: added changelog 2019-05-12 13:53:09 +10:00
Lea Anthony
508295b558 docs: updated contributors 2019-05-12 13:52:30 +10:00
Lea Anthony
bdc33e1430 docs: update contributors 2019-05-12 13:37:31 +10:00
Lea Anthony
d55dcb2dfb chore: update version 2019-05-12 13:37:19 +10:00
Lea Anthony
79ac4c1d45 Merge pull request #86 from fishfishfish2104/v0.13.0-pre
Added Dependancy check for redhat distros
2019-05-12 13:31:45 +10:00
Lea Anthony
c6bfa85a1a Merge branch 'v0.13.0-pre' of github.com:wailsapp/wails into v0.13.0-pre 2019-05-12 13:00:55 +10:00
Lea Anthony
82289714ba chore: update go mod files 2019-05-12 13:00:34 +10:00
Lea Anthony
77142bd99e feat: support version flag 2019-05-12 12:59:35 +10:00
Lea Anthony
538f5c6501 fix: typo fixes 2019-05-12 12:51:14 +10:00
Lea Anthony
3ff02fb183 fix: better version checking 2019-05-12 12:50:50 +10:00
Lea Anthony
30298b4237 feat: add IsValidTag 2019-05-12 12:50:28 +10:00
fred2104
9f2c9a989f Added instructions for red hat distros 2019-05-12 09:06:23 +12:00
Lea Anthony
146147bed8 Merge branch 'pr/82' into v0.13.0-pre 2019-05-11 17:08:40 +10:00
Lea Anthony
76499b20c4 fix: windows template.json 2019-05-11 17:04:42 +10:00
Bryn Sinclair
b21e79daf5 changed to use rpm instead of yum as its faster 2019-05-11 12:19:18 +12:00
Lea Anthony
71194108de feat: better version comparison 2019-05-10 23:01:50 +10:00
Lea Anthony
11fd50f78d fix: ensure GO111MODULE=on 2019-05-10 21:23:58 +10:00
Lea Anthony
c08d1d7b3c fix: remove test data 2019-05-10 21:18:35 +10:00
Lea Anthony
2febf5a97a fix: set gomod=on when execing 2019-05-10 21:12:20 +10:00
Lea Anthony
cea7b1e494 feat: new Github helper 2019-05-10 21:11:43 +10:00
Lea Anthony
25962e2e53 fix: set correct version 2019-05-10 21:11:20 +10:00
Bryn Sinclair
43f9b141fe removed unnecessary dependancies
changed logger.red to logger.error
2019-05-10 21:06:58 +12:00
Bryn Sinclair
e1b729ea96 Merge commit 'f9a18817b74828ff8fae92a1a873087f9adc363b' of https://github.com/wailsapp/wails into v0.13.0-pre 2019-05-10 21:04:53 +12:00
Bryn Sinclair
f9a18817b7 Added library checking support for red hat distros (Only tested on fedora)
Changed some Package help inconsistencies
2019-05-10 17:41:30 +12:00
Yasuhiro Matsumoto
23cb97d314 Fix windows paths 2019-05-10 09:31:10 +09:00
Lea Anthony
32e085b609 docs: remove -u 2019-05-09 22:07:56 +10:00
Lea Anthony
389dee8db9 docs: add MDH 2019-05-09 22:06:53 +10:00
Lea Anthony
dba6fdf7e4 docs: add awesomego 2019-05-09 22:06:41 +10:00
Lea Anthony
cc45dcf91e fix: leave win assets on -p flag 2019-05-09 22:06:27 +10:00
Lea Anthony
4aeb554f1b fix: remove debug output 2019-05-09 19:43:19 +10:00
Lea Anthony
3d2268420b fix: show prerequisite errors 2019-05-09 19:31:07 +10:00
Lea Anthony
ca388be121 chore: update go.mod 2019-05-09 17:53:37 +10:00
Lea Anthony
f9ca13ff30 fix: remove -u from go get 2019-05-09 13:58:49 +10:00
Lea Anthony
319dbcdc49 chore: lint fix 2019-05-08 22:42:13 +10:00
Lea Anthony
bffbbd59ce fix: Windows 10 colour 2019-05-08 22:40:56 +10:00
Lea Anthony
8bd1d0ec92 fix: no need for windows separator 2019-05-08 22:32:04 +10:00
Lea Anthony
0daec29fab Updates to update command 2019-05-07 08:48:52 +10:00
Lea Anthony
bb3dbe0510 update to mewn 0.10.5 2019-05-07 08:25:35 +10:00
Lea Anthony
2fa9e3b0ee Bump to v0.12.0 2019-05-03 19:21:39 +10:00
Lea Anthony
40d1750345 Updated contributors 2019-05-03 19:20:09 +10:00
Lea Anthony
d2d4ea3033 Add Arch instructions 2019-05-03 19:09:36 +10:00
Lea Anthony
ff55170002 chore: improve updateversion.sh 2019-05-02 20:15:50 +10:00
Lea Anthony
444db6a560 docs: add contributors 2019-05-02 20:15:31 +10:00
Adrian Lanzafame
b015f27e14 add archlinux support 2019-05-02 13:35:34 +10:00
Lea Anthony
67a1f23b13 Merge pull request #72 from qaisjp/patch-1
Fix HTML spellings
2019-05-01 20:53:28 +10:00
Qais Patankar
9c98a7a9e3 Fix HTML spelling in README.md 2019-05-01 03:06:56 +01:00
Qais Patankar
5aa5ad8ad3 Fix HTML spelling in app_config.go 2019-05-01 03:06:19 +01:00
Lea Anthony
ac203ec931 version bump 2019-04-30 08:30:46 +10:00
Lea Anthony
3fd73186f4 Version bump 2019-04-30 08:22:18 +10:00
Lea Anthony
46307469e5 Updated Readme 2019-04-29 23:23:29 +10:00
Lea Anthony
31a67f3aed Add Hound badge 2019-04-29 18:43:27 +10:00
Lea Anthony
44919d2750 dialog errors -> warnings 2019-04-27 10:16:12 +10:00
Lea Anthony
cff87c641b update bridge warning messages 2019-04-27 10:14:08 +10:00
Lea Anthony
abbd71d057 Merge pull request #71 from wailsapp/replace-wailsbridge-when-serving
always install bridge on serve
2019-04-27 09:30:33 +10:00
Lea Anthony
aacfe8386a always install bridge on serve 2019-04-27 09:29:19 +10:00
Lea Anthony
97944d771a Bump to 0.11.6 2019-04-26 18:58:56 +10:00
Lea Anthony
3f1b616a5e Merge pull request #70 from wailsapp/update-webview
Update webview to 0.2.7
2019-04-26 18:56:38 +10:00
Lea Anthony
fdcc2fd2e5 Update webview to 0.2.7 2019-04-26 18:54:06 +10:00
Lea Anthony
855032ed1e release 0.11.3 2019-04-25 20:14:10 +10:00
Lea Anthony
760e109aab create windows builds 2019-04-25 20:12:56 +10:00
Lea Anthony
4c799bca8f version bump 2019-04-25 20:08:42 +10:00
Lea Anthony
2d08ebc054 vscode settings 2019-04-25 20:08:07 +10:00
Lea Anthony
91ab2c2b31 Version bump 2019-04-25 20:06:11 +10:00
Lea Anthony
13ad57d49f fix: ensure errors are logged 2019-04-25 20:05:39 +10:00
Lea Anthony
a109e3078d New dependency installation text 2019-04-23 08:46:39 +10:00
Lea Anthony
2e61a3c309 Set script type for injections 2019-04-23 08:46:11 +10:00
Lea Anthony
0373bea4e5 fix: destructure emit data 2019-04-23 08:44:47 +10:00
Lea Anthony
2d5825d73d Speed up Wails Serve 2019-04-20 12:15:19 +10:00
Lea Anthony
c4a042cb1d Added Runtime.FileSystem 2019-04-20 12:13:55 +10:00
Lea Anthony
205f9476fa Change 'Headless' to 'Bridge' in logging 2019-04-20 12:12:30 +10:00
Lea Anthony
a1230fcbb6 Badges! 2019-04-11 08:43:50 +10:00
Lea Anthony
ba5c32a4a1 more linting fixes 2019-04-11 08:38:14 +10:00
Lea Anthony
58eee64326 more linting fixes 2019-04-11 08:26:57 +10:00
Lea Anthony
41d786a13c Add devtools to Vue config in template 2019-04-10 08:48:12 +10:00
Lea Anthony
a2b7906c89 more linting fixes 2019-04-10 08:46:49 +10:00
Lea Anthony
eeb6fa4677 linting fixes 2019-04-10 08:38:46 +10:00
Lea Anthony
6a36d75774 Use cropped logo 2019-04-08 19:33:44 +10:00
Lea Anthony
6078f3c780 Center subtitle 2019-04-08 19:29:17 +10:00
Lea Anthony
fc11197725 Fix image 2019-04-08 19:24:20 +10:00
Lea Anthony
8c40b99194 Update license and readme 2019-04-08 19:18:39 +10:00
Lea Anthony
de53fc6510 chore: remove unused files 2019-03-29 08:25:18 +11:00
Lea Anthony
d4f4feb429 fix: better input during setup 2019-03-29 08:25:09 +11:00
Lea Anthony
02973c49ff fix: version output of built app 2019-03-29 08:24:46 +11:00
Lea Anthony
01dce9f139 Merge pull request #68 from wailsapp/fix-packaging
fix: call package when -p flag provided
2019-03-20 08:12:48 +11:00
Lea Anthony
6c0906e87d fix: call package when -p flag provided 2019-03-20 08:11:46 +11:00
Lea Anthony
d7cfc4c71a Merge pull request #67 from wailsapp/fix-concurrent-websocket-writes
fix: use mutex to serialise websocket writes
2019-03-19 08:35:49 +11:00
Lea Anthony
fec3e7eac5 fix: use mutex to serialise websocket writes 2019-03-19 08:35:09 +11:00
Lea Anthony
9f5e2c7dd4 Merge pull request #66 from wailsapp/handle-javascript-nulls
fix: convert js nulls to Go zero values
2019-03-19 08:21:31 +11:00
Lea Anthony
c5276cca6c fix: convert js nulls to Go zero values 2019-03-19 08:20:45 +11:00
Lea Anthony
74dbbbed8a Merge pull request #65 from wailsapp/improved-ipc-encoding
Use hex encoded strings for callbacks
2019-03-17 16:57:50 +11:00
Lea Anthony
629ac4b93c Use hex encoded strings for callbacks 2019-03-17 16:56:41 +11:00
Lea Anthony
5ece7e84b3 Release 0.11.0 2019-03-10 17:03:55 +11:00
Lea Anthony
eaba857676 Add frontend build back to serve 2019-03-10 17:02:57 +11:00
Lea Anthony
db489a3cae Remove banner from application cli 2019-03-10 17:02:36 +11:00
Lea Anthony
4821ab8597 Automate version bumps 2019-03-10 17:02:12 +11:00
Lea Anthony
670b769f82 version bump 2019-03-09 05:18:23 +11:00
Lea Anthony
eb53399824 add wails bridge assets 2019-03-08 20:39:09 +11:00
Lea Anthony
24e4fbfb68 ignore frontend files when using wails serve 2019-03-08 20:38:55 +11:00
Lea Anthony
7f54ca4ac3 version bump 2019-03-07 21:30:30 +11:00
Lea Anthony
b224803e4d fix vue basic template 2019-03-07 21:29:55 +11:00
Lea Anthony
28b2025aaa Merge pull request #63 from wailsapp/0.9.9
0.9.9
2019-03-07 08:25:23 +11:00
Lea Anthony
77e85705d1 Version bump 2019-03-07 08:23:38 +11:00
Lea Anthony
9fd24595c7 fix asset imports in vue basic template 2019-03-07 08:23:29 +11:00
Lea Anthony
69067e85f5 Merge pull request #62 from wailsapp/Default-Prompts-not-populating
Default prompts not populating
2019-03-07 05:48:15 +11:00
Lea Anthony
c8db58e00e Version bump 2019-03-07 05:47:13 +11:00
Lea Anthony
e96e0e0999 fix default prompts 2019-03-07 05:46:20 +11:00
60 changed files with 1441 additions and 598 deletions

42
.chglog/CHANGELOG.tpl.md Executable file
View File

@@ -0,0 +1,42 @@
{{ 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 -}}

27
.chglog/config.yml Executable file
View File

@@ -0,0 +1,27 @@
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

3
.gitignore vendored
View File

@@ -15,4 +15,5 @@ examples/**/example*
!examples/**/*.*
cmd/wails/wails
.DS_Store
tmp
tmp
dist

34
.goreleaser.yml Normal file
View File

@@ -0,0 +1,34 @@
# 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
View File

@@ -5,14 +5,36 @@
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"name": "Wails Init",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/cmd/wails/main.go",
"env": {},
"cwd": "/tmp",
"args": [
"setup"
"init",
"-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 Normal file
View File

@@ -0,0 +1,3 @@
{
"go.formatTool": "goimports"
}

19
CHANGELOG.md Normal file
View File

@@ -0,0 +1,19 @@
<a name="v0.13.0"></a>
## [v0.13.0] - 2019-05-12
### Feat
- revamped 'update' system
- no need for explicit GO111MODULE=on
### Fix
- documentation typo fixes
- windows init project
- windows 10 colour
- leave windows assets on -p flag
- show prerequisite errors
### Docs
- updated contributors
- added awesomego logo
- added Redhat distro

12
CONTRIBUTORS.md Normal file
View File

@@ -0,0 +1,12 @@
# 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)

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2018 wailsapp
Copyright (c) 2018-Present Lea Anthony
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

121
README.md
View File

@@ -1 +1,120 @@
# Coming Soon
<p align="center" style="text-align: center">
<img src="https://github.com/wailsapp/docs/raw/master/.vuepress/public/media/logo_cropped.png" width="40%"><br/>
</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/sindresorhus/awesome" rel="nofollow"><img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome"></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
- 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.11 or above
- 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
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.
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)

10
app.go
View File

@@ -70,7 +70,11 @@ func (a *App) Run() error {
}
a.logLevel = "error"
return a.start()
err := a.start()
if err != nil {
a.log.Error(err.Error())
}
return err
}
func (a *App) start() error {
@@ -114,9 +118,7 @@ func (a *App) start() error {
a.renderer.AddJSList(a.jsCache)
// Run the renderer
a.renderer.Run()
return nil
return a.renderer.Run()
}
// Bind allows the user to bind the given object

View File

@@ -1,8 +1,6 @@
package wails
import (
"fmt"
"github.com/wailsapp/wails/cmd"
)
@@ -11,6 +9,7 @@ func (app *App) setupCli() *cmd.Cli {
// Create a new cli
result := cmd.NewCli(app.config.Title, "Debug build")
result.Version(cmd.Version)
// Setup cli to handle loglevel and headless flags
result.
@@ -21,8 +20,6 @@ func (app *App) setupCli() *cmd.Cli {
// Banner
result.PreRun(func(cli *cmd.Cli) error {
log := cmd.NewLogger()
log.PrintSmallBanner()
fmt.Println()
log.YellowUnderline(app.config.Title + " - Debug Build")
return nil
})

View File

@@ -41,7 +41,7 @@ func (a *AppConfig) merge(in *AppConfig) error {
a.HTML = strings.TrimSpace(inlineHTML)
// Deduce whether this is a full html page or a fragment
// The document is determined to be a fragment if an HMTL
// The document is determined to be a fragment if an HTML
// tag exists and is located before the first div tag
HTMLTagIndex := strings.Index(a.HTML, "<html")
DivTagIndex := strings.Index(a.HTML, "<div")

View File

@@ -153,8 +153,11 @@ func (b *boundFunction) setInputValue(index int, typ reflect.Type, val interface
}
}()
// Do the conversion
result = reflect.ValueOf(val).Convert(typ)
// Translate javascript null values
if val == nil {
result = reflect.Zero(typ)
} else {
result = reflect.ValueOf(val).Convert(typ)
}
return result, err
}

View File

@@ -96,6 +96,7 @@ type Command struct {
flagCount int
log *Logger
helpFlag bool
hidden bool
}
// NewCommand creates a new Command
@@ -106,6 +107,7 @@ func NewCommand(name string, description string, app *Cli, parentCommandPath str
SubCommandsMap: make(map[string]*Command),
App: app,
log: NewLogger(),
hidden: false,
}
// Set up command path
@@ -195,10 +197,7 @@ func (c *Command) Action(callback Action) *Command {
// PrintHelp - Output the help text for this command
func (c *Command) PrintHelp() {
c.log.PrintBanner()
versionString := c.AppVersion
if versionString != "" {
versionString = " " + versionString
}
commandTitle := c.CommandPath
if c.Shortdescription != "" {
commandTitle += " - " + c.Shortdescription
@@ -215,6 +214,9 @@ func (c *Command) PrintHelp() {
c.log.White("Available commands:")
fmt.Println("")
for _, subcommand := range c.SubCommands {
if subcommand.isHidden() {
continue
}
spacer := strings.Repeat(" ", 3+c.longestSubcommand-len(subcommand.Name))
isDefault := ""
if subcommand.isDefaultCommand() {
@@ -240,6 +242,16 @@ func (c *Command) isDefaultCommand() bool {
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
func (c *Command) Command(name, description string) *Command {
result := NewCommand(name, description, c.App, c.CommandPath)

File diff suppressed because one or more lines are too long

View File

@@ -1,13 +1,19 @@
package cmd
import (
"bytes"
"crypto/md5"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"path"
"path/filepath"
"runtime"
"github.com/leaanthony/slicer"
)
// FSHelper - Wrapper struct for File System utility commands
@@ -104,11 +110,30 @@ func (fs *FSHelper) RemoveFiles(files []string) error {
return nil
}
type Dir struct {
localPath string
fullPath string
}
func (fs *FSHelper) Dir(dir string) (*Dir, error) {
fullPath, err := filepath.Abs(dir)
return &Dir{fullPath: fullPath}, err
}
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
func (fs *FSHelper) GetSubdirs(dir string) (map[string]string, error) {
func (d *Dir) GetSubdirs() (map[string]string, error) {
// Read in the directory information
fileInfo, err := ioutil.ReadDir(dir)
fileInfo, err := ioutil.ReadDir(d.fullPath)
if err != nil {
return nil, err
}
@@ -120,25 +145,65 @@ func (fs *FSHelper) GetSubdirs(dir string) (map[string]string, error) {
// map["directoryName"] = "path/to/directoryName"
for _, file := range fileInfo {
if file.IsDir() {
subdirs[file.Name()] = filepath.Join(dir, file.Name())
subdirs[file.Name()] = filepath.Join(d.fullPath, file.Name())
}
}
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.
// Returns error on failure
func (fs *FSHelper) MkDir(dir string) error {
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
// its contents as a string
func (fs *FSHelper) LoadAsString(filename string) (string, error) {
bytes, err := ioutil.ReadFile(filename)
bytes, err := fs.LoadAsBytes(filename)
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
func (fs *FSHelper) FileMD5(filename string) (string, error) {
f, err := os.Open(filename)

108
cmd/github.go Normal file
View File

@@ -0,0 +1,108 @@
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
}

View File

@@ -5,11 +5,11 @@ import (
"io/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"runtime"
"time"
mewn "github.com/leaanthony/mewn"
"github.com/leaanthony/slicer"
"github.com/leaanthony/spinner"
)
@@ -36,7 +36,7 @@ func ValidateFrontendConfig(projectOptions *ProjectOptions) error {
// InstallGoDependencies will run go get in the current directory
func InstallGoDependencies() error {
depSpinner := spinner.New("Installing Dependencies...")
depSpinner := spinner.New("Ensuring Dependencies are up to date...")
depSpinner.SetSpinSpeed(50)
depSpinner.Start()
err := NewProgramHelper().RunCommand("go get")
@@ -77,7 +77,14 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
packSpinner.Start()
buildCommand := slicer.String()
buildCommand.AddSlice([]string{"mewn", "build"})
buildCommand.Add("mewn")
if buildMode == BuildModeBridge {
// Ignore errors
buildCommand.Add("-i")
}
buildCommand.Add("build")
if binaryName != "" {
buildCommand.Add("-o")
@@ -110,10 +117,18 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
}
packSpinner.Success()
// packageApp
if packageApp {
err = PackageApplication(projectOptions)
if err != nil {
return err
}
}
return nil
}
// PackageApplication will attempt to package the application in a pltform dependent way
// PackageApplication will attempt to package the application in a platform dependent way
func PackageApplication(projectOptions *ProjectOptions) error {
// Package app
message := "Generating .app"
@@ -189,7 +204,7 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
}
// Check if frontend deps have been updated
feSpinner := spinner.New("Installing frontend dependencies (This may take a while)...")
feSpinner := spinner.New("Ensuring frontend dependencies are up to date (This may take a while)")
feSpinner.SetSpinSpeed(50)
feSpinner.Start()
@@ -234,16 +249,8 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
ioutil.WriteFile(md5sumFile, []byte(packageJSONMD5), 0644)
}
bridgeFile := "wailsbridge.prod.js"
if caller == "serve" {
bridgeFile = "wailsbridge.js"
}
// Copy bridge to project
_, filename, _, _ := runtime.Caller(1)
bridgeFileSource := filepath.Join(path.Dir(filename), "..", "..", "wailsruntimeassets", "bridge", bridgeFile)
bridgeFileTarget := filepath.Join(projectDir, projectOptions.FrontEnd.Dir, projectOptions.FrontEnd.Bridge, "wailsbridge.js")
err = fs.CopyFile(bridgeFileSource, bridgeFileTarget)
// Install the bridge library
err = InstallBridge(caller, projectDir, projectOptions)
if err != nil {
return err
}
@@ -256,6 +263,24 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
return nil
}
// InstallBridge installs the relevant bridge javascript library
func InstallBridge(caller string, projectDir string, projectOptions *ProjectOptions) error {
bridgeFile := "wailsbridge.prod.js"
if caller == "serve" {
bridgeFile = "wailsbridge.js"
}
// Copy bridge to project
bridgeAssets := mewn.Group("../wailsruntimeassets/bridge/")
bridgeFileData := bridgeAssets.Bytes(bridgeFile)
bridgeFileTarget := filepath.Join(projectDir, projectOptions.FrontEnd.Dir, projectOptions.FrontEnd.Bridge, "wailsbridge.js")
err := fs.CreateFile(bridgeFileTarget, bridgeFileData)
if err != nil {
return err
}
return nil
}
// ServeProject attempts to serve up the current project so that it may be connected to
// via the Wails bridge
func ServeProject(projectOptions *ProjectOptions, logger *Logger) error {

View File

@@ -2,6 +2,9 @@ package cmd
import (
"fmt"
"io/ioutil"
"os"
"regexp"
"strings"
)
@@ -10,9 +13,13 @@ type LinuxDistribution int
const (
// Unknown is the catch-all distro
Unknown LinuxDistribution = 0
Unknown LinuxDistribution = iota
// Ubuntu distribution
Ubuntu LinuxDistribution = 1
Ubuntu
// Arch linux distribution
Arch
// RedHat linux distribution
RedHat
)
// DistroInfo contains all the information relating to a linux distribution
@@ -49,6 +56,8 @@ func GetLinuxDistroInfo() *DistroInfo {
switch value {
case "Ubuntu":
result.Distribution = Ubuntu
case "Arch", "ManjaroLinux":
result.Distribution = Arch
}
case "Description":
result.Description = value
@@ -60,20 +69,52 @@ 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])
// Check distro name against list of RedHat distros
if osName == "Fedora" || osName == "CentOS" {
//if it matches set result.Distribution to RedHat
result.Distribution = RedHat
}
}
return result
}
// DpkgInstalled uses dpkg to see if a package is installed
func DpkgInstalled(packageName string) (bool, error) {
result := false
program := NewProgramHelper()
dpkg := program.FindProgram("dpkg")
if dpkg == nil {
return false, fmt.Errorf("cannot check dependencies: dpkg not found")
}
_, _, exitCode, _ := dpkg.Run("-L", packageName)
result = exitCode == 0
return result, nil
return exitCode == 0, 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
}

View File

@@ -72,11 +72,11 @@ func (b *PackageHelper) Package(po *ProjectOptions) error {
case "darwin":
// Check we have the exe
if !b.fs.FileExists(po.BinaryName) {
return fmt.Errorf("cannot bundle non-existant binary file '%s'. Please build with 'wails build' first", po.BinaryName)
return fmt.Errorf("cannot bundle non-existent binary file '%s'. Please build with 'wails build' first", po.BinaryName)
}
return b.packageOSX(po)
case "windows":
return b.PackageWindows(po, true)
return b.PackageWindows(po, false)
case "linux":
return fmt.Errorf("linux is not supported at this time. Please see https://github.com/wailsapp/wails/issues/2")
default:
@@ -199,7 +199,7 @@ func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
// clean up
if cleanUp {
filesToDelete := []string{tgtIconFile, tgtManifestFile, tgtRCFile}
filesToDelete := []string{tgtIconFile, tgtManifestFile, tgtRCFile, sysofile}
err := b.fs.RemoveFiles(filesToDelete)
if err != nil {
return err
@@ -255,9 +255,5 @@ func (b *PackageHelper) packageIconOSX(resourceDir string) error {
}
defer dest.Close()
if err := icns.Encode(dest, srcImg); err != nil {
return err
}
return nil
return icns.Encode(dest, srcImg)
}

View File

@@ -97,6 +97,12 @@ func getRequiredLibrariesLinux() (*Prerequisites, error) {
case Ubuntu:
result.Add(newPrerequisite("libgtk-3-dev", "Please install with `sudo apt install libgtk-3-dev` and try again"))
result.Add(newPrerequisite("libwebkit2gtk-4.0-dev", "Please install with `sudo apt install libwebkit2gtk-4.0-dev` and try again"))
case Arch:
result.Add(newPrerequisite("gtk3", "Please install with `sudo pacman -S gtk3` and try again"))
result.Add(newPrerequisite("webkit2gtk", "Please install with `sudo pacman -S webkit2gtk` and try again"))
case RedHat:
result.Add(newPrerequisite("gtk3-devel", "Please install with `sudo yum install gtk3-devel` and try again"))
result.Add(newPrerequisite("webkit2gtk3-devel", "Please install with `sudo yum install webkit2gtk3-devel` and try again"))
default:
result.Add(newPrerequisite("libgtk-3-dev", "Please install with your system package manager and try again"))
result.Add(newPrerequisite("libwebkit2gtk-4.0-dev", "Please install with your system package manager and try again"))

View File

@@ -56,7 +56,7 @@ func (p *Program) GetFullPathToBinary() (string, error) {
}
// Run will execute the program with the given parameters
// Returns stdout + stderr as strings and an error if one occured
// Returns stdout + stderr as strings and an error if one occurred
func (p *Program) Run(vars ...string) (stdout, stderr string, exitCode int, err error) {
command, err := p.GetFullPathToBinary()
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
func (p *ProgramHelper) InstallGoPackage(packageName string) error {
args := strings.Split("get -u "+packageName, " ")
args := strings.Split("get "+packageName, " ")
_, stderr, err := p.shell.Run("go", args...)
if err != nil {
fmt.Println(stderr)
@@ -107,7 +107,7 @@ func (p *ProgramHelper) RunCommand(command string) error {
}
// RunCommandArray runs the command specified in the array
func (p *ProgramHelper) RunCommandArray(args []string) error {
func (p *ProgramHelper) RunCommandArray(args []string, dir ...string) error {
program := args[0]
// TODO: Run FindProgram here and get the full path to the exe
program, err := exec.LookPath(program)
@@ -116,8 +116,13 @@ func (p *ProgramHelper) RunCommandArray(args []string) error {
return err
}
args = args[1:]
var stderr string
// fmt.Printf("RunCommandArray = %s %+v\n", program, args)
_, stderr, err := p.shell.Run(program, args...)
if len(dir) > 0 {
_, stderr, err = p.shell.RunInDirectory(dir[0], program, args...)
} else {
_, stderr, err = p.shell.Run(program, args...)
}
if err != nil {
fmt.Println(stderr)
}

View File

@@ -50,12 +50,6 @@ func NewProjectHelper() *ProjectHelper {
// GenerateProject generates a new project using the options given
func (ph *ProjectHelper) GenerateProject(projectOptions *ProjectOptions) error {
// exists := ph.templates.TemplateExists(projectOptions.Template)
// if !exists {
// return fmt.Errorf("template '%s' is invalid", projectOptions.Template)
// }
// Calculate project path
projectPath, err := filepath.Abs(projectOptions.OutputDirectory)
if err != nil {
@@ -173,19 +167,43 @@ func (po *ProjectOptions) PromptForInputs() error {
// Process Templates
templateList := slicer.Interface()
options := slicer.String()
for _, templateDetails := range po.templates.TemplateList.details {
templateList.Add(templateDetails)
options.Add(fmt.Sprintf("%s - %s", templateDetails.Metadata.Name, templateDetails.Metadata.ShortDescription))
templateDetails, err := po.templates.GetTemplateDetails()
if err != nil {
return err
}
templateIndex := 0
if po.Template != "" {
// Check template is valid if given
if templateDetails[po.Template] == nil {
keys := make([]string, 0, len(templateDetails))
for k := range templateDetails {
keys = append(keys, k)
}
return fmt.Errorf("invalid template name '%s'. Valid options: %s", po.Template, strings.Join(keys, ", "))
}
po.selectedTemplate = templateDetails[po.Template]
} else {
if len(options.AsSlice()) > 1 {
templateIndex = PromptSelection("Please select a template", options.AsSlice(), 0)
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)
}
// After selection do this....
po.selectedTemplate = templateList.AsSlice()[templateIndex].(*TemplateDetails)
fmt.Println("Template: " + po.selectedTemplate.Metadata.Name)
// Setup NPM Project name
po.NPMProjectName = strings.ToLower(strings.Replace(po.Name, " ", "_", -1))
@@ -266,7 +284,6 @@ func processProjectName(po *ProjectOptions) {
po.Name = Prompt("The name of the project", "My Project")
}
fmt.Println("Project Name: " + po.Name)
}
func processBinaryName(po *ProjectOptions) {

View File

@@ -4,7 +4,9 @@ import (
"bufio"
"fmt"
"os"
"runtime"
"strconv"
"strings"
)
// Prompt asks the user for a value
@@ -16,9 +18,16 @@ func Prompt(question string, defaultValue ...string) string {
question = fmt.Sprintf("%s (%s)", question, answer)
}
fmt.Printf(question + ": ")
scanner := bufio.NewScanner(os.Stdin)
if scanner.Scan() {
answer = scanner.Text()
reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n')
EOL := "\n"
if runtime.GOOS == "windows" {
EOL = "\r\n"
}
input = strings.Replace(input, EOL, "", -1)
if input != "" {
answer = input
}
return answer

98
cmd/semver.go Normal file
View File

@@ -0,0 +1,98 @@
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]
}

View File

@@ -1 +0,0 @@
package cmd

View File

@@ -2,6 +2,7 @@ package cmd
import (
"bytes"
"os"
"os/exec"
)
@@ -17,6 +18,21 @@ func NewShellHelper() *ShellHelper {
// Run the given command
func (sh *ShellHelper) Run(command string, vars ...string) (stdout, stderr string, err error) {
cmd := exec.Command(command, vars...)
cmd.Env = append(os.Environ(), "GO111MODULE=on")
var stdo, stde bytes.Buffer
cmd.Stdout = &stdo
cmd.Stderr = &stde
err = cmd.Run()
stdout = string(stdo.Bytes())
stderr = string(stde.Bytes())
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
cmd.Stdout = &stdo
cmd.Stderr = &stde

View File

@@ -68,6 +68,17 @@ func (s *SystemHelper) ConfigFileIsValid() bool {
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
func (s *SystemHelper) BackupConfig() (string, error) {
now := strconv.FormatInt(time.Now().UTC().UnixNano(), 10)
@@ -81,21 +92,24 @@ func (s *SystemHelper) BackupConfig() (string, error) {
func (s *SystemHelper) setup() error {
systemConfig := make(map[string]string)
// Try to load current values - ignore errors
config, err := s.LoadConfig()
defaultName := ""
defaultEmail := ""
if config != nil {
defaultName = config.Name
defaultEmail = config.Email
config, _ := s.LoadConfig()
if config.Name != "" {
systemConfig["name"] = PromptRequired("What is your name", config.Name)
} else {
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")
}
systemConfig := make(map[string]string)
systemConfig["name"] = PromptRequired("What is your name", defaultName)
systemConfig["email"] = PromptRequired("What is your email address", defaultEmail)
// Create the directory
err = s.fs.MkDirs(s.wailsSystemDir)
err := s.fs.MkDirs(s.wailsSystemDir)
if err != nil {
return err
}
@@ -242,7 +256,7 @@ func CheckDependencies(logger *Logger) (bool, error) {
bin := programHelper.FindProgram(program.Name)
if bin == nil {
errors = true
logger.Red("Program '%s' not found. %s", program.Name, program.Help)
logger.Error("Program '%s' not found. %s", program.Name, program.Help)
} else {
logger.Green("Program '%s' found: %s", program.Name, bin.Path)
}
@@ -265,7 +279,30 @@ func CheckDependencies(logger *Logger) (bool, error) {
}
if !installed {
errors = true
logger.Red("Library '%s' not found. %s", library.Name, library.Help)
logger.Error("Library '%s' not found. %s", library.Name, library.Help)
} else {
logger.Green("Library '%s' installed.", library.Name)
}
case Arch:
installed, err := PacmanInstalled(library.Name)
if err != nil {
return false, err
}
if !installed {
errors = true
logger.Error("Library '%s' not found. %s", library.Name, library.Help)
} else {
logger.Green("Library '%s' installed.", library.Name)
}
case RedHat:
installed, err := RpmInstalled(library.Name)
if err != nil {
return false, err
}
if !installed {
errors = true
logger.Error("Library '%s' not found. %s", library.Name, library.Help)
} else {
logger.Green("Library '%s' installed.", library.Name)
}

View File

@@ -3,20 +3,21 @@ package cmd
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"path/filepath"
"regexp"
"strings"
"text/template"
mewn "github.com/leaanthony/mewn"
mewnlib "github.com/leaanthony/mewn/lib"
"github.com/kennygrant/sanitize"
"github.com/leaanthony/slicer"
)
// TemplateMetadata holds all the metadata for a Wails template
type TemplateMetadata struct {
Name string `json:"name"`
Version string `json:"version"`
ShortDescription string `json:"shortdescription"`
Description string `json:"description"`
Install string `json:"install"`
@@ -26,91 +27,146 @@ type TemplateMetadata struct {
FrontendDir string `json:"frontenddir"`
Serve string `json:"serve"`
Bridge string `json:"bridge"`
WailsDir string `json:"wailsdir"`
}
// TemplateDetails holds information about a specific template
type TemplateDetails struct {
BasePath string
Name string
Path string
Metadata *TemplateMetadata
}
// TemplateList is a list of available templates
type TemplateList struct {
details map[string]*TemplateDetails
}
// NewTemplateList creates a new TemplateList object
func NewTemplateList(filenames *mewnlib.FileGroup) *TemplateList {
// Iterate each template and store information
result := &TemplateList{details: make(map[string]*TemplateDetails)}
entries := slicer.String()
entries.AddSlice(filenames.Entries())
// Find all template.json files
metadataFiles := entries.Filter(func(filename string) bool {
match, _ := regexp.MatchString("(.)+template.json$", filename)
return match
})
// Load each metadata file
metadataFiles.Each(func(filename string) {
fileData := filenames.Bytes(filename)
var metadata TemplateMetadata
err := json.Unmarshal(fileData, &metadata)
if err != nil {
log.Fatalf("corrupt metadata for template: %s", filename)
}
path := strings.Split(filename, string(filepath.Separator))[0]
thisTemplate := &TemplateDetails{Path: path, Metadata: &metadata}
result.details[filename] = thisTemplate
})
return result
}
// Template holds details about a Wails template
type Template struct {
Name string
Path string
Description string
fs *FSHelper
}
// TemplateHelper is a utility object to help with processing templates
type TemplateHelper struct {
TemplateList *TemplateList
Files *mewnlib.FileGroup
templateDir *Dir
fs *FSHelper
metadataFilename string
}
// NewTemplateHelper creates a new template helper
func NewTemplateHelper() *TemplateHelper {
files := mewn.Group("./templates")
templateDir, err := fs.LocalDir("./templates")
if err != nil {
log.Fatal("Unable to find the template directory. Please reinstall Wails.")
}
return &TemplateHelper{
TemplateList: NewTemplateList(files),
Files: files,
templateDir: templateDir,
metadataFilename: "template.json",
}
}
// IsValidTemplate returns true if the given tempalte name resides on disk
func (t *TemplateHelper) IsValidTemplate(templateName string) bool {
pathToTemplate := filepath.Join(t.templateDir.fullPath, templateName)
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 {
return "", err
}
targetMetadata := filepath.Join(targetDir, t.metadataFilename)
err = t.fs.SaveAsJSON(details, targetMetadata)
return targetDir, err
}
// LoadMetadata loads the template's 'metadata.json' file
func (t *TemplateHelper) LoadMetadata(dir string) (*TemplateMetadata, error) {
templateFile := filepath.Join(dir, t.metadataFilename)
result := &TemplateMetadata{}
if !t.fs.FileExists(templateFile) {
return nil, nil
}
rawJSON, err := ioutil.ReadFile(templateFile)
if err != nil {
return nil, err
}
err = json.Unmarshal(rawJSON, &result)
return result, err
}
// GetTemplateDetails returns a map of Template structs containing details
// of the found templates
func (t *TemplateHelper) GetTemplateDetails() (map[string]*TemplateDetails, error) {
// Get the subdirectory details
templateDirs, err := t.templateDir.GetSubdirs()
if err != nil {
return nil, err
}
result := make(map[string]*TemplateDetails)
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.Dir(template.Path)
if err != nil {
return nil, err
}
return templateDir.GetAllFilenames()
}
// InstallTemplate installs the template given in the project options to the
// project path given
func (t *TemplateHelper) InstallTemplate(projectPath string, projectOptions *ProjectOptions) error {
// Get template files
templateFilenames, err := t.GetTemplateFilenames(projectOptions.selectedTemplate)
if err != nil {
return err
}
templatePath := projectOptions.selectedTemplate.Path
templateFilenames := slicer.String()
templateFilenames.AddSlice(projectOptions.templates.Files.Entries())
templateJSONFilename := filepath.Join(templatePath, "template.json")
templateJSONFilename := filepath.Join(templatePath, t.metadataFilename)
templateFiles := templateFilenames.Filter(func(filename string) bool {
filename = filepath.FromSlash(filename)
return strings.HasPrefix(filename, templatePath) && filename != templateJSONFilename
})
var err error
templateFiles.Each(func(templateFile string) {
// Setup filenames
@@ -119,11 +175,14 @@ func (t *TemplateHelper) InstallTemplate(projectPath string, projectOptions *Pro
if err != nil {
return
}
filedata := projectOptions.templates.Files.Bytes(templateFile)
filedata, err := t.fs.LoadAsBytes(templateFile)
if err != nil {
return
}
// If file is a template, process it
if strings.HasSuffix(templateFile, ".template") {
templateData := projectOptions.templates.Files.String(templateFile)
templateData := string(filedata)
tmpl := template.New(templateFile)
tmpl.Parse(templateData)
var tpl bytes.Buffer

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,17 +0,0 @@
<!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>

View File

@@ -2,6 +2,7 @@ import Vue from "vue";
import App from "./App.vue";
Vue.config.productionTip = false;
Vue.config.devtools = true;
import Bridge from "./wailsbridge";

View File

@@ -11,12 +11,15 @@ func basic() string {
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: mewn.String("./frontend/dist/app.js"),
CSS: mewn.String("./frontend/dist/app.css"),
JS: js,
CSS: css,
Colour: "#131313",
})
app.Bind(basic)

View File

@@ -1,5 +1,4 @@
package cmd
// Version - Wails version
// ...oO(There must be a better way)
const Version = "v0.9.7"
const Version = "v0.14.4-pre"

View File

@@ -18,11 +18,13 @@ func init() {
setupCommand.Action(func() error {
logger.PrintBanner();
logger.PrintBanner()
var err error
system := cmd.NewSystemHelper()
err := system.Initialise()
if err != nil {
err = system.Initialise()
if err == nil {
return err
}
@@ -39,13 +41,15 @@ Create your first project by running 'wails init'.`
// Check we have a cgo capable environment
logger.Yellow("Checking for prerequisites...")
errors, err := checkRequiredPrograms()
var requiredProgramErrors bool
requiredProgramErrors, err = checkRequiredPrograms()
if err != nil {
return err
}
// Linux has library deps
errors, err = checkLibraries()
var libraryErrors bool
libraryErrors, err = checkLibraries()
if err != nil {
return err
}
@@ -58,6 +62,8 @@ Create your first project by running 'wails init'.`
logger.White("")
// Check for errors
var errors = libraryErrors || requiredProgramErrors
if !errors {
logger.Yellow(successMessage)
}

View File

@@ -0,0 +1,121 @@
// +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
})
}

18
cmd/wails/10_dev.go Normal file
View File

@@ -0,0 +1,18 @@
// +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
})
}

View File

@@ -17,7 +17,7 @@ Any flags that are required and not given will be prompted for.`
LongDescription(commandDescription).
BoolFlag("f", "Use defaults", &projectOptions.UseDefaults).
StringFlag("dir", "Directory to create project in", &projectOptions.OutputDirectory).
// StringFlag("template", "Template name", &projectOptions.Template).
StringFlag("template", "Template name", &projectOptions.Template).
StringFlag("name", "Project name", &projectOptions.Name).
StringFlag("description", "Project description", &projectOptions.Description).
StringFlag("output", "Output binary name", &projectOptions.BinaryName)

View File

@@ -26,6 +26,9 @@ func init() {
initCmd.Action(func() error {
message := "Building Application"
if packageApp {
message = "Packaging Application"
}
if forceRebuild {
message += " (force rebuild)"
}
@@ -40,7 +43,7 @@ func init() {
fs := cmd.NewFSHelper()
err := projectOptions.LoadConfig(fs.Cwd())
if err != nil {
return err
return fmt.Errorf("Unable to find 'project.json'. Please check you are in a Wails project directory")
}
// Validate config

View File

@@ -14,7 +14,7 @@ func init() {
buildSpinner.SetSpinSpeed(50)
commandDescription := `This command builds then serves your application in bridge mode. Useful for developing your app in a browser.`
initCmd := app.Command("serve", "Run your Wails project in bridge mode.").
initCmd := app.Command("serve", "Run your Wails project in bridge mode").
LongDescription(commandDescription).
BoolFlag("f", "Force rebuild of application components", &forceRebuild)
@@ -24,19 +24,28 @@ func init() {
logger.PrintSmallBanner(message)
fmt.Println()
// Check Mewn is installed
err := cmd.CheckMewn()
if err != nil {
return err
}
// Project options
projectOptions := &cmd.ProjectOptions{}
// Check we are in project directory
// Check project.json loads correctly
fs := cmd.NewFSHelper()
err := projectOptions.LoadConfig(fs.Cwd())
err = projectOptions.LoadConfig(fs.Cwd())
if err != nil {
return err
}
// Check Mewn is installed
err = cmd.CheckMewn()
// Save project directory
projectDir := fs.Cwd()
// Install the bridge library
err = cmd.InstallBridge("serve", projectDir, projectOptions)
if err != nil {
return err
}

View File

@@ -2,23 +2,27 @@ package main
import (
"fmt"
"net/http"
"io/ioutil"
"encoding/json"
"log"
"github.com/leaanthony/spinner"
"github.com/mitchellh/go-homedir"
"github.com/wailsapp/wails/cmd"
)
func init() {
var prereleaseRequired bool
var specificVersion string
// var forceRebuild = false
checkSpinner := spinner.NewSpinner()
checkSpinner.SetSpinSpeed(50)
commandDescription := `This command checks if there are updates to Wails.`
updateCmd := app.Command("update", "Check for Updates.").
LongDescription(commandDescription)
commandDescription := `This command allows you to update your version of Wails.`
updateCmd := app.Command("update", "Update to newer [pre]releases or specific versions").
LongDescription(commandDescription).
BoolFlag("pre", "Update to latest Prerelease", &prereleaseRequired).
StringFlag("version", "Install a specific version (Overrides other flags)", &specificVersion)
updateCmd.Action(func() error {
@@ -28,42 +32,133 @@ func init() {
// Get versions
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 {
checkSpinner.Error(err.Error())
return err
}
checkSpinner.Success()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
checkSpinner.Error(err.Error())
return err
}
data := []map[string]interface{}{}
err = json.Unmarshal(body, &data)
if err != nil {
return err
}
latestVersion := data[0]["name"].(string)
fmt.Println()
fmt.Println("Current Version: " + cmd.Version)
fmt.Println(" Latest Version: " + latestVersion)
if latestVersion != cmd.Version {
updateSpinner := spinner.NewSpinner()
updateSpinner.SetSpinSpeed(40)
updateSpinner.Start("Updating to : " + latestVersion)
err = cmd.NewProgramHelper().RunCommandArray([]string{"go","get","-u","github.com/wailsapp/wails/cmd/wails"})
if err != nil {
updateSpinner.Error(err.Error())
return err
}
updateSpinner.Success()
logger.Yellow("Wails updated to " + latestVersion)
fmt.Println(" Current Version : " + cmd.Version)
if len(specificVersion) > 0 {
fmt.Printf(" Desired Version : v%s\n", desiredVersion)
} else {
logger.Yellow("Looks like you're up to date!")
if prereleaseRequired {
fmt.Printf(" Latest Prerelease : v%s\n", desiredVersion)
} else {
fmt.Printf(" Latest Release : v%s\n", desiredVersion)
}
}
return nil
return updateToVersion(desiredVersion, len(specificVersion) > 0)
})
}
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 {
return err
}
var success bool
// Release -> Pre-Release = Massage current version to prerelease format
if targetVersion.IsPreRelease() && currentVersion.IsRelease() {
testVersion, err := cmd.NewSemanticVersion(compareVersion + "-0")
if err != nil {
return err
}
success, _ = targetVersion.IsGreaterThan(testVersion)
}
// 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 {
return err
}
success, _ = targetVersion.IsGreaterThanOrEqual(mainversion)
}
// 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
}

View File

@@ -18,7 +18,7 @@ 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.").
initCommand := app.Command("issue", "Generates an issue in Github").
LongDescription(commandDescription)
initCommand.Action(func() error {

19
cmd/windows.go Normal file
View File

@@ -0,0 +1,19 @@
// +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)
}

View File

@@ -87,7 +87,7 @@ func (e *eventManager) start(renderer Renderer) {
var wg sync.WaitGroup
wg.Add(1)
// Run main loop in seperate goroutine
// Run main loop in separate goroutine
go func() {
wg.Done()
e.log.Info("Listening")
@@ -126,7 +126,7 @@ func (e *eventManager) start(renderer Renderer) {
}
}
// Remove expired listners in place
// Remove expired listeners in place
if len(listenersToRemove) > 0 {
listeners := e.listeners[event.Name][:0]
for _, listener := range listeners {

71
go.mod
View File

@@ -1,74 +1,31 @@
module github.com/wailsapp/wails
require (
cloud.google.com/go v0.36.0 // indirect
dmitri.shuralyov.com/app/changes v0.0.0-20181114035150-5af16e21babb // indirect
dmitri.shuralyov.com/service/change v0.0.0-20190203163610-217368fe4577 // indirect
git.apache.org/thrift.git v0.12.0 // indirect
github.com/Shopify/sarama v1.20.1 // indirect
github.com/akavel/rsrc v0.0.0-20170831122431-f6a15ece2cfd // indirect
github.com/coreos/go-systemd v0.0.0-20190212144455-93d5ec2c7f76 // indirect
github.com/Masterminds/semver v1.4.2 // indirect
github.com/dchest/cssmin v0.0.0-20151210170030-fb8d9b44afdc // indirect
github.com/dchest/htmlmin v0.0.0-20150526090704-e254725e81ac
github.com/dchest/jsmin v0.0.0-20160823214000-faeced883947 // indirect
github.com/fatih/color v1.7.0
github.com/gliderlabs/ssh v0.1.3 // indirect
github.com/go-logfmt/logfmt v0.4.0 // indirect
github.com/go-playground/colors v1.2.0
github.com/gogo/protobuf v1.2.1 // indirect
github.com/golang/lint v0.0.0-20181217174547-8f45f776aaf1 // indirect
github.com/golang/snappy v0.0.1 // indirect
github.com/google/pprof v0.0.0-20190208070709-b421f19a5c07 // indirect
github.com/googleapis/gax-go v2.0.2+incompatible // indirect
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e // indirect
github.com/gorilla/mux v1.7.0 // indirect
github.com/gorilla/websocket v1.4.0
github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc // indirect
github.com/grpc-ecosystem/grpc-gateway v1.7.0 // indirect
github.com/jackmordaunt/icns v1.0.0
github.com/kisielk/errcheck v1.2.0 // indirect
github.com/leaanthony/mewn v0.9.4
github.com/leaanthony/slicer v1.2.0
github.com/kennygrant/sanitize v1.2.4
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/leaanthony/mewn v0.10.6
github.com/leaanthony/slicer v1.3.1
github.com/leaanthony/spinner v0.5.0
github.com/mattn/go-colorable v0.1.0 // indirect
github.com/microcosm-cc/bluemonday v1.0.2 // indirect
github.com/masterminds/semver v1.4.2
github.com/mattn/go-colorable v0.1.1 // indirect
github.com/mattn/go-isatty v0.0.7 // indirect
github.com/mitchellh/go-homedir v1.1.0
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/openzipkin/zipkin-go v0.1.5 // indirect
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4
github.com/pkg/errors v0.8.1 // indirect
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 // indirect
github.com/prometheus/common v0.2.0 // indirect
github.com/prometheus/procfs v0.0.0-20190219184716-e4d4a2206da0 // indirect
github.com/russross/blackfriday v2.0.0+incompatible // indirect
github.com/shurcooL/go v0.0.0-20190121191506-3fef8c783dec // indirect
github.com/shurcooL/gofontwoff v0.0.0-20181114050219-180f79e6909d // indirect
github.com/shurcooL/highlight_diff v0.0.0-20181222201841-111da2e7d480 // indirect
github.com/shurcooL/highlight_go v0.0.0-20181215221002-9d8641ddf2e1 // indirect
github.com/shurcooL/home v0.0.0-20190204141146-5c8ae21d4240 // indirect
github.com/shurcooL/htmlg v0.0.0-20190120222857-1e8a37b806f3 // indirect
github.com/shurcooL/httpfs v0.0.0-20181222201310-74dc9339e414 // indirect
github.com/shurcooL/issues v0.0.0-20190120000219-08d8dadf8acb // indirect
github.com/shurcooL/issuesapp v0.0.0-20181229001453-b8198a402c58 // indirect
github.com/shurcooL/notifications v0.0.0-20181111060504-bcc2b3082a7a // indirect
github.com/shurcooL/octicon v0.0.0-20181222203144-9ff1a4cf27f4 // indirect
github.com/shurcooL/reactions v0.0.0-20181222204718-145cd5e7f3d1 // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
github.com/shurcooL/webdavfs v0.0.0-20181215192745-5988b2d638f6 // indirect
github.com/sirupsen/logrus v1.3.0
github.com/sirupsen/logrus v1.4.1
github.com/stretchr/testify v1.3.0 // indirect
github.com/wailsapp/webview v0.2.5
go.opencensus.io v0.19.0 // indirect
go4.org v0.0.0-20190218023631-ce4c26f7be8e // indirect
golang.org/x/build v0.0.0-20190221223049-69dd6b2c22e1 // indirect
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2 // indirect
golang.org/x/exp v0.0.0-20190221220918-438050ddec5e // indirect
golang.org/x/oauth2 v0.0.0-20190220154721-9b3c75971fc9 // indirect
golang.org/x/perf v0.0.0-20190124201629-844a5f5b46f4 // indirect
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 // indirect
golang.org/x/tools v0.0.0-20190221204921-83362c3779f5 // indirect
google.golang.org/genproto v0.0.0-20190219182410-082222b4a5c5 // indirect
google.golang.org/grpc v1.18.0 // indirect
honnef.co/go/tools v0.0.0-20190215041234-466a0476246c // indirect
sourcegraph.com/sqs/pbtypes v1.0.0 // indirect
github.com/wailsapp/webview v0.2.7
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 // indirect
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5 // indirect
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862
gopkg.in/AlecAivazis/survey.v1 v1.8.4
)

303
go.sum
View File

@@ -1,30 +1,9 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.33.1/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.36.0/go.mod h1:RUoy9p/M4ge0HzT8L+SDZ8jg+Q6fth0CiBuhFJpSV40=
dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
dmitri.shuralyov.com/app/changes v0.0.0-20181114035150-5af16e21babb/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
dmitri.shuralyov.com/service/change v0.0.0-20190203163610-217368fe4577/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
git.apache.org/thrift.git v0.0.0-20181218151757-9b75e4fe745a/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
git.apache.org/thrift.git v0.12.0/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/sarama v1.20.1/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/akavel/rsrc v0.0.0-20170831122431-f6a15ece2cfd/go.mod h1:2+aQMrY0hBFBaIr2xxnZ/ctfwnYmMRMbTczYLAC34v4=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190212144455-93d5ec2c7f76/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dchest/cssmin v0.0.0-20151210170030-fb8d9b44afdc h1:VBS1z48BFEe00G81z8MKOtwX7f/ISkuH38NscT8iVPw=
github.com/dchest/cssmin v0.0.0-20151210170030-fb8d9b44afdc/go.mod h1:ABJPuor7YlcsHmvJ1QxX38e2NcufLY3hm0yXv+cy9sI=
@@ -32,279 +11,97 @@ github.com/dchest/htmlmin v0.0.0-20150526090704-e254725e81ac h1:DpMwFluHWoZpV9ex
github.com/dchest/htmlmin v0.0.0-20150526090704-e254725e81ac/go.mod h1:XsAE+b4rOZc8gvgsgF+wU75mNBvBcyED1wdd9PBLlJ0=
github.com/dchest/jsmin v0.0.0-20160823214000-faeced883947 h1:Fm10/KNuoAyBm2P5P5H91Xy21hGcZnBdjR+cMdytv1M=
github.com/dchest/jsmin v0.0.0-20160823214000-faeced883947/go.mod h1:Dv9D0NUlAsaQcGQZa5kc5mqR9ua72SmA8VXi4cd+cBw=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/gliderlabs/ssh v0.1.3/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
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-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
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/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190208070709-b421f19a5c07/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
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/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/grpc-ecosystem/grpc-gateway v1.6.2/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/grpc-ecosystem/grpc-gateway v1.7.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
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/go.mod h1:7TTQVEuGzVVfOPPlLNHJIkzA6CoV7aH1Dv9dW351oOo=
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
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/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/leaanthony/mewn v0.9.0 h1:GExA7M15ikWytAIBKgs9SDl9EOC04JSjvL29qiLTAq4=
github.com/leaanthony/mewn v0.9.0/go.mod h1:CRkTx8unLiSSilu/Sd7i1LwrdaAL+3eQ3ses99qGMEQ=
github.com/leaanthony/mewn v0.9.1 h1:+qmAnR5nETU/00o5wvYJ7w9Y36R9uIBRB9I15E9Ru8A=
github.com/leaanthony/mewn v0.9.1/go.mod h1:CRkTx8unLiSSilu/Sd7i1LwrdaAL+3eQ3ses99qGMEQ=
github.com/leaanthony/mewn v0.9.4 h1:thDAdV8DkCwqHcFLnfMLQtTHqK1N8leF7sD/SPsLMHI=
github.com/leaanthony/mewn v0.9.4/go.mod h1:CRkTx8unLiSSilu/Sd7i1LwrdaAL+3eQ3ses99qGMEQ=
github.com/leaanthony/slicer v1.0.0 h1:BV2CySexcZ20qyHp5qBTxQhsazR6e8MBTF1EHmGu1xw=
github.com/leaanthony/slicer v1.0.0/go.mod h1:VMB/HGvr3uR3MRpFWHWAm0w+DHQLzPHYe2pKfpFlQIQ=
github.com/leaanthony/slicer v1.2.0 h1:XZ+1l7cCO36j238iv5ZXkJAcM3hPtD0xb41/WE+QmuU=
github.com/leaanthony/slicer v1.2.0/go.mod h1:VMB/HGvr3uR3MRpFWHWAm0w+DHQLzPHYe2pKfpFlQIQ=
github.com/leaanthony/mewn v0.10.6 h1:tL8YYcVXGpJJeWlwjd2su88or8Ul+0cQoJPNcICGMto=
github.com/leaanthony/mewn v0.10.6/go.mod h1:i3ygCWW96qVQlGa8sjWnTM0IKAijoFvTwATDIZgK4k0=
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.0 h1:HQykt/iTy7fmINEREtRbWrt+8j4MxC8dtvWBxEWM9oA=
github.com/leaanthony/spinner v0.5.0/go.mod h1:8TSFz9SL1AUC4XSbEFYE6SfN5Mlus51qYluVGrie9ww=
github.com/leaanthony/synx v0.1.0 h1:R0lmg2w6VMb8XcotOwAe5DLyzwjLrskNkwU7LLWsyL8=
github.com/leaanthony/synx v0.1.0/go.mod h1:Iz7eybeeG8bdq640iR+CwYb8p+9EOsgMWghkSRyZcqs=
github.com/leaanthony/wincursor v0.1.0 h1:Dsyp68QcF5cCs65AMBmxoYNEm0n8K7mMchG6a8fYxf8=
github.com/leaanthony/wincursor v0.1.0/go.mod h1:7TVwwrzSH/2Y9gLOGH+VhA+bZhoWXBRgbGNTMk+yimE=
github.com/masterminds/semver v1.4.2 h1:BgrAYDjlAebjtOwS7C/1QZoh5WgyXx4b59ydc+Ph8xI=
github.com/masterminds/semver v1.4.2/go.mod h1:s7KNT9fnd7edGzwwP7RBX4H0v/CYd5qdOLfkL1V75yg=
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.0 h1:v2XXALHHh6zHfYTJ+cSkwtyffnaOyR1MXaA91mTrb8o=
github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc=
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
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/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
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/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/openzipkin/zipkin-go v0.1.3/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/openzipkin/zipkin-go v0.1.5/go.mod h1:8NDCjKHoHW1XOp/vf3lClHem0b91r4433B67KXyKXAQ=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4 h1:49lOXmGaUpV9Fz3gd7TFZY106KVlPVa5jcYD1gaQf98=
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20181218105931-67670fe90761/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190219184716-e4d4a2206da0/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/ribice/glice v0.0.0-20181011133736-685f13fa9b12/go.mod h1:A+ednilkKNW0CJGLsrLkq0D49M4EhlCi8gvnkwoZFn0=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go v0.0.0-20190121191506-3fef8c783dec/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw=
github.com/shurcooL/gofontwoff v0.0.0-20181114050219-180f79e6909d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw=
github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI=
github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU=
github.com/shurcooL/highlight_diff v0.0.0-20181222201841-111da2e7d480/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU=
github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag=
github.com/shurcooL/highlight_go v0.0.0-20181215221002-9d8641ddf2e1/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag=
github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg=
github.com/shurcooL/home v0.0.0-20190204141146-5c8ae21d4240/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg=
github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw=
github.com/shurcooL/htmlg v0.0.0-20190120222857-1e8a37b806f3/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw=
github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y=
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/httpfs v0.0.0-20181222201310-74dc9339e414/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q=
github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ=
github.com/shurcooL/issues v0.0.0-20190120000219-08d8dadf8acb/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ=
github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I=
github.com/shurcooL/issuesapp v0.0.0-20181229001453-b8198a402c58/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I=
github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0=
github.com/shurcooL/notifications v0.0.0-20181111060504-bcc2b3082a7a/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0=
github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
github.com/shurcooL/octicon v0.0.0-20181222203144-9ff1a4cf27f4/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk=
github.com/shurcooL/reactions v0.0.0-20181222204718-145cd5e7f3d1/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk=
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
github.com/shurcooL/webdavfs v0.0.0-20181215192745-5988b2d638f6/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
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/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
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/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.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/wailsapp/webview v0.2.5 h1:/VacryPEUeMBb2VHHOjpoIze6ki8tW3qYX04MnI0b7o=
github.com/wailsapp/webview v0.2.5/go.mod h1:XO9HJbKWokDxUYTWQEBCYg95n/To1v7PxvanDNVf8hY=
github.com/wailsapp/webview v0.2.7 h1:fN5L5H9Oivg9IJPk7uaXQnjqB68Fny11ZWkIaTIZHmk=
github.com/wailsapp/webview v0.2.7/go.mod h1:XO9HJbKWokDxUYTWQEBCYg95n/To1v7PxvanDNVf8hY=
github.com/zserge/webview v0.0.0-20190123072648-16c93bcaeaeb/go.mod h1:a1CV8KR4Dd1eP2g+mEijGOp+HKczwdKHWyx0aPHKvo4=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go.opencensus.io v0.19.0/go.mod h1:AYeH0+ZxYyghG8diqaaIq/9P3VgCCt5GF2ldCY4dkFg=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
go4.org v0.0.0-20190218023631-ce4c26f7be8e/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/build v0.0.0-20190221223049-69dd6b2c22e1/go.mod h1:LS5++pZInCkeGSsPGP/1yB0yvU9gfqv2yD1PQgIbDYI=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 h1:u+LnwYTOOW7Ukr/fppxEb1Nwz0AtPflrblfvUudpo+I=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2 h1:NwxKRvbkH5MsNkvOtPZi3/3kmI8CAzs3mtv+GLQMkNo=
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190221220918-438050ddec5e/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181217023233-e147a9138326/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3 h1:eH6Eip3UpmR+yM/qI9Ijluzb1bNv/cAU/n+6l8tRSis=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd h1:HuTn7WObtcDo9uEEU7rEqL0jYthdXAmZ6PP+meazmaU=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181120190819-8f65e3013eba/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5 h1:6M3SDHlHHDCx2PcQw3S4KsR170vGqDhJDOmpVd4Hjak=
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190220154721-9b3c75971fc9/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
golang.org/x/perf v0.0.0-20190124201629-844a5f5b46f4/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181218192612-074acd46bca6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb h1:pf3XwC90UUdNPYWZdFjhGBE7DUFuK3Ct1zWmZ65QN30=
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862 h1:rM0ROo5vb9AdYJi1110yjWGMej9ITfKddS89P3Fkhug=
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181122213734-04b5d21e00f1/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181219222714-6e267b5cc78e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190221204921-83362c3779f5/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.0.0-20181220000619-583d854617af/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181109154231-b5d43981345b/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
google.golang.org/genproto v0.0.0-20181219182458-5a97ab628bfb/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922/go.mod h1:L3J43x8/uS+qIUoksaLKe6OS3nUKxOKuIFz1sl2/jx4=
google.golang.org/genproto v0.0.0-20190219182410-082222b4a5c5/go.mod h1:L3J43x8/uS+qIUoksaLKe6OS3nUKxOKuIFz1sl2/jx4=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190215041234-466a0476246c/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
sourcegraph.com/sqs/pbtypes v1.0.0/go.mod h1:3AciMUv4qUuRHRHhOG4TZOB+72GdPVz5k+c648qsFS4=
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=

View File

@@ -1,8 +1,8 @@
package wails
import (
"encoding/hex"
"encoding/json"
"strings"
)
// ipcResponse contains the response data from an RPC call
@@ -37,7 +37,9 @@ func newSuccessResponse(callbackID string, data interface{}) *ipcResponse {
// Serialise formats the response to a string
func (i *ipcResponse) Serialise() (string, error) {
b, err := json.Marshal(i)
result := strings.Replace(string(b), "\\", "\\\\", -1)
result = strings.Replace(result, "'", "\\'", -1)
if err != nil {
return "", err
}
result := hex.EncodeToString(b)
return result, err
}

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"net/http"
"strings"
"sync"
"github.com/dchest/htmlmin"
"github.com/gorilla/websocket"
@@ -45,6 +46,9 @@ type Headless struct {
initialisationJS []string
server *http.Server
theConnection *websocket.Conn
// Mutex for writing to the socket
lock sync.Mutex
}
// Initialise the Headless Renderer
@@ -53,7 +57,7 @@ func (h *Headless) Initialise(appConfig *AppConfig, ipcManager *ipcManager, even
h.appConfig = appConfig
h.eventManager = eventManager
ipcManager.bindRenderer(h)
h.log = newCustomLogger("Headless")
h.log = newCustomLogger("Bridge")
return nil
}
@@ -103,6 +107,10 @@ func (h *Headless) wsBridgeHandler(w http.ResponseWriter, r *http.Request) {
}
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 {
h.log.Error(err.Error())
}
@@ -145,8 +153,8 @@ func (h *Headless) Run() error {
h.server = &http.Server{Addr: ":34115"}
http.HandleFunc("/bridge", h.wsBridgeHandler)
h.log.Info("Headless mode started.")
h.log.Info("The Wails bridge will connect automatically.")
h.log.Info("Bridge mode started.")
h.log.Info("The frontend will connect automatically.")
err := h.server.ListenAndServe()
if err != nil {
@@ -164,21 +172,21 @@ func (h *Headless) NewBinding(methodName string) error {
// SelectFile is unsupported for Headless but required
// for the Renderer interface
func (h *Headless) SelectFile() string {
h.log.Error("SelectFile() unsupported in headless mode")
h.log.Warn("SelectFile() unsupported in bridge mode")
return ""
}
// SelectDirectory is unsupported for Headless but required
// for the Renderer interface
func (h *Headless) SelectDirectory() string {
h.log.Error("SelectDirectory() unsupported in headless mode")
h.log.Warn("SelectDirectory() unsupported in bridge mode")
return ""
}
// SelectSaveFile is unsupported for Headless but required
// for the Renderer interface
func (h *Headless) SelectSaveFile() string {
h.log.Error("SelectSaveFile() unsupported in headless mode")
h.log.Warn("SelectSaveFile() unsupported in bridge mode")
return ""
}
@@ -237,23 +245,23 @@ func (h *Headless) SetColour(colour string) error {
// Fullscreen is unsupported for Headless but required
// for the Renderer interface
func (h *Headless) Fullscreen() {
h.log.Warn("Fullscreen() unsupported in headless mode")
h.log.Warn("Fullscreen() unsupported in bridge mode")
}
// UnFullscreen is unsupported for Headless but required
// for the Renderer interface
func (h *Headless) UnFullscreen() {
h.log.Warn("UnFullscreen() unsupported in headless mode")
h.log.Warn("UnFullscreen() unsupported in bridge mode")
}
// SetTitle is currently unsupported for Headless but required
// for the Renderer interface
func (h *Headless) SetTitle(title string) {
h.log.WarnFields("SetTitle() unsupported in headless mode", Fields{"title": title})
h.log.WarnFields("SetTitle() unsupported in bridge mode", Fields{"title": title})
}
// Close is unsupported for Headless but required
// for the Renderer interface
func (h *Headless) Close() {
h.log.Warn("Close() unsupported in headless mode")
h.log.Warn("Close() unsupported in bridge mode")
}

View File

@@ -122,7 +122,7 @@ func (w *webViewRenderer) evalJSSync(js string) error {
go func() {
exit := false
// We are done when we recieve the Callback ID
// We are done when we receive the Callback ID
w.log.Debug("SyncJS: sending with ID = " + ID)
w.eventManager.On(ID, func(...interface{}) {
w.log.Debug("SyncJS: Got callback ID = " + ID)

View File

@@ -2,17 +2,19 @@ package wails
// Runtime is the Wails Runtime Interface, given to a user who has defined the WailsInit method
type Runtime struct {
Events *RuntimeEvents
Log *RuntimeLog
Dialog *RuntimeDialog
Window *RuntimeWindow
Events *RuntimeEvents
Log *RuntimeLog
Dialog *RuntimeDialog
Window *RuntimeWindow
FileSystem *RuntimeFileSystem
}
func newRuntime(eventManager *eventManager, renderer Renderer) *Runtime {
return &Runtime{
Events: newRuntimeEvents(eventManager),
Log: newRuntimeLog(),
Dialog: newRuntimeDialog(renderer),
Window: newRuntimeWindow(renderer),
Events: newRuntimeEvents(eventManager),
Log: newRuntimeLog(),
Dialog: newRuntimeDialog(renderer),
Window: newRuntimeWindow(renderer),
FileSystem: newRuntimeFileSystem(),
}
}

View File

@@ -18,5 +18,5 @@ func (r *RuntimeEvents) On(eventName string, callback func(optionalData ...inter
// Emit pass through
func (r *RuntimeEvents) Emit(eventName string, optionalData ...interface{}) {
r.eventManager.Emit(eventName, optionalData)
r.eventManager.Emit(eventName, optionalData...)
}

16
runtime_filesystem.go Normal file
View File

@@ -0,0 +1,16 @@
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()
}

15
scripts/updateversion.sh Executable file
View File

@@ -0,0 +1,15 @@
#!/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

View File

@@ -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>',
overlayCSS:
".wails-reconnect-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.6);font-family:sans-serif;display:none;z-index:999999}.wails-reconnect-overlay-content{padding:20px 30px;text-align:center;width:20em;position:relative;height:14em;border-radius:1em;margin:5% auto 0;background-color:#fff;box-shadow:1px 1px 20px 3px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC8AAAAuCAMAAACPpbA7AAAAqFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQAAAAAAAAEBAQAAAAAAAAAAAAEBAQEBAQDAwMBAQEAAAABAQEAAAAAAAAAAAABAQEAAAAAAAACAgICAgIBAQEAAAAAAAAAAAAAAAAAAAAAAAABAQEAAAACAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBQWKCj6oAAAAN3RSTlMALiIqDhkGBAswJjP0GxP6NR4W9/ztjRDMhWU50G9g5eHXvbZ9XEI9xZTcqZl2aldKo55QwoCvZUgzhAAAAs9JREFUSMeNleeWqjAUhU0BCaH3Itiw9zKT93+zG02QK1hm/5HF+jzZJ6fQe6cyXE+jg9X7o9wxuylIIf4Tv2V3+bOrEXnf8dwQ/KQIGDN2/S+4OmVCVXL/ScBnfibxURqIByP/hONE8r8T+bDMlQ98KSl7Y8hzjpS8v1qtDh8u5f8KQpGpfnPPhqG8JeogN37Hq9eaN2xRhIwAaGnvws8F1ShxqK5ob2twYi1FAMD4rXsYtnC/JEiRbl4cUrCWhnMCLRFemXezXbb59QK4WASOsm6n2W1+4CBT2JmtzQ6fsrbGubR/NFbd2g5Y179+5w/GEHaKsHjYCet7CgrXU3txarNC7YxOVJtIj4/ERzMdZfzc31hp+8cD6eGILgarZY9uZ12hAs03vfBD9C171gS5Omz7OcvxALQIn4u8RRBBBcsi9WW2woO9ipLgfzpYlggg3ZRdROUC8KT7QLqq3W9KB5BbdFVg4929kdwp6+qaZnMCCNBdj+NyN1W885Ry/AL3D4AQbsVV4noCiM/C83kyYq80XlDAYQtralOiDzoRAHlotWl8q2tjvYlOgcg1A8jEApZa+C06TBdAz2Qv0wu11I/zZOyJQ6EwGez2P2b8PIQr1hwwnAZsAxwA4UAYOyXUxM/xp6tHAn4GUmPGM9R28oVxgC0e/zQJJI6DyhyZ1r7uzRQhpcW7x7vTaWSzKSG6aep77kroTEl3U81uSVaUTtgEINfC8epx+Q4F9SpplHG84Ek6m4RAq9/TLkOBrxyeuddZhHvGIp1XXfFy3Z3vtwNblKGiDn+J+92vwwABHghj7HnzlS1H5kB49AZvdGCFgiBPq69qfXPr3y++yilF0ON4R8eR7spAsLpZ95NqAW5tab1c4vkZm6aleajchMwYTdILQQTwE2OV411ZM9WztDjPql12caBi6gDpUKmDd4U1XNdQxZ4LIXQ5/Tr4P7I9tYcFrDK3AAAAAElFTkSuQmCC);background-repeat:no-repeat;background-position:center}.wails-reconnect-overlay-title{font-size:2em}.wails-reconnect-overlay-message{font-size:1.3em}.wails-reconnect-overlay-loadingspinner{pointer-events:none;width:2.5em;height:2.5em;border:.4em solid transparent;border-color:#3E67EC #eee #eee;border-radius:50%;animation:loadingspin 1s linear infinite;margin:auto;padding:2.5em}@keyframes loadingspin{100%{transform:rotate(360deg)}}",
log: function(message) {
log: function (message) {
// eslint-disable-next-line
console.log(
"%c wails bridge %c " + message + " ",
@@ -102,7 +102,7 @@ function startBridge() {
// Bridge external.invoke
window.external = {
invoke: function(msg) {
invoke: function (msg) {
window.wailsbridge.websocket.send(msg);
}
};
@@ -111,6 +111,7 @@ function startBridge() {
// Removes it if second parameter is true.
function addScript(script, remove) {
var s = document.createElement("script");
s.setAttribute('type', 'text/javascript');
s.textContent = script;
document.head.appendChild(s);
@@ -142,11 +143,11 @@ function startBridge() {
// Try to connect to the backend every 300ms (default value).
// Change this value in the main wailsbridge object.
function connect() {
window.wailsbridge.connectTimer = setInterval(function() {
window.wailsbridge.connectTimer = setInterval(function () {
if (window.wailsbridge.websocket == null) {
window.wailsbridge.websocket = new WebSocket(window.wailsbridge.wsURL);
window.wailsbridge.websocket.onopen = handleConnect;
window.wailsbridge.websocket.onerror = function(e) {
window.wailsbridge.websocket.onerror = function (e) {
e.stopImmediatePropagation();
e.stopPropagation();
e.preventDefault();
@@ -159,7 +160,6 @@ function startBridge() {
function handleMessage(message) {
// As a bridge we ignore js and css injections
switch (message.data[0]) {
// Wails library - inject!
case "w":
@@ -167,7 +167,7 @@ function startBridge() {
// Now wails runtime is loaded, wails for the ready event
// 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");
if (window.wailsbridge.callback) {
window.wailsbridge.log("Notifying application");
@@ -189,7 +189,6 @@ function startBridge() {
// Call back
case "c":
var callbackData = message.data.slice(1);
window.wailsbridge.log("Callback = " + callbackData);
window.wails._.callback(callbackData);
break;
}
@@ -205,7 +204,7 @@ function startBridge() {
export default {
// The main function
// Passes the main Wails object to the callback if given.
Start: function(callback) {
Start: function (callback) {
// Save the callback
window.wailsbridge.callback = callback;

View File

@@ -0,0 +1,40 @@
(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");})();
(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!0}catch(e){return!1}}
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){incomingMessage=decodeURIComponent(incomingMessage.replace(/\s+/g,'').replace(/[0-9a-f]{2}/g,'%$&'));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")})()

View File

@@ -1 +1 @@
(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");})();
!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={};var i={};function r(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){i[e]=i[e]||[],i[e].push(n)}},window.wails.log={debug:function(e){r("debug",e)},info:function(e){r("info",e)},warning:function(e){r("warning",e)},error:function(e){r("error",e)},fatal:function(e){r("fatal",e)}},window.wails._={newBinding:function(i){var r,l=i.split(".").splice(1),o=l.pop(),c=function(e){var t=a;for(var i in e){var r=e[i];if(!n(r))return[null,new Error(r+" is not a valid javascript identifier.")];t[r]||(t[r]={}),t=t[r]}return[t,null]}(l),s=c[0];if(null!=(r=c[1]))return r;s[o]=function(){var n=0;function a(){var a=[].slice.call(arguments);return function(n,a,i){return null!=i&&null!=i||(i=0),new Promise(function(r,l){var o;do{o=n+"-"+e()}while(t[o]);if(i>0)var c=setTimeout(function(){l(Error("Call to "+n+" timed out. Request ID: "+o))},i);t[o]={timeoutHandle:c,reject:l,resolve:r};try{var s=JSON.stringify(a);message={type:"call",callbackid:o,payload:{bindingName:n,data:s}};var u=JSON.stringify(message);external.invoke(u)}catch(e){console.error(e)}})}(i,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){i[e]&&i[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:r,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")}();

View File

@@ -10,8 +10,8 @@
function cryptoRandom() {
var array = new Uint32Array(1);
return window.crypto.getRandomValues(array)[0];
}
}
// LOLRandom
function basicRandom() {
@@ -203,6 +203,10 @@
// Called by the backend to return data to a previously called
// binding invocation
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
var message;
try {
@@ -243,7 +247,7 @@
// notify informs frontend listeners that an event was emitted with the given data
function notify(eventName, data) {
if (eventListeners[eventName]) {
eventListeners[eventName].forEach(function(element) {
eventListeners[eventName].forEach(function (element) {
var parsedData = [];
// Parse data if we have it
if (data) {
@@ -332,8 +336,8 @@
callbacks: callbacks,
injectCSS: injectCSS,
addScript: addScript,
}
}
/************************************************************/