Compare commits

...

106 Commits

Author SHA1 Message Date
Lea Anthony
9164bf17c0 chore: hotfix 2019-07-31 06:56:12 +10:00
Lea Anthony
bb86d770a1 fix: gitbash fixes 2019-07-31 06:54:07 +10:00
Lea Anthony
33daa8621e chore: version bump 2019-07-31 06:21:00 +10:00
Lea Anthony
6c124fcff4 Merge pull request #175 from bh90210/174-wails-init-does-not-work-on-centos-7
fixed centos & fedora support
2019-07-31 06:17:42 +10:00
Lea Anthony
45833574b3 Merge branch 'bh90210-169-improve-wails-issue' into develop 2019-07-31 06:09:12 +10:00
Lea Anthony
5cb00eb481 trim gcc string 2019-07-31 06:08:43 +10:00
Lea Anthony
e2105331c1 Merge branch '169-improve-wails-issue' of git://github.com/bh90210/wails into bh90210-169-improve-wails-issue 2019-07-31 06:02:41 +10:00
bh90210
21d2383e63 Merge branch '169-improve-wails-issue' of github.com:bh90210/wails into 169-improve-wails-issue 2019-07-30 16:11:51 +03:00
bh90210
6c945a4eed fix: crashing typo 2019-07-30 16:11:18 +03:00
admin_3.exe
6c8d34dfd3 Delete npm-debug.log 2019-07-30 16:00:16 +03:00
bh90210
b9b42c059e feat: show gcc, node, npm version on issue report 2019-07-30 15:57:51 +03:00
bh90210
3f657b34cf darwin working 2019-07-30 02:12:51 +03:00
bh90210
6e81a36ada linux working 2019-07-30 02:02:01 +03:00
bh90210
ddec01a429 feat: gcc,npm,node versions on issues 2019-07-29 23:53:43 +03:00
bh90210
21fdb3be7d fix(linux): fedora & centos support 2019-07-29 19:12:05 +03:00
admin_3.exe
c1a13ab6d0 Merge pull request #2 from wailsapp/develop
Develop
2019-07-29 16:09:33 +03:00
Lea Anthony
750a02efc6 chore: version bump 2019-07-29 17:54:41 +10:00
Lea Anthony
5e047debfc fix: add support back for ubuntu, redhat 2019-07-29 17:52:22 +10:00
Lea Anthony
9cac336708 docs: updated contributors 2019-07-29 09:03:17 +10:00
Lea Anthony
827c2b9a95 Merge pull request #172 from Chronophylos/dont-use-lsb_release
Drop lsb_release
2019-07-29 09:01:41 +10:00
Chronophylos
b36a3c4abb fix assumption
Signed-off-by: Chronophylos <nikolai@chronophylos.com>
2019-07-28 13:39:03 +02:00
Chronophylos
0bac205565 show distro id when creating a issue
Signed-off-by: Chronophylos <nikolai@chronophylos.com>
2019-07-28 13:16:56 +02:00
Chronophylos
67a8ad8e12 change DistributionID to NAME=
Signed-off-by: Chronophylos <nikolai@chronophylos.com>
2019-07-28 00:44:46 +02:00
Chronophylos
9de2f66f50 drop lsb_release
Signed-off-by: Chronophylos <nikolai@chronophylos.com>
2019-07-27 21:26:11 +02:00
admin_3.exe
9370030ff3 Merge pull request #1 from wailsapp/develop
Develop
2019-07-27 22:12:15 +03:00
Lea Anthony
e38d6e7ef0 Merge pull request #165 from bt/master
Fix Masterminds/semver reference import path (case-sensitivity)
2019-07-22 18:33:54 +10:00
Bertram Truong
2f21fc3575 Fix Masterminds/semver reference import path (case-sensitivity) 2019-07-22 10:25:23 +10:00
Lea Anthony
63e73f5f64 chore: Version Bump 2019-07-20 19:40:43 +10:00
Lea Anthony
e1adc1ba49 Merge pull request #163 from wailsapp/more-runtime-refactor
More runtime refactor
2019-07-20 19:35:59 +10:00
Lea Anthony
030e911ea4 feat: significant overhaul of runtime 2019-07-20 19:32:30 +10:00
Lea Anthony
d2f114e44e Update contributors 2019-07-19 08:08:26 +10:00
Lea Anthony
700d3f84d3 Merge pull request #161 from fdidron/145-Fix-React-Error-Windows
145 fix react error windows
2019-07-19 00:32:20 +10:00
Florian Didron
1d49042013 style: replace double quotes with single quotes 2019-07-18 21:46:25 +09:00
Florian Didron
8671b1e6cf fix: add promises polyfill for the windows target 2019-07-18 21:10:42 +09:00
Lea Anthony
517d6c44ec fix: Print stdout on error :rolleyes: 2019-07-18 09:12:57 +10:00
Lea Anthony
a082a659ea fix: renamed global logger 2019-07-16 18:29:15 +10:00
Lea Anthony
083153efc9 fix: eslintrc config 2019-07-13 22:32:19 +10:00
Lea Anthony
65a2560153 chore: bump version 2019-07-13 22:30:32 +10:00
Lea Anthony
29535c10a3 Merge pull request #157 from wailsapp/runtime-refactor
Runtime refactor
2019-07-13 22:27:36 +10:00
Lea Anthony
24c7362163 Even more fixes 2019-07-13 22:18:42 +10:00
Lea Anthony
f6ff7d7b16 fix: linting for hound 2019-07-13 22:12:49 +10:00
Lea Anthony
b0a075cdf2 fix: more lint fixes 2019-07-13 22:10:43 +10:00
Lea Anthony
98d4d6b33c config: eslint 2019-07-13 15:42:57 +10:00
Lea Anthony
9ba3e0512b fix: linting 2019-07-13 15:35:50 +10:00
Lea Anthony
eff63175e5 fix: lint 2019-07-13 15:34:00 +10:00
Lea Anthony
75a0b632bc fix: capitalisation and binding fix 2019-07-13 15:30:52 +10:00
Lea Anthony
a2af626477 fix: config errors 2019-07-12 10:22:19 +10:00
Lea Anthony
8aa97f64ef feat: major refactor 2019-07-12 10:12:15 +10:00
Lea Anthony
caa1e04b5a Update README.md 2019-07-08 21:29:59 +10:00
Lea Anthony
cddf6a0204 chore: version bump 2019-07-07 10:28:58 +10:00
Lea Anthony
9fa1f42dc7 Merge pull request #155 from wailsapp/154-Support-Distribution-'Fedora'
feat: test support for Fedora
2019-07-07 10:28:19 +10:00
Lea Anthony
c7e709d487 feat: test support for Fedora 2019-07-07 10:25:59 +10:00
Lea Anthony
6801398f3d docs: update contributors 2019-07-07 10:17:44 +10:00
Lea Anthony
982d14c049 Merge pull request #152 from fallendusk/master
Add support for Gentoo
2019-07-07 10:16:21 +10:00
fallendusk
ddbaf55ae7 Merge branch 'develop' into master 2019-07-06 17:31:21 -04:00
Greg Helton
5552a8501b Add support for Gentoo 2019-07-06 01:43:02 -04:00
Lea Anthony
b997becb2f chore: bump version 2019-07-03 19:47:03 +10:00
Lea Anthony
753516bab7 Merge pull request #149 from wailsapp/148-Support-Distribution-'Zorin'
148 support distribution 'zorin'
2019-07-03 19:46:20 +10:00
Lea Anthony
89992d8636 feat: attempt to support Zorin 2019-07-03 19:42:32 +10:00
Lea Anthony
7dd42f964b Merge pull request #147 from wailsapp/develop
Release v0.17.0
2019-07-02 17:39:41 +10:00
Lea Anthony
078a7a5519 feat: release v0.17.0 2019-07-02 17:38:18 +10:00
Lea Anthony
d811f721ac docs: be explicit about node version 2019-07-01 21:50:16 +10:00
Lea Anthony
26950ba045 chore: version bump 2019-07-01 21:36:07 +10:00
Lea Anthony
80adb70e78 chore: version bump 2019-07-01 21:35:30 +10:00
Lea Anthony
0c042acd4a fix: template name order 2019-07-01 21:35:06 +10:00
Lea Anthony
0ad0c4151a feat: use slicer v1.3.2 2019-07-01 18:27:10 +10:00
Lea Anthony
65a8a1e1f7 feat: sort templates by name 2019-07-01 18:26:24 +10:00
Lea Anthony
a2ac8af882 chore: Bump to version v0.16.5-pre 2019-07-01 18:10:26 +10:00
Lea Anthony
52afbd3f15 fix: revert back to my-app 2019-07-01 09:01:07 +10:00
Lea Anthony
ce35ee5ca8 Merge branch 'bh90210-118-angular-support' into develop 2019-07-01 08:58:37 +10:00
Lea Anthony
74c64c6420 chore: misc updates for template 2019-07-01 08:57:42 +10:00
Lea Anthony
678328b7aa Merge branch '118-angular-support' of git://github.com/bh90210/wails into bh90210-118-angular-support 2019-06-30 18:11:35 +10:00
Lea Anthony
345c8bc094 fix: linting fixes 2019-06-30 17:16:38 +10:00
Lea Anthony
44386490c8 chore: add default case to bridge switch 2019-06-29 23:03:46 +10:00
bh90210
87158a342a feat: angular template 2019-06-29 15:45:48 +03:00
Lea Anthony
0b43fae32a docs: updated contributors 2019-06-29 21:43:19 +10:00
Lea Anthony
89f7a95167 Merge pull request #141 from wailsapp/138-Template-dependency-checker
feat: initial support for template dependencies
2019-06-27 19:56:57 +10:00
Lea Anthony
c5be3e5634 feat: initial support for template dependencies 2019-06-27 09:05:46 +10:00
Lea Anthony
7156740f6c fix: typo 2019-06-27 08:46:01 +10:00
Lea Anthony
2d29b626c7 chore: version bump 2019-06-26 19:50:22 +10:00
Lea Anthony
698145be1e Merge pull request #140 from wailsapp/139-go.mod-should-reflect-current-wails-version
feat: set wails version in go.mod
2019-06-26 19:48:35 +10:00
Lea Anthony
a9188cbfdd feat: set wails version in go.mod 2019-06-26 19:46:51 +10:00
Lea Anthony
d07cca0278 chore: version bump 2019-06-25 18:49:18 +10:00
Lea Anthony
60d1dc51ad Merge pull request #137 from wailsapp/135-Add-Debian-support
135 add debian support
2019-06-25 18:48:24 +10:00
Lea Anthony
105073e412 fix: add Debian support across tooling 2019-06-25 18:32:25 +10:00
Lea Anthony
9d1f1fff47 feat: debian support 2019-06-25 18:29:57 +10:00
Lea Anthony
08050ec35e Merge pull request #134 from wailsapp/133-Unsupported-Platform-Requests
133 unsupported platform requests
2019-06-25 08:18:06 +10:00
Lea Anthony
bd9751d888 feat: Support distribution support requests 2019-06-25 08:13:20 +10:00
Lea Anthony
7d171b0907 feat: initial support for platform requests 2019-06-24 09:11:06 +10:00
Lea Anthony
5b8f311465 Merge pull request #130 from wailsapp/123-Unify-Runtime-APIs
fix: linting
2019-06-22 08:47:25 +10:00
Lea Anthony
801465ac51 fix: linting 2019-06-22 08:45:46 +10:00
Lea Anthony
a84e2ae9b3 Merge pull request #129 from wailsapp/123-Unify-Runtime-APIs
feat: unify runtime API signatures
2019-06-22 08:43:23 +10:00
Lea Anthony
9496d1d47f Merge pull request #126 from bh90210/121-react-template-build-error
fix(react template): reverting bugfix + code clean-up
2019-06-22 08:39:16 +10:00
Lea Anthony
36e575e0a2 feat: unify runtime API signatures 2019-06-22 08:36:11 +10:00
ktc
70ccb8942b fix(react template): reverting bugfix + code clean-up 2019-06-19 20:09:23 +03:00
Lea Anthony
d3cd3d43bd chore: version bump 2019-06-19 21:04:27 +10:00
Lea Anthony
9116f0d06c Merge pull request #124 from wailsapp/116-Add-browser-methods-to-runtime
116 add browser methods to runtime
2019-06-19 21:01:53 +10:00
Lea Anthony
2c91e26add docs: guardrails badge 2019-06-19 21:01:00 +10:00
Lea Anthony
f1647443dc chore: add .jshintrc file to indicate es6 2019-06-19 20:54:36 +10:00
Lea Anthony
b6b6ce2d4a fix: linting fix 2019-06-19 20:53:04 +10:00
Lea Anthony
abcc869537 feat: added OpenFile 2019-06-19 20:49:39 +10:00
Lea Anthony
3e02e1676a Merge pull request #122 from bh90210/121-react-template-build-error
fix(react template): build bugfix
2019-06-19 08:31:57 +10:00
Lea Anthony
5c8a4de446 fix: version 2019-06-19 08:29:15 +10:00
Lea Anthony
7cabef946e feat: initial support for browser.openURL for f/e 2019-06-19 08:28:31 +10:00
ktc
f2519e5af2 fix(react template): build bugfix 2019-06-18 13:57:45 +03:00
Lea Anthony
63f1767755 Merge pull request #120 from wailsapp/develop
Release v0.16.0
2019-06-18 08:25:24 +10:00
153 changed files with 11064 additions and 1415 deletions

View File

@@ -1,42 +0,0 @@
{{ if .Versions -}}
<a name="unreleased"></a>
## [Unreleased]
{{ if .Unreleased.CommitGroups -}}
{{ range .Unreleased.CommitGroups -}}
### {{ .Title }}
{{ range .Commits -}}
- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }}
{{ end }}
{{ end -}}
{{ end -}}
{{ end -}}
{{ range .Versions }}
<a name="{{ .Tag.Name }}"></a>
## {{ if .Tag.Previous }}[{{ .Tag.Name }}]{{ else }}{{ .Tag.Name }}{{ end }} - {{ datetime "2006-01-02" .Tag.Date }}
{{ range .CommitGroups -}}
### {{ .Title }}
{{ range .Commits -}}
- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }}
{{ end }}
{{ end -}}
{{- if .NoteGroups -}}
{{ range .NoteGroups -}}
### {{ .Title }}
{{ range .Notes }}
{{ .Body }}
{{ end }}
{{ end -}}
{{ end -}}
{{ end -}}
{{- if .Versions }}
[Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ $latest := index .Versions 0 }}{{ $latest.Tag.Name }}...HEAD
{{ range .Versions -}}
{{ if .Tag.Previous -}}
[{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }}
{{ end -}}
{{ end -}}
{{ end -}}

View File

@@ -1,27 +0,0 @@
style: github
template: CHANGELOG.tpl.md
info:
title: CHANGELOG
repository_url: https://github.com/wailsapp/wails
options:
commits:
# filters:
# Type:
# - feat
# - fix
# - perf
# - refactor
commit_groups:
# title_maps:
# feat: Features
# fix: Bug Fixes
# perf: Performance Improvements
# refactor: Code Refactoring
header:
pattern: "^(\\w*)\\:\\s(.*)$"
pattern_maps:
- Type
- Subject
notes:
keywords:
- BREAKING CHANGE

1
.eslintignore Normal file
View File

@@ -0,0 +1 @@
runtime/assets/default.html

30
.eslintrc Normal file
View File

@@ -0,0 +1,30 @@
{
"env": {
"browser": true,
"es6": true,
"node": true,
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaVersion": 2016,
"sourceType": "module",
},
"rules": {
"indent": [
"error",
"tab"
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"single"
],
"semi": [
"error",
"always"
]
}
}

2
.gitignore vendored
View File

@@ -16,4 +16,4 @@ examples/**/example*
cmd/wails/wails cmd/wails/wails
.DS_Store .DS_Store
tmp tmp
dist node_modules/

6
.hound.yml Normal file
View File

@@ -0,0 +1,6 @@
jshint:
config_file: .jshintrc
eslint:
enabled: true
config_file: .eslintrc
ignore_file: .eslintignore

3
.jshintrc Normal file
View File

@@ -0,0 +1,3 @@
{
"esversion": 6
}

View File

@@ -1,3 +1,4 @@
{ {
"go.formatTool": "goimports" "go.formatTool": "goimports",
"eslint.alwaysShowStatus": true
} }

View File

@@ -1,3 +1,9 @@
2019-07-20 **v0.17.6-pre**
* Significant refactor of runtime
* Removed wailsbridge file - now a unified approach taken
* Fixed React on Windows - Thanks [Florian Didran](https://github.com/fdidron)!
2019-06-18 **v0.16.0** 2019-06-18 **v0.16.0**
* React template FTW! - Thanks [admin_3.exe](https://github.com/bh90210)! * React template FTW! - Thanks [admin_3.exe](https://github.com/bh90210)!
* Updated contributors * Updated contributors

View File

@@ -12,3 +12,7 @@ Wails is what it is because of the time and effort given by these great people.
* [intelwalk](https://github.com/intelwalk) * [intelwalk](https://github.com/intelwalk)
* [Mark Stenglein](https://github.com/ocelotsloth) * [Mark Stenglein](https://github.com/ocelotsloth)
* [admin_3.exe](https://github.com/bh90210) * [admin_3.exe](https://github.com/bh90210)
* [iceleo-com](https://github.com/iceleo-com)
* [fallendusk](https://github.com/fallendusk)
* [Florian Didran](https://github.com/fdidron)
* [Nikolai Zimmermann](https://github.com/Chronophylos)

View File

@@ -10,6 +10,7 @@
<a href="https://github.com/wailsapp/wails/issues"><img src="https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat" alt="CodeFactor" /></a> <a href="https://github.com/wailsapp/wails/issues"><img src="https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat" alt="CodeFactor" /></a>
<a href="https://houndci.com"><img src="https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg"/></a> <a href="https://houndci.com"><img src="https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg"/></a>
<a href="https://github.com/avelino/awesome-go" rel="nofollow"><img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome"></a> <a href="https://github.com/avelino/awesome-go" rel="nofollow"><img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome"></a>
<a href="https://dashboard.guardrails.io/default/gh/wailsapp/wails"><img src="https://badges.guardrails.io/wailsapp/wails.svg?token=53657bc22ec360d7673c894fdd70568e918ec581d10d84427ed4de5fe1eeff1a"></a>
</p> </p>
The traditional method of providing web interfaces to Go programs is via a built-in web server. Wails offers a different approach: it provides the ability to wrap both Go code and a web frontend into a single binary. Tools are provided to make this easy for you by handling project creation, compilation and bundling. All you have to do is get creative! The traditional method of providing web interfaces to Go programs is via a built-in web server. Wails offers a different approach: it provides the ability to wrap both Go code and a web frontend into a single binary. Tools are provided to make this easy for you by handling project creation, compilation and bundling. All you have to do is get creative!
@@ -45,19 +46,21 @@ Make sure you have the xcode command line tools installed. This can be done by r
### Linux ### Linux
#### Ubuntu 18.04 #### Ubuntu 18.04, Debian 9, Zorin 15
`sudo apt install pkg-config build-essential libgtk-3-dev libwebkit2gtk-4.0-dev` `sudo apt install libgtk-3-dev libwebkit2gtk-4.0-dev`
#### Arch Linux #### Arch Linux
`sudo pacman -S webkit2gtk gtk3` `sudo pacman -S webkit2gtk gtk3`
#### Red Hat Based Distros #### Fedora 30
`sudo yum install webkit2gtk-devel gtk3-devel` `sudo yum install webkit2gtk3-devel gtk3-devel`
Note: If you have successfully installed these dependencies on a different flavour of Linux, please consider submitting a PR. #### Centos 7
`sudo yum install webkitgtk3-devel gtk3-devel`
### Windows ### Windows
@@ -120,4 +123,3 @@ This project was mainly coded to the following albums:
* [Bloc Party - Silent Alarm](https://open.spotify.com/album/6SsIdN05HQg2GwYLfXuzLB) * [Bloc Party - Silent Alarm](https://open.spotify.com/album/6SsIdN05HQg2GwYLfXuzLB)
* [Maxthor - Another World](https://open.spotify.com/album/3tklE2Fgw1hCIUstIwPBJF) * [Maxthor - Another World](https://open.spotify.com/album/3tklE2Fgw1hCIUstIwPBJF)
* [Alun Tan Lan - Y Distawrwydd](https://open.spotify.com/album/0c32OywcLpdJCWWMC6vB8v) * [Alun Tan Lan - Y Distawrwydd](https://open.spotify.com/album/0c32OywcLpdJCWWMC6vB8v)

52
app.go
View File

@@ -2,6 +2,12 @@ package wails
import ( import (
"github.com/wailsapp/wails/cmd" "github.com/wailsapp/wails/cmd"
"github.com/wailsapp/wails/lib/binding"
"github.com/wailsapp/wails/lib/event"
"github.com/wailsapp/wails/lib/interfaces"
"github.com/wailsapp/wails/lib/ipc"
"github.com/wailsapp/wails/lib/logger"
"github.com/wailsapp/wails/lib/renderer"
) )
// -------------------------------- Compile time Flags ------------------------------ // -------------------------------- Compile time Flags ------------------------------
@@ -13,15 +19,15 @@ var BuildMode = cmd.BuildModeProd
// App defines the main application struct // App defines the main application struct
type App struct { type App struct {
config *AppConfig // The Application configuration object config *AppConfig // The Application configuration object
cli *cmd.Cli // In debug mode, we have a cli cli *cmd.Cli // In debug mode, we have a cli
renderer Renderer // The renderer is what we will render the app to renderer interfaces.Renderer // The renderer is what we will render the app to
logLevel string // The log level of the app logLevel string // The log level of the app
ipc *ipcManager // Handles the IPC calls ipc interfaces.IPCManager // Handles the IPC calls
log *CustomLogger // Logger log *logger.CustomLogger // Logger
bindingManager *bindingManager // Handles binding of Go code to renderer bindingManager interfaces.BindingManager // Handles binding of Go code to renderer
eventManager *eventManager // Handles all the events eventManager interfaces.EventManager // Handles all the events
runtime *Runtime // The runtime object for registered structs runtime interfaces.Runtime // The runtime object for registered structs
} }
// CreateApp creates the application window with the given configuration // CreateApp creates the application window with the given configuration
@@ -34,14 +40,14 @@ func CreateApp(optionalConfig ...*AppConfig) *App {
result := &App{ result := &App{
logLevel: "info", logLevel: "info",
renderer: &webViewRenderer{}, renderer: renderer.NewWebView(),
ipc: newIPCManager(), ipc: ipc.NewManager(),
bindingManager: newBindingManager(), bindingManager: binding.NewManager(),
eventManager: newEventManager(), eventManager: event.NewManager(),
log: newCustomLogger("App"), log: logger.NewCustomLogger("App"),
} }
appconfig, err := newAppConfig(userConfig) appconfig, err := newConfig(userConfig)
if err != nil { if err != nil {
result.log.Fatalf("Cannot use custom HTML: %s", err.Error()) result.log.Fatalf("Cannot use custom HTML: %s", err.Error())
} }
@@ -75,14 +81,14 @@ func (a *App) Run() error {
func (a *App) start() error { func (a *App) start() error {
// Set the log level // Set the log level
setLogLevel(a.logLevel) logger.SetLogLevel(a.logLevel)
// Log starup // Log starup
a.log.Info("Starting") a.log.Info("Starting")
// Check if we are to run in headless mode // Check if we are to run in bridge mode
if BuildMode == cmd.BuildModeBridge { if BuildMode == cmd.BuildModeBridge {
a.renderer = &Headless{} a.renderer = &renderer.Bridge{}
} }
// Initialise the renderer // Initialise the renderer
@@ -92,16 +98,16 @@ func (a *App) start() error {
} }
// Start event manager and give it our renderer // Start event manager and give it our renderer
a.eventManager.start(a.renderer) a.eventManager.Start(a.renderer)
// Start the IPC Manager and give it the event manager and binding manager // Start the IPC Manager and give it the event manager and binding manager
a.ipc.start(a.eventManager, a.bindingManager) a.ipc.Start(a.eventManager, a.bindingManager)
// Create the runtime // Create the runtime
a.runtime = newRuntime(a.eventManager, a.renderer) a.runtime = NewRuntime(a.eventManager, a.renderer)
// Start binding manager and give it our renderer // Start binding manager and give it our renderer
err = a.bindingManager.start(a.renderer, a.runtime) err = a.bindingManager.Start(a.renderer, a.runtime)
if err != nil { if err != nil {
return err return err
} }
@@ -113,5 +119,5 @@ func (a *App) start() error {
// Bind allows the user to bind the given object // Bind allows the user to bind the given object
// with the application // with the application
func (a *App) Bind(object interface{}) { func (a *App) Bind(object interface{}) {
a.bindingManager.bind(object) a.bindingManager.Bind(object)
} }

View File

@@ -1,97 +0,0 @@
package wails
import (
"strings"
"github.com/dchest/htmlmin"
"github.com/leaanthony/mewn"
)
// AppConfig is the configuration structure used when creating a Wails App object
type AppConfig struct {
Width, Height int
Title string
defaultHTML string
HTML string
JS string
CSS string
Colour string
Resizable bool
DisableInspector bool
isHTMLFragment bool
}
func (a *AppConfig) merge(in *AppConfig) error {
if in.CSS != "" {
a.CSS = in.CSS
}
if in.Title != "" {
a.Title = in.Title
}
if in.HTML != "" {
minified, err := htmlmin.Minify([]byte(in.HTML), &htmlmin.Options{
MinifyScripts: true,
})
if err != nil {
return err
}
inlineHTML := string(minified)
inlineHTML = strings.Replace(inlineHTML, "'", "\\'", -1)
inlineHTML = strings.Replace(inlineHTML, "\n", " ", -1)
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 HTML
// tag exists and is located before the first div tag
HTMLTagIndex := strings.Index(a.HTML, "<html")
DivTagIndex := strings.Index(a.HTML, "<div")
if HTMLTagIndex == -1 {
a.isHTMLFragment = true
} else {
if DivTagIndex < HTMLTagIndex {
a.isHTMLFragment = true
}
}
}
if in.Colour != "" {
a.Colour = in.Colour
}
if in.JS != "" {
a.JS = in.JS
}
if in.Width != 0 {
a.Width = in.Width
}
if in.Height != 0 {
a.Height = in.Height
}
a.Resizable = in.Resizable
a.DisableInspector = in.DisableInspector
return nil
}
// Creates the default configuration
func newAppConfig(userConfig *AppConfig) (*AppConfig, error) {
result := &AppConfig{
Width: 800,
Height: 600,
Resizable: true,
Title: "My Wails App",
Colour: "#FFF", // White by default
HTML: mewn.String("./wailsruntimeassets/default/default.html"),
}
if userConfig != nil {
err := result.merge(userConfig)
if err != nil {
return nil, err
}
}
return result, nil
}

View File

@@ -11,10 +11,9 @@ func (app *App) setupCli() *cmd.Cli {
result := cmd.NewCli(app.config.Title, "Debug build") result := cmd.NewCli(app.config.Title, "Debug build")
result.Version(cmd.Version) result.Version(cmd.Version)
// Setup cli to handle loglevel and headless flags // Setup cli to handle loglevel
result. result.
StringFlag("loglevel", "Sets the log level [debug|info|error|panic|fatal]. Default debug", &app.logLevel). StringFlag("loglevel", "Sets the log level [debug|info|error|panic|fatal]. Default debug", &app.logLevel).
// BoolFlag("headless", "Runs the app in headless mode", &app.headless).
Action(app.start) Action(app.start)
// Banner // Banner

10
cmd/cmd-mewn.go Normal file

File diff suppressed because one or more lines are too long

View File

@@ -9,7 +9,7 @@ import (
"runtime" "runtime"
"time" "time"
mewn "github.com/leaanthony/mewn" "github.com/leaanthony/mewn"
"github.com/leaanthony/slicer" "github.com/leaanthony/slicer"
"github.com/leaanthony/spinner" "github.com/leaanthony/spinner"
) )
@@ -249,8 +249,8 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
ioutil.WriteFile(md5sumFile, []byte(packageJSONMD5), 0644) ioutil.WriteFile(md5sumFile, []byte(packageJSONMD5), 0644)
} }
// Install the bridge library // Install the runtime
err = InstallBridge(caller, projectDir, projectOptions) err = InstallRuntime(caller, projectDir, projectOptions)
if err != nil { if err != nil {
return err return err
} }
@@ -263,22 +263,29 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
return nil return nil
} }
// InstallBridge installs the relevant bridge javascript library // InstallRuntime installs the correct runtime for the type of build
func InstallBridge(caller string, projectDir string, projectOptions *ProjectOptions) error { func InstallRuntime(caller string, projectDir string, projectOptions *ProjectOptions) error {
bridgeFile := "wailsbridge.prod.js" if caller == "build" {
if caller == "serve" { return InstallProdRuntime(projectDir, projectOptions)
bridgeFile = "wailsbridge.js"
} }
// Copy bridge to project return InstallBridge(projectDir, projectOptions)
bridgeAssets := mewn.Group("../wailsruntimeassets/bridge/") }
bridgeFileData := bridgeAssets.Bytes(bridgeFile)
bridgeFileTarget := filepath.Join(projectDir, projectOptions.FrontEnd.Dir, projectOptions.FrontEnd.Bridge, "wailsbridge.js") // InstallBridge installs the relevant bridge javascript library
err := fs.CreateFile(bridgeFileTarget, bridgeFileData) func InstallBridge(projectDir string, projectOptions *ProjectOptions) error {
if err != nil { bridgeFileData := mewn.String("../runtime/assets/bridge.js")
return err bridgeFileTarget := filepath.Join(projectDir, projectOptions.FrontEnd.Dir, "node_modules", "@wailsapp", "runtime", "main.js")
} err := fs.CreateFile(bridgeFileTarget, []byte(bridgeFileData))
return nil return err
}
// InstallProdRuntime installs the production runtime
func InstallProdRuntime(projectDir string, projectOptions *ProjectOptions) error {
prodInit := mewn.String("../runtime/js/runtime/init.js")
bridgeFileTarget := filepath.Join(projectDir, projectOptions.FrontEnd.Dir, "node_modules", "@wailsapp", "runtime", "main.js")
err := fs.CreateFile(bridgeFileTarget, []byte(prodInit))
return err
} }
// ServeProject attempts to serve up the current project so that it may be connected to // ServeProject attempts to serve up the current project so that it may be connected to

View File

@@ -3,9 +3,12 @@ package cmd
import ( import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/url"
"os" "os"
"regexp" "runtime"
"strings" "strings"
"github.com/pkg/browser"
) )
// LinuxDistribution is of type int // LinuxDistribution is of type int
@@ -20,78 +23,99 @@ const (
Arch Arch
// RedHat linux distribution // RedHat linux distribution
RedHat RedHat
// CentOS linux distribution
CentOS
// Fedora linux distribution
Fedora
// Debian distribution
Debian
// Gentoo distribution
Gentoo
// Zorin distribution
Zorin
) )
// DistroInfo contains all the information relating to a linux distribution // DistroInfo contains all the information relating to a linux distribution
type DistroInfo struct { type DistroInfo struct {
Distribution LinuxDistribution Distribution LinuxDistribution
Description string Name string
Release string ID string
Codename string Description string
DistributorID string Release string
DiscoveredBy string
} }
// GetLinuxDistroInfo returns information about the running linux distribution // GetLinuxDistroInfo returns information about the running linux distribution
func GetLinuxDistroInfo() *DistroInfo { func GetLinuxDistroInfo() *DistroInfo {
result := &DistroInfo{Distribution: Unknown} result := &DistroInfo{Distribution: Unknown}
program := NewProgramHelper()
// Does lsb_release exist?
lsbRelease := program.FindProgram("lsb_release") _, err := os.Stat("/etc/os-release")
if lsbRelease != nil { if !os.IsNotExist(err) {
stdout, _, _, err := lsbRelease.Run("-a") // Default value
if err != nil { osID := "unknown"
return result osNAME := "Unknown"
} version := ""
for _, line := range strings.Split(stdout, "\n") {
if strings.Contains(line, ":") {
// Iterate lines a
details := strings.Split(line, ":")
key := strings.TrimSpace(details[0])
value := strings.TrimSpace(details[1])
switch key {
case "Distributor ID":
result.DistributorID = value
switch value {
case "Ubuntu":
result.Distribution = Ubuntu
case "Arch", "ManjaroLinux":
result.Distribution = Arch
}
case "Description":
result.Description = value
case "Release":
result.Release = value
case "Codename":
result.Codename = value
}
}
}
// check if /etc/os-release exists
} else if _, err := os.Stat("/etc/os-release"); !os.IsNotExist(err) {
// read /etc/os-release // read /etc/os-release
osRelease, _ := ioutil.ReadFile("/etc/os-release") osRelease, _ := ioutil.ReadFile("/etc/os-release")
// compile a regex to find NAME=distro // Split into lines
re := regexp.MustCompile(`^NAME=(.*)\n`) lines := strings.Split(string(osRelease), "\n")
// extract the distro name // Iterate lines
osName := string(re.FindSubmatch(osRelease)[1]) for _, line := range lines {
// strip quotations // Split each line by the equals char
osName = strings.Trim(osName, "\"") splitLine := strings.SplitN(line, "=", 2)
// Check distro name against list of distros // Check we have
switch osName { if len(splitLine) != 2 {
case "Fedora": continue
result.Distribution = RedHat }
case "CentOS": switch splitLine[0] {
result.Distribution = RedHat case "ID":
case "Arch Linux": osID = strings.Trim(splitLine[1], "\"")
result.Distribution = Arch case "NAME":
osNAME = strings.Trim(splitLine[1], "\"")
case "VERSION_ID":
version = strings.Trim(splitLine[1], "\"")
}
} }
// Check distro name against list of distros
result.Release = version
result.DiscoveredBy = "/etc/os-release"
switch osID {
case "fedora":
result.Distribution = Fedora
case "centos":
result.Distribution = CentOS
case "arch":
result.Distribution = Arch
case "debian":
result.Distribution = Debian
case "ubuntu":
result.Distribution = Ubuntu
case "gentoo":
result.Distribution = Gentoo
case "zorin":
result.Distribution = Zorin
default:
result.Distribution = Unknown
}
result.ID = osID
result.Name = osNAME
} }
return result return result
} }
// EqueryInstalled uses equery to see if a package is installed
func EqueryInstalled(packageName string) (bool, error) {
program := NewProgramHelper()
equery := program.FindProgram("equery")
if equery == nil {
return false, fmt.Errorf("cannont check dependencies: equery not found")
}
_, _, exitCode, _ := equery.Run("l", packageName)
return exitCode == 0, nil
}
// DpkgInstalled uses dpkg to see if a package is installed // DpkgInstalled uses dpkg to see if a package is installed
func DpkgInstalled(packageName string) (bool, error) { func DpkgInstalled(packageName string) (bool, error) {
program := NewProgramHelper() program := NewProgramHelper()
@@ -124,3 +148,45 @@ func RpmInstalled(packageName string) (bool, error) {
_, _, exitCode, _ := rpm.Run("--query", packageName) _, _, exitCode, _ := rpm.Run("--query", packageName)
return exitCode == 0, nil return exitCode == 0, nil
} }
// RequestSupportForDistribution promts the user to submit a request to support their
// currently unsupported distribution
func RequestSupportForDistribution(distroInfo *DistroInfo, libraryName string) error {
var logger = NewLogger()
defaultError := fmt.Errorf("unable to check libraries on distribution '%s'. Please ensure that the '%s' equivalent is installed", distroInfo.Name, libraryName)
logger.Yellow("Distribution '%s' is not currently supported, but we would love to!", distroInfo.Name)
q := fmt.Sprintf("Would you like to submit a request to support distribution '%s'?", distroInfo.Name)
result := Prompt(q, "yes")
if strings.ToLower(result) != "yes" {
return defaultError
}
title := fmt.Sprintf("Support Distribution '%s'", distroInfo.Name)
var str strings.Builder
gomodule, exists := os.LookupEnv("GO111MODULE")
if !exists {
gomodule = "(Not Set)"
}
str.WriteString("\n| Name | Value |\n| ----- | ----- |\n")
str.WriteString(fmt.Sprintf("| Wails Version | %s |\n", Version))
str.WriteString(fmt.Sprintf("| Go Version | %s |\n", runtime.Version()))
str.WriteString(fmt.Sprintf("| Platform | %s |\n", runtime.GOOS))
str.WriteString(fmt.Sprintf("| Arch | %s |\n", runtime.GOARCH))
str.WriteString(fmt.Sprintf("| GO111MODULE | %s |\n", gomodule))
str.WriteString(fmt.Sprintf("| Distribution ID | %s |\n", distroInfo.ID))
str.WriteString(fmt.Sprintf("| Distribution Name | %s |\n", distroInfo.Name))
str.WriteString(fmt.Sprintf("| Distribution Version | %s |\n", distroInfo.Release))
str.WriteString(fmt.Sprintf("| Discovered by | %s |\n", distroInfo.DiscoveredBy))
body := fmt.Sprintf("**Description**\nDistribution '%s' is currently unsupported.\n\n**Further Information**\n\n%s\n\n*Please add any extra information here, EG: libraries that are needed to make the distribution work, or commands to install them*", distroInfo.ID, str.String())
fullURL := "https://github.com/wailsapp/wails/issues/new?"
params := "title=" + title + "&body=" + body
fmt.Println("Opening browser to file request.")
browser.OpenURL(fullURL + url.PathEscape(params))
return nil
}

View File

@@ -49,16 +49,30 @@ func getRequiredProgramsLinux() *Prerequisites {
result := &Prerequisites{} result := &Prerequisites{}
distroInfo := GetLinuxDistroInfo() distroInfo := GetLinuxDistroInfo()
switch distroInfo.Distribution { switch distroInfo.Distribution {
case Debian:
result.Add(newPrerequisite("gcc", "Please install with `sudo apt install build-essentials` and try again"))
result.Add(newPrerequisite("pkg-config", "Please install with `sudo apt install pkg-config` and try again"))
result.Add(newPrerequisite("npm", "Please install with `curl -sL https://deb.nodesource.com/setup_12.x | sudo bash - && sudo apt-get install -y nodejs` and try again"))
case Ubuntu: case Ubuntu:
result.Add(newPrerequisite("gcc", "Please install with `sudo apt install build-essentials` and try again"))
result.Add(newPrerequisite("pkg-config", "Please install with `sudo apt install pkg-config` and try again"))
result.Add(newPrerequisite("npm", "Please install with `curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - && sudo apt-get install -y nodejs` and try again"))
case Zorin:
result.Add(newPrerequisite("gcc", "Please install with `sudo apt install build-essentials` and try again")) result.Add(newPrerequisite("gcc", "Please install with `sudo apt install build-essentials` and try again"))
result.Add(newPrerequisite("pkg-config", "Please install with `sudo apt install pkg-config` and try again")) result.Add(newPrerequisite("pkg-config", "Please install with `sudo apt install pkg-config` and try again"))
result.Add(newPrerequisite("npm", "Please install with `sudo snap install node --channel=12/stable --classic` and try again")) result.Add(newPrerequisite("npm", "Please install with `sudo snap install node --channel=12/stable --classic` and try again"))
case Fedora:
result.Add(newPrerequisite("gcc", "Please install with `sudo yum install gcc-c++ make` and try again"))
result.Add(newPrerequisite("pkg-config", "Please install with `sudo yum install pkgconf-pkg-config` and try again"))
result.Add(newPrerequisite("npm", "Please install with `curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - && sudo yum install -y nodejs` and try again"))
case CentOS:
result.Add(newPrerequisite("gcc", "Please install with `sudo yum install gcc gcc-c++ make` and try again"))
result.Add(newPrerequisite("pkg-config", "Please install with `sudo yum install pkgconfig` and try again"))
result.Add(newPrerequisite("npm", "Please install with `curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - && sudo yum install -y nodejs` and try again"))
default: default:
result.Add(newPrerequisite("gcc", "Please install with your system package manager and try again")) result.Add(newPrerequisite("gcc", "Please install with your system package manager and try again"))
result.Add(newPrerequisite("pkg-config", "Please install with your system package manager and try again")) result.Add(newPrerequisite("pkg-config", "Please install with your system package manager and try again"))
result.Add(newPrerequisite("npm", "Please install from https://nodejs.org/en/download/ and try again")) result.Add(newPrerequisite("npm", "Please install from https://nodejs.org/en/download/ and try again"))
} }
return result return result
} }
@@ -94,15 +108,27 @@ func getRequiredLibrariesLinux() (*Prerequisites, error) {
result := &Prerequisites{} result := &Prerequisites{}
distroInfo := GetLinuxDistroInfo() distroInfo := GetLinuxDistroInfo()
switch distroInfo.Distribution { switch distroInfo.Distribution {
case Debian:
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 Ubuntu: case Ubuntu:
result.Add(newPrerequisite("libgtk-3-dev", "Please install with `sudo apt install libgtk-3-dev` and try again")) result.Add(newPrerequisite("libgtk-3-dev", "Please install with `sudo apt install libgtk-3-dev` and try again"))
result.Add(newPrerequisite("libwebkit2gtk-4.0-dev", "Please install with `sudo apt install libwebkit2gtk-4.0-dev` and try again")) result.Add(newPrerequisite("libwebkit2gtk-4.0-dev", "Please install with `sudo apt install libwebkit2gtk-4.0-dev` and try again"))
case Zorin:
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 Gentoo:
result.Add(newPrerequisite("gtk+:3", "Please install with `sudo emerge gtk+:3` and try again"))
result.Add(newPrerequisite("webkit-gtk", "Please install with `sudo emerge webkit-gtk` and try again"))
case Arch: case Arch:
result.Add(newPrerequisite("gtk3", "Please install with `sudo pacman -S gtk3` and try again")) 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")) result.Add(newPrerequisite("webkit2gtk", "Please install with `sudo pacman -S webkit2gtk` and try again"))
case RedHat: case Fedora:
result.Add(newPrerequisite("gtk3-devel", "Please install with `sudo yum install gtk3-devel` and try again")) 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")) result.Add(newPrerequisite("webkit2gtk3-devel", "Please install with `sudo yum install webkit2gtk3-devel` and try again"))
case CentOS:
result.Add(newPrerequisite("gtk3-devel", "Please install with `sudo yum install gtk3-devel` and try again"))
result.Add(newPrerequisite("webkitgtk3-devel", "Please install with `sudo yum install webkitgtk3-devel` and try again"))
default: default:
result.Add(newPrerequisite("libgtk-3-dev", "Please install with your system package manager and try again")) result.Add(newPrerequisite("libgtk-3-dev", "Please install with your system package manager and try again"))
result.Add(newPrerequisite("libwebkit2gtk-4.0-dev", "Please install with your system package manager and try again")) result.Add(newPrerequisite("libwebkit2gtk-4.0-dev", "Please install with your system package manager and try again"))

View File

@@ -117,14 +117,15 @@ func (p *ProgramHelper) RunCommandArray(args []string, dir ...string) error {
} }
args = args[1:] args = args[1:]
var stderr string var stderr string
// fmt.Printf("RunCommandArray = %s %+v\n", program, args) var stdout string
if len(dir) > 0 { if len(dir) > 0 {
_, stderr, err = p.shell.RunInDirectory(dir[0], program, args...) stdout, stderr, err = p.shell.RunInDirectory(dir[0], program, args...)
} else { } else {
_, stderr, err = p.shell.Run(program, args...) stdout, stderr, err = p.shell.Run(program, args...)
} }
if err != nil { if err != nil {
fmt.Println(stderr) fmt.Println(stderr)
fmt.Println(stdout)
} }
return err return err
} }

View File

@@ -7,6 +7,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"sort"
"strings" "strings"
"github.com/leaanthony/slicer" "github.com/leaanthony/slicer"
@@ -143,11 +144,13 @@ type ProjectOptions struct {
log *Logger log *Logger
templates *TemplateHelper templates *TemplateHelper
selectedTemplate *TemplateDetails selectedTemplate *TemplateDetails
WailsVersion string
} }
// Defaults sets the default project template // Defaults sets the default project template
func (po *ProjectOptions) Defaults() { func (po *ProjectOptions) Defaults() {
po.Template = "vuebasic" po.Template = "vuebasic"
po.WailsVersion = Version
} }
// PromptForInputs asks the user to input project details // PromptForInputs asks the user to input project details
@@ -182,7 +185,13 @@ func (po *ProjectOptions) PromptForInputs() error {
po.selectedTemplate = templateDetails[po.Template] po.selectedTemplate = templateDetails[po.Template]
} else { } else {
for _, templateDetail := range templateDetails { keys := make([]string, 0)
for k := range templateDetails {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
templateDetail := templateDetails[k]
templateList.Add(templateDetail) templateList.Add(templateDetail)
options.Add(fmt.Sprintf("%s - %s", templateDetail.Metadata.Name, templateDetail.Metadata.ShortDescription)) options.Add(fmt.Sprintf("%s - %s", templateDetail.Metadata.Name, templateDetail.Metadata.ShortDescription))
} }

View File

@@ -4,7 +4,6 @@ import (
"bufio" "bufio"
"fmt" "fmt"
"os" "os"
"runtime"
"strconv" "strconv"
"strings" "strings"
) )
@@ -20,11 +19,7 @@ func Prompt(question string, defaultValue ...string) string {
fmt.Printf(question + ": ") fmt.Printf(question + ": ")
reader := bufio.NewReader(os.Stdin) reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n') input, _ := reader.ReadString('\n')
EOL := "\n" input = strings.TrimSpace(input)
if runtime.GOOS == "windows" {
EOL = "\r\n"
}
input = strings.Replace(input, EOL, "", -1)
if input != "" { if input != "" {
answer = input answer = input

View File

@@ -3,7 +3,7 @@ package cmd
import ( import (
"fmt" "fmt"
"github.com/masterminds/semver" "github.com/Masterminds/semver"
) )
// SemanticVersion is a struct containing a semantic version // SemanticVersion is a struct containing a semantic version

View File

@@ -272,7 +272,7 @@ func CheckDependencies(logger *Logger) (bool, error) {
distroInfo := GetLinuxDistroInfo() distroInfo := GetLinuxDistroInfo()
for _, library := range *requiredLibraries { for _, library := range *requiredLibraries {
switch distroInfo.Distribution { switch distroInfo.Distribution {
case Ubuntu: case Ubuntu, Zorin, Debian:
installed, err := DpkgInstalled(library.Name) installed, err := DpkgInstalled(library.Name)
if err != nil { if err != nil {
return false, err return false, err
@@ -294,8 +294,7 @@ func CheckDependencies(logger *Logger) (bool, error) {
} else { } else {
logger.Green("Library '%s' installed.", library.Name) logger.Green("Library '%s' installed.", library.Name)
} }
case RedHat: case RedHat, Fedora, CentOS:
installed, err := RpmInstalled(library.Name) installed, err := RpmInstalled(library.Name)
if err != nil { if err != nil {
return false, err return false, err
@@ -306,8 +305,19 @@ func CheckDependencies(logger *Logger) (bool, error) {
} else { } else {
logger.Green("Library '%s' installed.", library.Name) logger.Green("Library '%s' installed.", library.Name)
} }
case Gentoo:
installed, err := EqueryInstalled(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)
}
default: default:
return false, fmt.Errorf("unable to check libraries on distribution '%s'. Please ensure that the '%s' equivalent is installed", distroInfo.DistributorID, library.Name) return false, RequestSupportForDistribution(distroInfo, library.Name)
} }
} }
} }

View File

@@ -16,18 +16,26 @@ import (
// TemplateMetadata holds all the metadata for a Wails template // TemplateMetadata holds all the metadata for a Wails template
type TemplateMetadata struct { type TemplateMetadata struct {
Name string `json:"name"` Name string `json:"name"`
Version string `json:"version"` Version string `json:"version"`
ShortDescription string `json:"shortdescription"` ShortDescription string `json:"shortdescription"`
Description string `json:"description"` Description string `json:"description"`
Install string `json:"install"` Install string `json:"install"`
Build string `json:"build"` Build string `json:"build"`
Author string `json:"author"` Author string `json:"author"`
Created string `json:"created"` Created string `json:"created"`
FrontendDir string `json:"frontenddir"` FrontendDir string `json:"frontenddir"`
Serve string `json:"serve"` Serve string `json:"serve"`
Bridge string `json:"bridge"` Bridge string `json:"bridge"`
WailsDir string `json:"wailsdir"` WailsDir string `json:"wailsdir"`
TemplateDependencies []*TemplateDependency `json:"dependencies,omitempty"`
}
// TemplateDependency defines a binary dependency for the template
// EG: ng for angular
type TemplateDependency struct {
Bin string `json:"bin"`
Help string `json:"help"`
} }
// TemplateDetails holds information about a specific template // TemplateDetails holds information about a specific template
@@ -152,6 +160,31 @@ func (t *TemplateHelper) GetTemplateFilenames(template *TemplateDetails) (*slice
// project path given // project path given
func (t *TemplateHelper) InstallTemplate(projectPath string, projectOptions *ProjectOptions) error { func (t *TemplateHelper) InstallTemplate(projectPath string, projectOptions *ProjectOptions) error {
// Check dependencies before installing
dependencies := projectOptions.selectedTemplate.Metadata.TemplateDependencies
if dependencies != nil {
programHelper := NewProgramHelper()
logger := NewLogger()
errors := []string{}
for _, dep := range dependencies {
program := programHelper.FindProgram(dep.Bin)
if program == nil {
errors = append(errors, dep.Help)
}
}
if len(errors) > 0 {
mainError := "template dependencies not installed"
if len(errors) == 1 {
mainError = errors[0]
} else {
for _, error := range errors {
logger.Red(error)
}
}
return fmt.Errorf(mainError)
}
}
// Get template files // Get template files
templateFilenames, err := t.GetTemplateFilenames(projectOptions.selectedTemplate) templateFilenames, err := t.GetTemplateFilenames(projectOptions.selectedTemplate)
if err != nil { if err != nil {
@@ -160,6 +193,9 @@ func (t *TemplateHelper) InstallTemplate(projectPath string, projectOptions *Pro
templatePath := projectOptions.selectedTemplate.Path templatePath := projectOptions.selectedTemplate.Path
// Save the version
projectOptions.WailsVersion = Version
templateJSONFilename := filepath.Join(templatePath, t.metadataFilename) templateJSONFilename := filepath.Join(templatePath, t.metadataFilename)
templateFiles := templateFilenames.Filter(func(filename string) bool { templateFiles := templateFilenames.Filter(func(filename string) bool {

View File

@@ -0,0 +1,13 @@
# Editor configuration, see https://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
max_line_length = off
trim_trailing_whitespace = false

View File

@@ -0,0 +1,47 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
# compiled output
/dist
/tmp
/out-tsc
# Only exists if Bazel was run
/bazel-out
# dependencies
/node_modules
# profiling files
chrome-profiler-events.json
speed-measure-plugin.json
# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*
# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
yarn-error.log
testem.log
/typings
# System Files
.DS_Store
Thumbs.db
.editorcinfig

View File

@@ -0,0 +1,27 @@
# MyApp
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.0.3.
## Development server
Run `npx ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
## Code scaffolding
Run `npx ng generate component component-name` to generate a new component. You can also use `npx ng generate directive|pipe|service|class|guard|interface|enum|module`.
## Build
Run `npx ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
## Running unit tests
Run `npx ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
## Running end-to-end tests
Run `npx ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
## Further help
To get more help on the Angular CLI use `npx ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).

View File

@@ -0,0 +1,121 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"my-app": {
"projectType": "application",
"schematics": {},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "ngx-build-plus:browser",
"options": {
"outputPath": "dist/my-app",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": false,
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.css"
],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
}
]
}
}
},
"serve": {
"builder": "ngx-build-plus:dev-server",
"options": {
"browserTarget": "my-app:build"
},
"configurations": {
"production": {
"browserTarget": "my-app:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "my-app:build"
}
},
"test": {
"builder": "ngx-build-plus:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.css"
],
"scripts": []
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json",
"e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "my-app:serve"
},
"configurations": {
"production": {
"devServerTarget": "my-app:serve:production"
}
}
}
}
}
},
"defaultProject": "my-app"
}

View File

@@ -0,0 +1,12 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# You can see what browsers were selected by your queries by running:
# npx browserslist
> 0.5%
last 2 versions
Firefox ESR
not dead
not IE 9-11 # For IE 9-11 support, remove 'not'.

View File

@@ -0,0 +1,32 @@
// @ts-check
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter } = require('jasmine-spec-reporter');
/**
* @type { import("protractor").Config }
*/
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./src/**/*.e2e-spec.ts'
],
capabilities: {
'browserName': 'chrome'
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
onPrepare() {
require('ts-node').register({
project: require('path').join(__dirname, './tsconfig.json')
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};

View File

@@ -0,0 +1,23 @@
import { AppPage } from './app.po';
import { browser, logging } from 'protractor';
describe('workspace-project App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
it('should display welcome message', () => {
page.navigateTo();
expect(page.getTitleText()).toEqual('Welcome to my-app!');
});
afterEach(async () => {
// Assert that there are no errors emitted from the browser
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
expect(logs).not.toContain(jasmine.objectContaining({
level: logging.Level.SEVERE,
} as logging.Entry));
});
});

View File

@@ -0,0 +1,11 @@
import { browser, by, element } from 'protractor';
export class AppPage {
navigateTo() {
return browser.get(browser.baseUrl) as Promise<any>;
}
getTitleText() {
return element(by.css('app-root h1')).getText() as Promise<string>;
}
}

View File

@@ -0,0 +1,13 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/e2e",
"module": "commonjs",
"target": "es5",
"types": [
"jasmine",
"jasminewd2",
"node"
]
}
}

View File

@@ -0,0 +1,32 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular-devkit/build-angular/plugins/karma')
],
client: {
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, './coverage/my-app'),
reports: ['html', 'lcovonly', 'text-summary'],
fixWebpackSourcePaths: true
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
restartOnFileChange: true
});
};

View File

@@ -0,0 +1,51 @@
{
"name": "my-app",
"version": "0.0.0",
"scripts": {
"ng": "npx ng",
"start": "npx ng serve --poll=2000",
"build": "npx ng build --single-bundle true --output-hashing none --prod --bundle-styles false",
"test": "npx ng test",
"lint": "npx ng lint",
"e2e": "npx ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "^8.0.2",
"@angular/cdk": "^8.0.1",
"@angular/common": "~8.0.1",
"@angular/compiler": "~8.0.1",
"@angular/core": "~8.0.1",
"@angular/forms": "~8.0.1",
"@angular/material": "^8.0.1",
"@angular/platform-browser": "~8.0.1",
"@angular/platform-browser-dynamic": "~8.0.1",
"@angular/router": "~8.0.1",
"@wailsapp/runtime": "^1.0.0",
"ngx-build-plus": "^8.0.3",
"rxjs": "~6.4.0",
"tslib": "^1.9.0",
"zone.js": "~0.9.1"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.800.0",
"@angular/cli": "~8.0.3",
"@angular/compiler-cli": "~8.0.1",
"@angular/language-service": "~8.0.1",
"@types/node": "~8.9.4",
"@types/jasmine": "~3.3.8",
"@types/jasminewd2": "~2.0.3",
"codelyzer": "^5.0.0",
"jasmine-core": "~3.4.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~4.1.0",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~2.0.1",
"karma-jasmine": "~2.0.1",
"karma-jasmine-html-reporter": "^1.4.0",
"protractor": "~5.4.0",
"ts-node": "~7.0.0",
"tslint": "~5.15.0",
"typescript": "~3.4.3"
}
}

View File

@@ -0,0 +1,13 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
const routes: Routes = [];
@NgModule({
imports: [
RouterModule.forRoot(routes)
],
exports: [RouterModule]
})
export class AppRoutingModule { }

View File

@@ -0,0 +1,14 @@
<!--The content below is only a placeholder and can be replaced.-->
<div style="text-align:center">
<h1>
Welcome to {{ title }}!
</h1>
<img width="300" alt="Angular Logo"
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
<br />
<button (click)="onClickMe()">Hello</button>
<p>{{clickMessage}}</p>
</div>
<router-outlet></router-outlet>

View File

@@ -0,0 +1,35 @@
import { TestBed, async } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule
],
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
});
it(`should have as title 'my-app'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('my-app');
});
it('should render title in a h1 tag', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to my-app!');
});
});

View File

@@ -0,0 +1,19 @@
import { Component } from '@angular/core';
@Component({
selector: '[id="app"]',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'my-app';
clickMessage = '';
onClickMe() {
// @ts-ignore
window.backend.basic().then(result =>
this.clickMessage = result
);
}
}

View File

@@ -0,0 +1,20 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { APP_BASE_HREF } from '@angular/common';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [{provide: APP_BASE_HREF, useValue : '/' }],
bootstrap: [AppComponent]
})
export class AppModule { }

View File

@@ -0,0 +1,3 @@
export const environment = {
production: true
};

View File

@@ -0,0 +1,16 @@
// This file can be replaced during build by using the `fileReplacements` array.
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
// The list of file replacements can be found in `angular.json`.
export const environment = {
production: false
};
/*
* For easier debugging in development mode, you can import the following file
* to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
*
* This import should be commented out in production mode because it will have a negative impact
* on performance if an error is thrown.
*/
// import 'zone.js/dist/zone-error'; // Included with Angular CLI.

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@@ -0,0 +1,14 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>my-app</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<div id="app"></div>
</body>
</html>

View File

@@ -0,0 +1,18 @@
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
import 'zone.js'
import Wails from '@wailsapp/runtime';
if (environment.production) {
enableProdMode();
}
Wails.Init(() => {
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));
});

View File

@@ -0,0 +1,63 @@
/**
* This file includes polyfills needed by Angular and is loaded before the app.
* You can add your own extra polyfills to this file.
*
* This file is divided into 2 sections:
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
* file.
*
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
*
* Learn more in https://angular.io/guide/browser-support
*/
/***************************************************************************************************
* BROWSER POLYFILLS
*/
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js'; // Run `npm install --save classlist.js`.
/**
* Web Animations `@angular/platform-browser/animations`
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
*/
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
/**
* By default, zone.js will patch all possible macroTask and DomEvents
* user can disable parts of macroTask/DomEvents patch by setting following flags
* because those flags need to be set before `zone.js` being loaded, and webpack
* will put import in the top of bundle, so user need to create a separate file
* in this directory (for example: zone-flags.ts), and put the following flags
* into that file, and then add the following code before importing zone.js.
* import './zone-flags.ts';
*
* The flags allowed in zone-flags.ts are listed here.
*
* The following flags will work for all browsers.
*
* (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
* (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
* (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
*
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
* with the following flag, it will bypass `zone.js` patch for IE/Edge
*
* (window as any).__Zone_enable_cross_context_check = true;
*
*/
/***************************************************************************************************
* Zone JS is required by default for Angular itself.
*/
//import 'zone.js/dist/zone'; // Included with Angular CLI.
/***************************************************************************************************
* APPLICATION IMPORTS
*/

View File

@@ -0,0 +1,24 @@
/* You can add global styles to this file, and also import other style files */
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
background-color: #282c34;
}
p {
color: white
}
h1 {
color: white
}
button {
background-color: white;
color: black;
}

View File

@@ -0,0 +1,20 @@
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import 'zone.js/dist/zone-testing';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
declare const require: any;
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().map(context);

View File

@@ -0,0 +1,14 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": []
},
"include": [
"src/**/*.ts"
],
"exclude": [
"src/test.ts",
"src/**/*.spec.ts"
]
}

View File

@@ -0,0 +1,23 @@
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"module": "esnext",
"moduleResolution": "node",
"importHelpers": true,
"target": "es2015",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2018",
"dom"
]
}
}

View File

@@ -0,0 +1,18 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": [
"jasmine",
"node"
]
},
"files": [
"src/test.ts",
"src/polyfills.ts"
],
"include": [
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
}

View File

@@ -0,0 +1,92 @@
{
"extends": "tslint:recommended",
"rules": {
"array-type": false,
"arrow-parens": false,
"deprecation": {
"severity": "warn"
},
"component-class-suffix": true,
"contextual-lifecycle": true,
"directive-class-suffix": true,
"directive-selector": [
true,
"attribute",
"app",
"camelCase"
],
"component-selector": [
true,
"element",
"app",
"kebab-case"
],
"import-blacklist": [
true,
"rxjs/Rx"
],
"interface-name": false,
"max-classes-per-file": false,
"max-line-length": [
true,
140
],
"member-access": false,
"member-ordering": [
true,
{
"order": [
"static-field",
"instance-field",
"static-method",
"instance-method"
]
}
],
"no-consecutive-blank-lines": false,
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-empty": false,
"no-inferrable-types": [
true,
"ignore-params"
],
"no-non-null-assertion": true,
"no-redundant-jsdoc": true,
"no-switch-case-fall-through": true,
"no-use-before-declare": true,
"no-var-requires": false,
"object-literal-key-quotes": [
true,
"as-needed"
],
"object-literal-sort-keys": false,
"ordered-imports": false,
"quotemark": [
true,
"single"
],
"trailing-comma": false,
"no-conflicting-lifecycle": true,
"no-host-metadata-property": true,
"no-input-rename": true,
"no-inputs-metadata-property": true,
"no-output-native": true,
"no-output-on-prefix": true,
"no-output-rename": true,
"no-outputs-metadata-property": true,
"template-banana-in-box": true,
"template-no-negated-async": true,
"use-lifecycle-interface": true,
"use-pipe-transform-interface": true
},
"rulesDirectory": [
"codelyzer"
]
}

View File

@@ -0,0 +1,5 @@
module {{.BinaryName}}
require (
github.com/wailsapp/wails {{.WailsVersion}}
)

View File

@@ -0,0 +1,27 @@
package main
import (
"github.com/leaanthony/mewn"
"github.com/wailsapp/wails"
)
func basic() string {
return "World!"
}
func main() {
js := mewn.String("./frontend/dist/my-app/main-es2015.js")
css := mewn.String("./frontend/dist/my-app/styles.css")
app := wails.CreateApp(&wails.AppConfig{
Width: 1024,
Height: 768,
Title: "{{.Name}}",
JS: js,
CSS: css,
Colour: "#131313",
})
app.Bind(basic)
app.Run()
}

View File

@@ -0,0 +1,20 @@
{
"name": "Angular",
"version": "1.0.0",
"shortdescription": "Angular 8 template (Requires node 10.8+)",
"description": "Angular projects w/ @angular/cli - Note: in order to reach the cli use npx like this: npx ng",
"dependencies": [
{
"bin": "npx",
"help": "This template requires 'npx'. Please install with 'npm install -g npx'"
}
],
"install": "npm install",
"build": "npx ng build --single-bundle true --output-hashing none --prod --bundle-styles false",
"author": "bh90210 <ktc@pm.me>",
"created": "2019-06-15 18:23:48.666414555 +0300 EEST m=+223.934866008",
"frontenddir": "frontend",
"serve": "npx ng serve --poll=2000",
"bridge": "src",
"wailsdir": ""
}

View File

@@ -0,0 +1,3 @@
{
"esversion": 6
}

View File

@@ -4,10 +4,12 @@
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"dependencies": { "dependencies": {
"core-js": "^3.1.4",
"react": "^16.8.6", "react": "^16.8.6",
"react-dom": "^16.8.6", "react-dom": "^16.8.6",
"wails-react-scripts": "3.0.1-2", "wails-react-scripts": "3.0.1-2",
"react-modal": "3.8.1" "react-modal": "3.8.1",
"@wailsapp/runtime": "^1.0.0"
}, },
"scripts": { "scripts": {
"start": "react-scripts start", "start": "react-scripts start",

View File

@@ -26,22 +26,8 @@ class HelloWorld extends React.Component {
this.setState({ showModal: false }); this.setState({ showModal: false });
} }
startAsync() {
this.setState({
loading: true
});
window.backend.basic().then(result =>
this.setState({
loading: false,
result
})
);
}
render() { render() {
const { loading, result } = this.state; const { result } = this.state;
return ( return (
<div className="App"> <div className="App">
<button onClick={this.handleOpenModal} type="button"> <button onClick={this.handleOpenModal} type="button">

View File

@@ -1,10 +1,11 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import 'core-js/stable';
import './index.css'; import './index.css';
import App from './App'; import App from './App';
import Bridge from "./wailsbridge"; import Wails from '@wailsapp/runtime';
Bridge.Start(() => { Wails.Init(() => {
ReactDOM.render(<App />, document.getElementById('app')); ReactDOM.render(<App />, document.getElementById('app'));
}); });

View File

@@ -9,9 +9,9 @@
export default { export default {
// The main function // The main function
// Passes the main Wails object to the callback if given. // Passes the main Wails object to the callback if given.
Start: function(callback) { Start: function (callback) {
if (callback) { if (callback) {
window.wails.events.on("wails:ready", callback); window.wails.Events.On("wails:ready", callback);
} }
} }
}; };

View File

@@ -1 +1,5 @@
module {{.BinaryName}} module {{.BinaryName}}
require (
github.com/wailsapp/wails {{.WailsVersion}}
)

View File

@@ -0,0 +1,3 @@
{
"esversion": 6
}

View File

@@ -9,7 +9,8 @@
}, },
"dependencies": { "dependencies": {
"core-js": "^2.6.4", "core-js": "^2.6.4",
"vue": "^2.5.22" "vue": "^2.5.22",
"@wailsapp/runtime": "^1.0.0"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "^3.4.0", "@vue/cli-plugin-babel": "^3.4.0",

View File

@@ -1,13 +1,13 @@
import Vue from "vue"; import Vue from 'vue';
import App from "./App.vue"; import App from './App.vue';
Vue.config.productionTip = false; Vue.config.productionTip = false;
Vue.config.devtools = true; Vue.config.devtools = true;
import Bridge from "./wailsbridge"; import Wails from '@wailsapp/runtime';
Bridge.Start(() => { Wails.Init(() => {
new Vue({ new Vue({
render: h => h(App) render: h => h(App)
}).$mount("#app"); }).$mount('#app');
}); });

View File

@@ -1 +1,5 @@
module {{.BinaryName}} module {{.BinaryName}}
require (
github.com/wailsapp/wails {{.WailsVersion}}
)

View File

@@ -12,7 +12,8 @@
"core-js": "^2.6.4", "core-js": "^2.6.4",
"material-design-icons-iconfont": "^5.0.1", "material-design-icons-iconfont": "^5.0.1",
"vue": "^2.5.22", "vue": "^2.5.22",
"vuetify": "^1.5.14" "vuetify": "^1.5.14",
"@wailsapp/runtime": "^1.0.0"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "^3.4.0", "@vue/cli-plugin-babel": "^3.4.0",

View File

@@ -1,5 +1,5 @@
import 'babel-polyfill'; import 'babel-polyfill';
import Vue from "vue"; import Vue from 'vue';
// Setup Vuetify // Setup Vuetify
import Vuetify from 'vuetify'; import Vuetify from 'vuetify';
@@ -7,15 +7,15 @@ Vue.use(Vuetify);
import 'vuetify/dist/vuetify.min.css'; import 'vuetify/dist/vuetify.min.css';
import 'material-design-icons-iconfont'; import 'material-design-icons-iconfont';
import App from "./App.vue"; import App from './App.vue';
Vue.config.productionTip = false; Vue.config.productionTip = false;
Vue.config.devtools = true; Vue.config.devtools = true;
import Bridge from "./wailsbridge"; import Wails from '@wailsapp/runtime';
Bridge.Start(() => { Wails.Init(() => {
new Vue({ new Vue({
render: h => h(App) render: h => h(App)
}).$mount("#app"); }).$mount('#app');
}); });

View File

@@ -1 +1,5 @@
module {{.BinaryName}} module {{.BinaryName}}
require (
github.com/wailsapp/wails {{.WailsVersion}}
)

View File

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

View File

@@ -96,7 +96,7 @@ func checkLibraries() (errors bool, err error) {
distroInfo := cmd.GetLinuxDistroInfo() distroInfo := cmd.GetLinuxDistroInfo()
for _, library := range *requiredLibraries { for _, library := range *requiredLibraries {
switch distroInfo.Distribution { switch distroInfo.Distribution {
case cmd.Ubuntu: case cmd.Ubuntu, cmd.Zorin, cmd.Debian:
installed, err := cmd.DpkgInstalled(library.Name) installed, err := cmd.DpkgInstalled(library.Name)
if err != nil { if err != nil {
return false, err return false, err
@@ -108,7 +108,7 @@ func checkLibraries() (errors bool, err error) {
logger.Green("Library '%s' installed.", library.Name) logger.Green("Library '%s' installed.", library.Name)
} }
default: default:
return false, fmt.Errorf("unable to check libraries on distribution '%s'. Please ensure that the '%s' equivalent is installed", distroInfo.DistributorID, library.Name) return false, cmd.RequestSupportForDistribution(distroInfo, library.Name)
} }
} }
} }

View File

@@ -72,8 +72,17 @@ func init() {
if err != nil { if err != nil {
return err return err
} }
// Ensure that runtime init.js is the production version
err = cmd.InstallProdRuntime(projectDir, projectOptions)
if err != nil {
return err
}
} }
// Move to project directory // Move to project directory
err = os.Chdir(projectDir) err = os.Chdir(projectDir)
if err != nil { if err != nil {

View File

@@ -45,7 +45,7 @@ func init() {
projectDir := fs.Cwd() projectDir := fs.Cwd()
// Install the bridge library // Install the bridge library
err = cmd.InstallBridge("serve", projectDir, projectOptions) err = cmd.InstallBridge(projectDir, projectOptions)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -42,12 +42,51 @@ To help you in this process, we will ask for some information, add Go/Wails deta
gomodule = "(Not Set)" gomodule = "(Not Set)"
} }
// Get versions for GCC, node & npm
program := cmd.NewProgramHelper()
var gccVersion, nodeVersion, npmVersion string
switch runtime.GOOS {
case "darwin":
gcc := program.FindProgram("gcc")
if gcc != nil {
stdout, _, _, _ := gcc.Run("-dumpversion")
gccVersion = strings.TrimSpace(stdout)
}
case "linux":
gcc := program.FindProgram("gcc")
if gcc != nil {
gccVersion, _, _, _ := gcc.Run("-dumpfullversion")
gccVersion = gccVersion[:len(gccVersion)-1]
gccVersion = strings.TrimSpace(gccVersion)
}
// TODO: windows support
}
npm := program.FindProgram("npm")
if npm != nil {
stdout, _, _, _ := npm.Run("--version")
nodeVersion = stdout
nodeVersion = nodeVersion[:len(nodeVersion)-1]
}
node := program.FindProgram("node")
if node != nil {
stdout, _, _, _ := node.Run("--version")
npmVersion = stdout
npmVersion = npmVersion[:len(npmVersion)-1]
}
str.WriteString("\n| Name | Value |\n| ----- | ----- |\n") str.WriteString("\n| Name | Value |\n| ----- | ----- |\n")
str.WriteString(fmt.Sprintf("| Wails Version | %s |\n", cmd.Version)) str.WriteString(fmt.Sprintf("| Wails Version | %s |\n", cmd.Version))
str.WriteString(fmt.Sprintf("| Go Version | %s |\n", runtime.Version())) str.WriteString(fmt.Sprintf("| Go Version | %s |\n", runtime.Version()))
str.WriteString(fmt.Sprintf("| Platform | %s |\n", runtime.GOOS)) str.WriteString(fmt.Sprintf("| Platform | %s |\n", runtime.GOOS))
str.WriteString(fmt.Sprintf("| Arch | %s |\n", runtime.GOARCH)) str.WriteString(fmt.Sprintf("| Arch | %s |\n", runtime.GOARCH))
str.WriteString(fmt.Sprintf("| GO111MODULE | %s |\n", gomodule)) str.WriteString(fmt.Sprintf("| GO111MODULE | %s |\n", gomodule))
str.WriteString(fmt.Sprintf("| GCC | %s |\n", gccVersion))
str.WriteString(fmt.Sprintf("| Npm | %s |\n", npmVersion))
str.WriteString(fmt.Sprintf("| Node | %s |\n", nodeVersion))
fmt.Println() fmt.Println()
fmt.Println("Processing template and preparing for upload.") fmt.Println("Processing template and preparing for upload.")

110
config.go Normal file
View File

@@ -0,0 +1,110 @@
package wails
import "github.com/leaanthony/mewn"
// AppConfig is the configuration structure used when creating a Wails App object
type AppConfig struct {
Width, Height int
Title string
defaultHTML string
HTML string
JS string
CSS string
Colour string
Resizable bool
DisableInspector bool
}
// GetWidth returns the desired width
func (a *AppConfig) GetWidth() int {
return a.Width
}
// GetHeight returns the desired height
func (a *AppConfig) GetHeight() int {
return a.Height
}
// GetTitle returns the desired window title
func (a *AppConfig) GetTitle() string {
return a.Title
}
// GetDefaultHTML returns the default HTML
func (a *AppConfig) GetDefaultHTML() string {
return a.defaultHTML
}
// GetResizable returns true if the window should be resizable
func (a *AppConfig) GetResizable() bool {
return a.Resizable
}
// GetDisableInspector returns true if the inspector should be disabled
func (a *AppConfig) GetDisableInspector() bool {
return a.DisableInspector
}
// GetColour returns the colour
func (a *AppConfig) GetColour() string {
return a.Colour
}
// GetCSS returns the user CSS
func (a *AppConfig) GetCSS() string {
return a.CSS
}
// GetJS returns the user Javascript
func (a *AppConfig) GetJS() string {
return a.JS
}
func (a *AppConfig) merge(in *AppConfig) error {
if in.CSS != "" {
a.CSS = in.CSS
}
if in.Title != "" {
a.Title = in.Title
}
if in.Colour != "" {
a.Colour = in.Colour
}
if in.JS != "" {
a.JS = in.JS
}
if in.Width != 0 {
a.Width = in.Width
}
if in.Height != 0 {
a.Height = in.Height
}
a.Resizable = in.Resizable
a.DisableInspector = in.DisableInspector
return nil
}
// Creates the default configuration
func newConfig(userConfig *AppConfig) (*AppConfig, error) {
result := &AppConfig{
Width: 800,
Height: 600,
Resizable: true,
Title: "My Wails App",
Colour: "#FFF", // White by default
HTML: mewn.String("./runtime/assets/default.html"),
}
if userConfig != nil {
err := result.merge(userConfig)
if err != nil {
return nil, err
}
}
return result, nil
}

5
go.mod
View File

@@ -1,7 +1,7 @@
module github.com/wailsapp/wails module github.com/wailsapp/wails
require ( require (
github.com/Masterminds/semver v1.4.2 // indirect github.com/Masterminds/semver v1.4.2
github.com/dchest/cssmin v0.0.0-20151210170030-fb8d9b44afdc // indirect github.com/dchest/cssmin v0.0.0-20151210170030-fb8d9b44afdc // indirect
github.com/dchest/htmlmin v0.0.0-20150526090704-e254725e81ac github.com/dchest/htmlmin v0.0.0-20150526090704-e254725e81ac
github.com/dchest/jsmin v0.0.0-20160823214000-faeced883947 // indirect github.com/dchest/jsmin v0.0.0-20160823214000-faeced883947 // indirect
@@ -12,9 +12,8 @@ require (
github.com/kennygrant/sanitize v1.2.4 github.com/kennygrant/sanitize v1.2.4
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/leaanthony/mewn v0.10.7 github.com/leaanthony/mewn v0.10.7
github.com/leaanthony/slicer v1.3.1 github.com/leaanthony/slicer v1.3.2
github.com/leaanthony/spinner v0.5.3 github.com/leaanthony/spinner v0.5.3
github.com/masterminds/semver v1.4.2
github.com/mattn/go-colorable v0.1.1 // indirect github.com/mattn/go-colorable v0.1.1 // indirect
github.com/mattn/go-isatty v0.0.7 // indirect github.com/mattn/go-isatty v0.0.7 // indirect
github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/go-homedir v1.1.0

12
go.sum
View File

@@ -25,7 +25,6 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= 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 h1:gN25/otpP5vAsO2djbMhF/LQX6R7+O1TB4yv8NzpJ3o=
github.com/kennygrant/sanitize v1.2.4/go.mod h1:LGsjYYtgxbetdg5owWB2mpgUL6e2nfw2eObZ0u0qvak= 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/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/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/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -33,22 +32,18 @@ github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/leaanthony/mewn v0.10.7 h1:jCcNJyIUOpwj+I5SuATvCugDjHkoo+j6ubEOxxrxmPA= github.com/leaanthony/mewn v0.10.7 h1:jCcNJyIUOpwj+I5SuATvCugDjHkoo+j6ubEOxxrxmPA=
github.com/leaanthony/mewn v0.10.7/go.mod h1:CRkTx8unLiSSilu/Sd7i1LwrdaAL+3eQ3ses99qGMEQ= github.com/leaanthony/mewn v0.10.7/go.mod h1:CRkTx8unLiSSilu/Sd7i1LwrdaAL+3eQ3ses99qGMEQ=
github.com/leaanthony/slicer v1.3.1 h1:n2iIV2sxvL/3bpnmVY0vBjXf3yYFWcB6CYLVMrzJxRw= github.com/leaanthony/slicer v1.3.2 h1:kGWWFoyaY5WzwGrUsHXMmGbssuYthP4qYBNlkNpNAB8=
github.com/leaanthony/slicer v1.3.1/go.mod h1:VMB/HGvr3uR3MRpFWHWAm0w+DHQLzPHYe2pKfpFlQIQ= github.com/leaanthony/slicer v1.3.2/go.mod h1:VMB/HGvr3uR3MRpFWHWAm0w+DHQLzPHYe2pKfpFlQIQ=
github.com/leaanthony/spinner v0.5.3 h1:IMTvgdQCec5QA4qRy0wil4XsRP+QcG1OwLWVK/LPZ5Y= github.com/leaanthony/spinner v0.5.3 h1:IMTvgdQCec5QA4qRy0wil4XsRP+QcG1OwLWVK/LPZ5Y=
github.com/leaanthony/spinner v0.5.3/go.mod h1:oHlrvWicr++CVV7ALWYi+qHk/XNA91D9IJ48IqmpVUo= github.com/leaanthony/spinner v0.5.3/go.mod h1:oHlrvWicr++CVV7ALWYi+qHk/XNA91D9IJ48IqmpVUo=
github.com/leaanthony/synx v0.1.0 h1:R0lmg2w6VMb8XcotOwAe5DLyzwjLrskNkwU7LLWsyL8= github.com/leaanthony/synx v0.1.0 h1:R0lmg2w6VMb8XcotOwAe5DLyzwjLrskNkwU7LLWsyL8=
github.com/leaanthony/synx v0.1.0/go.mod h1:Iz7eybeeG8bdq640iR+CwYb8p+9EOsgMWghkSRyZcqs= github.com/leaanthony/synx v0.1.0/go.mod h1:Iz7eybeeG8bdq640iR+CwYb8p+9EOsgMWghkSRyZcqs=
github.com/leaanthony/wincursor v0.1.0 h1:Dsyp68QcF5cCs65AMBmxoYNEm0n8K7mMchG6a8fYxf8= github.com/leaanthony/wincursor v0.1.0 h1:Dsyp68QcF5cCs65AMBmxoYNEm0n8K7mMchG6a8fYxf8=
github.com/leaanthony/wincursor v0.1.0/go.mod h1:7TVwwrzSH/2Y9gLOGH+VhA+bZhoWXBRgbGNTMk+yimE= github.com/leaanthony/wincursor v0.1.0/go.mod h1:7TVwwrzSH/2Y9gLOGH+VhA+bZhoWXBRgbGNTMk+yimE=
github.com/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.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.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.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.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 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc=
@@ -77,7 +72,6 @@ github.com/wailsapp/webview v0.2.7 h1:fN5L5H9Oivg9IJPk7uaXQnjqB68Fny11ZWkIaTIZHm
github.com/wailsapp/webview v0.2.7/go.mod h1:XO9HJbKWokDxUYTWQEBCYg95n/To1v7PxvanDNVf8hY= 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= github.com/zserge/webview v0.0.0-20190123072648-16c93bcaeaeb/go.mod h1:a1CV8KR4Dd1eP2g+mEijGOp+HKczwdKHWyx0aPHKvo4=
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -86,10 +80,8 @@ golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5 h1:6M3SDHlHHDCx2PcQw3S4KsR17
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb h1:pf3XwC90UUdNPYWZdFjhGBE7DUFuK3Ct1zWmZ65QN30=
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862 h1:rM0ROo5vb9AdYJi1110yjWGMej9ITfKddS89P3Fkhug= golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862 h1:rM0ROo5vb9AdYJi1110yjWGMej9ITfKddS89P3Fkhug=

View File

@@ -1,4 +1,4 @@
package wails package binding
import ( import (
"bytes" "bytes"
@@ -6,6 +6,8 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"runtime" "runtime"
"github.com/wailsapp/wails/lib/logger"
) )
type boundFunction struct { type boundFunction struct {
@@ -14,7 +16,7 @@ type boundFunction struct {
functionType reflect.Type functionType reflect.Type
inputs []reflect.Type inputs []reflect.Type
returnTypes []reflect.Type returnTypes []reflect.Type
log *CustomLogger log *logger.CustomLogger
hasErrorReturnType bool hasErrorReturnType bool
} }
@@ -30,7 +32,7 @@ func newBoundFunction(object interface{}) (*boundFunction, error) {
fullName: name, fullName: name,
function: objectValue, function: objectValue,
functionType: objectType, functionType: objectType,
log: newCustomLogger(name), log: logger.NewCustomLogger(name),
} }
err := result.processParameters() err := result.processParameters()
@@ -55,7 +57,7 @@ func (b *boundFunction) processParameters() error {
b.inputs[index] = param b.inputs[index] = param
typ := param typ := param
index := index index := index
b.log.DebugFields("Input param", Fields{ b.log.DebugFields("Input param", logger.Fields{
"index": index, "index": index,
"name": name, "name": name,
"kind": kind, "kind": kind,

71
lib/binding/internal.go Normal file
View File

@@ -0,0 +1,71 @@
package binding
import (
"fmt"
"strings"
"github.com/wailsapp/wails/lib/logger"
"github.com/wailsapp/wails/lib/messages"
"github.com/wailsapp/wails/runtime"
)
type internalMethods struct {
log *logger.CustomLogger
browser *runtime.Browser
}
func newInternalMethods() *internalMethods {
return &internalMethods{
log: logger.NewCustomLogger("InternalCall"),
browser: runtime.NewBrowser(),
}
}
func (i *internalMethods) processCall(callData *messages.CallData) (interface{}, error) {
if !strings.HasPrefix(callData.BindingName, ".wails.") {
return nil, fmt.Errorf("Invalid call signature '%s'", callData.BindingName)
}
// Strip prefix
var splitCall = strings.Split(callData.BindingName, ".")[2:]
if len(splitCall) != 2 {
return nil, fmt.Errorf("Invalid call signature '%s'", callData.BindingName)
}
group := splitCall[0]
switch group {
case "Browser":
return i.processBrowserCommand(splitCall[1], callData.Data)
default:
return nil, fmt.Errorf("Unknown internal command group '%s'", group)
}
}
func (i *internalMethods) processBrowserCommand(command string, data interface{}) (interface{}, error) {
switch command {
case "OpenURL":
url := data.(string)
// Strip string quotes. Credit: https://stackoverflow.com/a/44222648
if url[0] == '"' {
url = url[1:]
}
if i := len(url) - 1; url[i] == '"' {
url = url[:i]
}
i.log.Debugf("Calling Browser.OpenURL with '%s'", url)
return nil, i.browser.OpenURL(url)
case "OpenFile":
filename := data.(string)
// Strip string quotes. Credit: https://stackoverflow.com/a/44222648
if filename[0] == '"' {
filename = filename[1:]
}
if i := len(filename) - 1; filename[i] == '"' {
filename = filename[:i]
}
i.log.Debugf("Calling Browser.OpenFile with '%s'", filename)
return nil, i.browser.OpenFile(filename)
default:
return nil, fmt.Errorf("Unknown Browser command '%s'", command)
}
}

View File

@@ -1,45 +1,46 @@
package wails package binding
import ( import (
"fmt" "fmt"
"reflect" "reflect"
"unicode" "unicode"
"github.com/wailsapp/wails/lib/logger"
"github.com/wailsapp/wails/lib/messages"
"github.com/wailsapp/wails/lib/interfaces"
) )
/** // Manager handles method binding
type Manager struct {
binding:
Name() // Full name (package+name)
Call(params)
**/
type bindingManager struct {
methods map[string]*boundMethod methods map[string]*boundMethod
functions map[string]*boundFunction functions map[string]*boundFunction
internalMethods *internalMethods
initMethods []*boundMethod initMethods []*boundMethod
log *CustomLogger log *logger.CustomLogger
renderer Renderer renderer interfaces.Renderer
runtime *Runtime // The runtime object to pass to bound structs runtime interfaces.Runtime // The runtime object to pass to bound structs
objectsToBind []interface{} objectsToBind []interface{}
bindPackageNames bool // Package name should be considered when binding bindPackageNames bool // Package name should be considered when binding
} }
func newBindingManager() *bindingManager { // NewManager creates a new Manager struct
result := &bindingManager{ func NewManager() interfaces.BindingManager {
methods: make(map[string]*boundMethod), result := &Manager{
functions: make(map[string]*boundFunction), methods: make(map[string]*boundMethod),
log: newCustomLogger("Bind"), functions: make(map[string]*boundFunction),
log: logger.NewCustomLogger("Bind"),
internalMethods: newInternalMethods(),
} }
return result return result
} }
// Sets flag to indicate package names should be considered when binding // BindPackageNames sets a flag to indicate package names should be considered when binding
func (b *bindingManager) BindPackageNames() { func (b *Manager) BindPackageNames() {
b.bindPackageNames = true b.bindPackageNames = true
} }
func (b *bindingManager) start(renderer Renderer, runtime *Runtime) error { // Start the binding manager
func (b *Manager) Start(renderer interfaces.Renderer, runtime interfaces.Runtime) error {
b.log.Info("Starting") b.log.Info("Starting")
b.renderer = renderer b.renderer = renderer
b.runtime = runtime b.runtime = runtime
@@ -52,7 +53,7 @@ func (b *bindingManager) start(renderer Renderer, runtime *Runtime) error {
return err return err
} }
func (b *bindingManager) initialise() error { func (b *Manager) initialise() error {
var err error var err error
// var binding *boundMethod // var binding *boundMethod
@@ -90,7 +91,7 @@ func (b *bindingManager) initialise() error {
} }
// bind the given struct method // bind the given struct method
func (b *bindingManager) bindMethod(object interface{}) error { func (b *Manager) bindMethod(object interface{}) error {
objectType := reflect.TypeOf(object) objectType := reflect.TypeOf(object)
baseName := objectType.String() baseName := objectType.String()
@@ -140,7 +141,7 @@ func (b *bindingManager) bindMethod(object interface{}) error {
} }
// bind the given function object // bind the given function object
func (b *bindingManager) bindFunction(object interface{}) error { func (b *Manager) bindFunction(object interface{}) error {
newFunction, err := newBoundFunction(object) newFunction, err := newBoundFunction(object)
if err != nil { if err != nil {
@@ -157,13 +158,18 @@ func (b *bindingManager) bindFunction(object interface{}) error {
return nil return nil
} }
// Save the given object to be bound at start time // Bind saves the given object to be bound at start time
func (b *bindingManager) bind(object interface{}) { func (b *Manager) Bind(object interface{}) {
// Store binding // Store binding
b.objectsToBind = append(b.objectsToBind, object) b.objectsToBind = append(b.objectsToBind, object)
} }
func (b *bindingManager) processFunctionCall(callData *callData) (interface{}, error) { func (b *Manager) processInternalCall(callData *messages.CallData) (interface{}, error) {
// Strip prefix
return b.internalMethods.processCall(callData)
}
func (b *Manager) processFunctionCall(callData *messages.CallData) (interface{}, error) {
// Return values // Return values
var result []reflect.Value var result []reflect.Value
var err error var err error
@@ -192,7 +198,7 @@ func (b *bindingManager) processFunctionCall(callData *callData) (interface{}, e
return result[0].Interface(), nil return result[0].Interface(), nil
} }
func (b *bindingManager) processMethodCall(callData *callData) (interface{}, error) { func (b *Manager) processMethodCall(callData *messages.CallData) (interface{}, error) {
// Return values // Return values
var result []reflect.Value var result []reflect.Value
var err error var err error
@@ -226,8 +232,8 @@ func (b *bindingManager) processMethodCall(callData *callData) (interface{}, err
return nil, nil return nil, nil
} }
// process an incoming call request // ProcessCall processes the given call request
func (b *bindingManager) processCall(callData *callData) (result interface{}, err error) { func (b *Manager) ProcessCall(callData *messages.CallData) (result interface{}, err error) {
b.log.Debugf("Wanting to call %s", callData.BindingName) b.log.Debugf("Wanting to call %s", callData.BindingName)
// Determine if this is function call or method call by the number of // Determine if this is function call or method call by the number of
@@ -254,6 +260,8 @@ func (b *bindingManager) processCall(callData *callData) (result interface{}, er
result, err = b.processFunctionCall(callData) result, err = b.processFunctionCall(callData)
case 2: case 2:
result, err = b.processMethodCall(callData) result, err = b.processMethodCall(callData)
case 3:
result, err = b.processInternalCall(callData)
default: default:
result = nil result = nil
err = fmt.Errorf("Invalid binding name '%s'", callData.BindingName) err = fmt.Errorf("Invalid binding name '%s'", callData.BindingName)
@@ -263,7 +271,7 @@ func (b *bindingManager) processCall(callData *callData) (result interface{}, er
// callWailsInitMethods calls all of the WailsInit methods that were // callWailsInitMethods calls all of the WailsInit methods that were
// registered with the runtime object // registered with the runtime object
func (b *bindingManager) callWailsInitMethods() error { func (b *Manager) callWailsInitMethods() error {
// Create reflect value for runtime object // Create reflect value for runtime object
runtimeValue := reflect.ValueOf(b.runtime) runtimeValue := reflect.ValueOf(b.runtime)
params := []reflect.Value{runtimeValue} params := []reflect.Value{runtimeValue}

View File

@@ -1,10 +1,12 @@
package wails package binding
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"reflect" "reflect"
"github.com/wailsapp/wails/lib/logger"
) )
type boundMethod struct { type boundMethod struct {
@@ -13,7 +15,7 @@ type boundMethod struct {
method reflect.Value method reflect.Value
inputs []reflect.Type inputs []reflect.Type
returnTypes []reflect.Type returnTypes []reflect.Type
log *CustomLogger log *logger.CustomLogger
hasErrorReturnType bool // Indicates if there is an error return type hasErrorReturnType bool // Indicates if there is an error return type
isWailsInit bool isWailsInit bool
} }
@@ -27,7 +29,7 @@ func newBoundMethod(name string, fullName string, method reflect.Value, objectTy
} }
// Setup logger // Setup logger
result.log = newCustomLogger(result.fullName) result.log = logger.NewCustomLogger(result.fullName)
// Check if Parameters are valid // Check if Parameters are valid
err := result.processParameters() err := result.processParameters()
@@ -57,7 +59,7 @@ func (b *boundMethod) processParameters() error {
b.inputs[index] = param b.inputs[index] = param
typ := param typ := param
index := index index := index
b.log.DebugFields("Input param", Fields{ b.log.DebugFields("Input param", logger.Fields{
"index": index, "index": index,
"name": name, "name": name,
"kind": kind, "kind": kind,
@@ -166,10 +168,10 @@ func (b *boundMethod) setInputValue(index int, typ reflect.Type, val interface{}
reflect.Map, reflect.Map,
reflect.Ptr, reflect.Ptr,
reflect.Slice: reflect.Slice:
logger.Debug("Converting nil to type") b.log.Debug("Converting nil to type")
result = reflect.ValueOf(val).Convert(typ) result = reflect.ValueOf(val).Convert(typ)
default: default:
logger.Debug("Cannot convert nil to type, returning error") b.log.Debug("Cannot convert nil to type, returning error")
return reflect.Zero(typ), fmt.Errorf("Unable to use null value for parameter %d of method %s", index+1, b.fullName) return reflect.Zero(typ), fmt.Errorf("Unable to use null value for parameter %d of method %s", index+1, b.fullName)
} }
} else { } else {

View File

@@ -1,31 +1,34 @@
package wails package event
import ( import (
"fmt" "fmt"
"sync" "sync"
"github.com/wailsapp/wails/lib/logger"
"github.com/wailsapp/wails/lib/messages"
"github.com/wailsapp/wails/lib/interfaces"
) )
// eventManager handles and processes events // Manager handles and processes events
type eventManager struct { type Manager struct {
incomingEvents chan *eventData incomingEvents chan *messages.EventData
listeners map[string][]*eventListener listeners map[string][]*eventListener
exit bool exit bool
log *CustomLogger log *logger.CustomLogger
renderer Renderer // Messages will be dispatched to the frontend renderer interfaces.Renderer // Messages will be dispatched to the frontend
} }
// newEventManager creates a new event manager with a 100 event buffer // NewManager creates a new event manager with a 100 event buffer
func newEventManager() *eventManager { func NewManager() interfaces.EventManager {
return &eventManager{ return &Manager{
incomingEvents: make(chan *eventData, 100), incomingEvents: make(chan *messages.EventData, 100),
listeners: make(map[string][]*eventListener), listeners: make(map[string][]*eventListener),
exit: false, exit: false,
log: newCustomLogger("Events"), log: logger.NewCustomLogger("Events"),
} }
} }
// PushEvent places the given event on to the event queue // PushEvent places the given event on to the event queue
func (e *eventManager) PushEvent(eventData *eventData) { func (e *Manager) PushEvent(eventData *messages.EventData) {
e.incomingEvents <- eventData e.incomingEvents <- eventData
} }
@@ -40,7 +43,7 @@ type eventListener struct {
} }
// Creates a new event listener from the given callback function // Creates a new event listener from the given callback function
func (e *eventManager) addEventListener(eventName string, callback func(...interface{}), counter int) error { func (e *Manager) addEventListener(eventName string, callback func(...interface{}), counter int) error {
// Sanity check inputs // Sanity check inputs
if callback == nil { if callback == nil {
@@ -65,18 +68,19 @@ func (e *eventManager) addEventListener(eventName string, callback func(...inter
return nil return nil
} }
func (e *eventManager) On(eventName string, callback func(...interface{})) { // On adds a listener for the given event
func (e *Manager) On(eventName string, callback func(...interface{})) {
// Add a persistent eventListener (counter = 0) // Add a persistent eventListener (counter = 0)
e.addEventListener(eventName, callback, 0) e.addEventListener(eventName, callback, 0)
} }
// Emit broadcasts the given event to the subscribed listeners // Emit broadcasts the given event to the subscribed listeners
func (e *eventManager) Emit(eventName string, optionalData ...interface{}) { func (e *Manager) Emit(eventName string, optionalData ...interface{}) {
e.incomingEvents <- &eventData{Name: eventName, Data: optionalData} e.incomingEvents <- &messages.EventData{Name: eventName, Data: optionalData}
} }
// Starts the event manager's queue processing // Start the event manager's queue processing
func (e *eventManager) start(renderer Renderer) { func (e *Manager) Start(renderer interfaces.Renderer) {
e.log.Info("Starting") e.log.Info("Starting")
@@ -95,7 +99,7 @@ func (e *eventManager) start(renderer Renderer) {
// TODO: Listen for application exit // TODO: Listen for application exit
select { select {
case event := <-e.incomingEvents: case event := <-e.incomingEvents:
e.log.DebugFields("Got Event", Fields{ e.log.DebugFields("Got Event", logger.Fields{
"data": event.Data, "data": event.Data,
"name": event.Name, "name": event.Name,
}) })
@@ -143,6 +147,6 @@ func (e *eventManager) start(renderer Renderer) {
wg.Wait() wg.Wait()
} }
func (e *eventManager) stop() { func (e *Manager) stop() {
e.exit = true e.exit = true
} }

View File

@@ -0,0 +1,14 @@
package interfaces
// AppConfig is the application config interface
type AppConfig interface {
GetWidth() int
GetHeight() int
GetTitle() string
GetResizable() bool
GetDefaultHTML() string
GetDisableInspector() bool
GetColour() string
GetCSS() string
GetJS() string
}

View File

@@ -0,0 +1,10 @@
package interfaces
import "github.com/wailsapp/wails/lib/messages"
// BindingManager is the binding manager interface
type BindingManager interface {
Bind(object interface{})
Start(renderer Renderer, runtime Runtime) error
ProcessCall(callData *messages.CallData) (result interface{}, err error)
}

View File

@@ -0,0 +1,11 @@
package interfaces
import "github.com/wailsapp/wails/lib/messages"
// EventManager is the event manager interface
type EventManager interface {
PushEvent(*messages.EventData)
Emit(eventName string, optionalData ...interface{})
On(eventName string, callback func(...interface{}))
Start(Renderer)
}

View File

@@ -0,0 +1,8 @@
package interfaces
// IPCManager is the event manager interface
type IPCManager interface {
BindRenderer(Renderer)
Dispatch(message string)
Start(eventManager EventManager, bindingManager BindingManager)
}

View File

@@ -1,8 +1,11 @@
package wails package interfaces
import (
"github.com/wailsapp/wails/lib/messages"
)
// Renderer is an interface describing a Wails target to render the app to // Renderer is an interface describing a Wails target to render the app to
type Renderer interface { type Renderer interface {
Initialise(*AppConfig, *ipcManager, *eventManager) error Initialise(AppConfig, IPCManager, EventManager) error
Run() error Run() error
// Binding // Binding
@@ -10,7 +13,7 @@ type Renderer interface {
Callback(data string) error Callback(data string) error
// Events // Events
NotifyEvent(eventData *eventData) error NotifyEvent(eventData *messages.EventData) error
// Dialog Runtime // Dialog Runtime
SelectFile() string SelectFile() string

View File

@@ -0,0 +1,4 @@
package interfaces
// Runtime interface
type Runtime interface {}

View File

@@ -1,13 +1,10 @@
package wails package ipc
import ( import (
"fmt" "fmt"
)
type callData struct { "github.com/wailsapp/wails/lib/messages"
BindingName string `json:"bindingName"` )
Data string `json:"data,omitempty"`
}
func init() { func init() {
messageProcessors["call"] = processCallData messageProcessors["call"] = processCallData
@@ -15,7 +12,7 @@ func init() {
func processCallData(message *ipcMessage) (*ipcMessage, error) { func processCallData(message *ipcMessage) (*ipcMessage, error) {
var payload callData var payload messages.CallData
// Decode binding call data // Decode binding call data
payloadMap := message.Payload.(map[string]interface{}) payloadMap := message.Payload.(map[string]interface{})

View File

@@ -1,13 +1,10 @@
package wails package ipc
import ( import (
"encoding/json" "encoding/json"
)
type eventData struct { "github.com/wailsapp/wails/lib/messages"
Name string `json:"name"` )
Data interface{} `json:"data"`
}
// Register the message handler // Register the message handler
func init() { func init() {
@@ -19,7 +16,7 @@ func processEventData(message *ipcMessage) (*ipcMessage, error) {
// TODO: Is it worth double checking this is actually an event message, // TODO: Is it worth double checking this is actually an event message,
// even though that's done by the caller? // even though that's done by the caller?
var payload eventData var payload messages.EventData
// Decode event data // Decode event data
payloadMap := message.Payload.(map[string]interface{}) payloadMap := message.Payload.(map[string]interface{})

View File

@@ -1,9 +1,6 @@
package wails package ipc
type logData struct { import "github.com/wailsapp/wails/lib/messages"
Level string `json:"level"`
Message string `json:"string"`
}
// Register the message handler // Register the message handler
func init() { func init() {
@@ -13,7 +10,7 @@ func init() {
// This processes the given log message // This processes the given log message
func processLogData(message *ipcMessage) (*ipcMessage, error) { func processLogData(message *ipcMessage) (*ipcMessage, error) {
var payload logData var payload messages.LogData
// Decode event data // Decode event data
payloadMap := message.Payload.(map[string]interface{}) payloadMap := message.Payload.(map[string]interface{})

View File

@@ -1,35 +1,42 @@
package wails package ipc
import ( import (
"fmt" "fmt"
"github.com/wailsapp/wails/lib/interfaces"
"github.com/wailsapp/wails/lib/logger"
"github.com/wailsapp/wails/lib/messages"
) )
type ipcManager struct { // Manager manages the IPC subsystem
renderer Renderer // The renderer type Manager struct {
renderer interfaces.Renderer // The renderer
messageQueue chan *ipcMessage messageQueue chan *ipcMessage
// quitChannel chan struct{} // quitChannel chan struct{}
// signals chan os.Signal // signals chan os.Signal
log *CustomLogger log *logger.CustomLogger
eventManager *eventManager eventManager interfaces.EventManager
bindingManager *bindingManager bindingManager interfaces.BindingManager
} }
func newIPCManager() *ipcManager { // NewManager creates a new IPC Manager
result := &ipcManager{ func NewManager() interfaces.IPCManager {
result := &Manager{
messageQueue: make(chan *ipcMessage, 100), messageQueue: make(chan *ipcMessage, 100),
// quitChannel: make(chan struct{}), // quitChannel: make(chan struct{}),
// signals: make(chan os.Signal, 1), // signals: make(chan os.Signal, 1),
log: newCustomLogger("IPC"), log: logger.NewCustomLogger("IPC"),
} }
return result return result
} }
// Sets the renderer, returns the dispatch function // BindRenderer sets the renderer, returns the dispatch function
func (i *ipcManager) bindRenderer(renderer Renderer) { func (i *Manager) BindRenderer(renderer interfaces.Renderer) {
i.renderer = renderer i.renderer = renderer
} }
func (i *ipcManager) start(eventManager *eventManager, bindingManager *bindingManager) { // Start the IPC Manager
func (i *Manager) Start(eventManager interfaces.EventManager, bindingManager interfaces.BindingManager) {
// Store manager references // Store manager references
i.eventManager = eventManager i.eventManager = eventManager
@@ -42,36 +49,36 @@ func (i *ipcManager) start(eventManager *eventManager, bindingManager *bindingMa
for running { for running {
select { select {
case incomingMessage := <-i.messageQueue: case incomingMessage := <-i.messageQueue:
i.log.DebugFields("Processing message", Fields{ i.log.DebugFields("Processing message", logger.Fields{
"1D": &incomingMessage, "1D": &incomingMessage,
}) })
switch incomingMessage.Type { switch incomingMessage.Type {
case "call": case "call":
callData := incomingMessage.Payload.(*callData) callData := incomingMessage.Payload.(*messages.CallData)
i.log.DebugFields("Processing call", Fields{ i.log.DebugFields("Processing call", logger.Fields{
"1D": &incomingMessage, "1D": &incomingMessage,
"bindingName": callData.BindingName, "bindingName": callData.BindingName,
"data": callData.Data, "data": callData.Data,
}) })
go func() { go func() {
result, err := bindingManager.processCall(callData) result, err := bindingManager.ProcessCall(callData)
i.log.DebugFields("processed call", Fields{"result": result, "err": err}) i.log.DebugFields("processed call", logger.Fields{"result": result, "err": err})
if err != nil { if err != nil {
incomingMessage.ReturnError(err.Error()) incomingMessage.ReturnError(err.Error())
} else { } else {
incomingMessage.ReturnSuccess(result) incomingMessage.ReturnSuccess(result)
} }
i.log.DebugFields("Finished processing call", Fields{ i.log.DebugFields("Finished processing call", logger.Fields{
"1D": &incomingMessage, "1D": &incomingMessage,
}) })
}() }()
case "event": case "event":
// Extract event data // Extract event data
eventData := incomingMessage.Payload.(*eventData) eventData := incomingMessage.Payload.(*messages.EventData)
// Log // Log
i.log.DebugFields("Processing event", Fields{ i.log.DebugFields("Processing event", logger.Fields{
"name": eventData.Name, "name": eventData.Name,
"data": eventData.Data, "data": eventData.Data,
}) })
@@ -80,24 +87,24 @@ func (i *ipcManager) start(eventManager *eventManager, bindingManager *bindingMa
i.eventManager.PushEvent(eventData) i.eventManager.PushEvent(eventData)
// Log // Log
i.log.DebugFields("Finished processing event", Fields{ i.log.DebugFields("Finished processing event", logger.Fields{
"name": eventData.Name, "name": eventData.Name,
}) })
case "log": case "log":
logdata := incomingMessage.Payload.(*logData) logdata := incomingMessage.Payload.(*messages.LogData)
switch logdata.Level { switch logdata.Level {
case "info": case "info":
logger.Info(logdata.Message) logger.GlobalLogger.Info(logdata.Message)
case "debug": case "debug":
logger.Debug(logdata.Message) logger.GlobalLogger.Debug(logdata.Message)
case "warning": case "warning":
logger.Warning(logdata.Message) logger.GlobalLogger.Warn(logdata.Message)
case "error": case "error":
logger.Error(logdata.Message) logger.GlobalLogger.Error(logdata.Message)
case "fatal": case "fatal":
logger.Fatal(logdata.Message) logger.GlobalLogger.Fatal(logdata.Message)
default: default:
i.log.ErrorFields("Invalid log level sent", Fields{ logger.ErrorFields("Invalid log level sent", logger.Fields{
"level": logdata.Level, "level": logdata.Level,
"message": logdata.Message, "message": logdata.Message,
}) })
@@ -107,7 +114,7 @@ func (i *ipcManager) start(eventManager *eventManager, bindingManager *bindingMa
} }
// Log // Log
i.log.DebugFields("Finished processing message", Fields{ i.log.DebugFields("Finished processing message", logger.Fields{
"1D": &incomingMessage, "1D": &incomingMessage,
}) })
// case <-manager.quitChannel: // case <-manager.quitChannel:
@@ -125,7 +132,7 @@ func (i *ipcManager) start(eventManager *eventManager, bindingManager *bindingMa
// Dispatch receives JSON encoded messages from the renderer. // Dispatch receives JSON encoded messages from the renderer.
// It processes the message to ensure that it is valid and places // It processes the message to ensure that it is valid and places
// the processed message on the message queue // the processed message on the message queue
func (i *ipcManager) Dispatch(message string) { func (i *Manager) Dispatch(message string) {
// Create a new IPC Message // Create a new IPC Message
incomingMessage, err := newIPCMessage(message, i.SendResponse) incomingMessage, err := newIPCMessage(message, i.SendResponse)
@@ -148,7 +155,7 @@ func (i *ipcManager) Dispatch(message string) {
} }
// SendResponse sends the given response back to the frontend // SendResponse sends the given response back to the frontend
func (i *ipcManager) SendResponse(response *ipcResponse) error { func (i *Manager) SendResponse(response *ipcResponse) error {
// Serialise the Message // Serialise the Message
data, err := response.Serialise() data, err := response.Serialise()

View File

@@ -1,4 +1,4 @@
package wails package ipc
import ( import (
"encoding/json" "encoding/json"

View File

@@ -1,4 +1,4 @@
package wails package ipc
import ( import (
"encoding/hex" "encoding/hex"

View File

@@ -1,4 +1,4 @@
package wails package logger
// CustomLogger is a wrapper object to logrus // CustomLogger is a wrapper object to logrus
type CustomLogger struct { type CustomLogger struct {
@@ -6,7 +6,8 @@ type CustomLogger struct {
errorOnly bool errorOnly bool
} }
func newCustomLogger(prefix string) *CustomLogger { // NewCustomLogger creates a new custom logger with the given prefix
func NewCustomLogger(prefix string) *CustomLogger {
return &CustomLogger{ return &CustomLogger{
prefix: "[" + prefix + "] ", prefix: "[" + prefix + "] ",
} }
@@ -14,90 +15,90 @@ func newCustomLogger(prefix string) *CustomLogger {
// Info level message // Info level message
func (c *CustomLogger) Info(message string) { func (c *CustomLogger) Info(message string) {
logger.Info(c.prefix + message) GlobalLogger.Info(c.prefix + message)
} }
// Infof - formatted message // Infof - formatted message
func (c *CustomLogger) Infof(message string, args ...interface{}) { func (c *CustomLogger) Infof(message string, args ...interface{}) {
logger.Infof(c.prefix+message, args...) GlobalLogger.Infof(c.prefix+message, args...)
} }
// InfoFields - message with fields // InfoFields - message with fields
func (c *CustomLogger) InfoFields(message string, fields Fields) { func (c *CustomLogger) InfoFields(message string, fields Fields) {
logger.WithFields(map[string]interface{}(fields)).Info(c.prefix + message) GlobalLogger.WithFields(map[string]interface{}(fields)).Info(c.prefix + message)
} }
// Debug level message // Debug level message
func (c *CustomLogger) Debug(message string) { func (c *CustomLogger) Debug(message string) {
logger.Debug(c.prefix + message) GlobalLogger.Debug(c.prefix + message)
} }
// Debugf - formatted message // Debugf - formatted message
func (c *CustomLogger) Debugf(message string, args ...interface{}) { func (c *CustomLogger) Debugf(message string, args ...interface{}) {
logger.Debugf(c.prefix+message, args...) GlobalLogger.Debugf(c.prefix+message, args...)
} }
// DebugFields - message with fields // DebugFields - message with fields
func (c *CustomLogger) DebugFields(message string, fields Fields) { func (c *CustomLogger) DebugFields(message string, fields Fields) {
logger.WithFields(map[string]interface{}(fields)).Debug(c.prefix + message) GlobalLogger.WithFields(map[string]interface{}(fields)).Debug(c.prefix + message)
} }
// Warn level message // Warn level message
func (c *CustomLogger) Warn(message string) { func (c *CustomLogger) Warn(message string) {
logger.Warn(c.prefix + message) GlobalLogger.Warn(c.prefix + message)
} }
// Warnf - formatted message // Warnf - formatted message
func (c *CustomLogger) Warnf(message string, args ...interface{}) { func (c *CustomLogger) Warnf(message string, args ...interface{}) {
logger.Warnf(c.prefix+message, args...) GlobalLogger.Warnf(c.prefix+message, args...)
} }
// WarnFields - message with fields // WarnFields - message with fields
func (c *CustomLogger) WarnFields(message string, fields Fields) { func (c *CustomLogger) WarnFields(message string, fields Fields) {
logger.WithFields(map[string]interface{}(fields)).Warn(c.prefix + message) GlobalLogger.WithFields(map[string]interface{}(fields)).Warn(c.prefix + message)
} }
// Error level message // Error level message
func (c *CustomLogger) Error(message string) { func (c *CustomLogger) Error(message string) {
logger.Error(c.prefix + message) GlobalLogger.Error(c.prefix + message)
} }
// Errorf - formatted message // Errorf - formatted message
func (c *CustomLogger) Errorf(message string, args ...interface{}) { func (c *CustomLogger) Errorf(message string, args ...interface{}) {
logger.Errorf(c.prefix+message, args...) GlobalLogger.Errorf(c.prefix+message, args...)
} }
// ErrorFields - message with fields // ErrorFields - message with fields
func (c *CustomLogger) ErrorFields(message string, fields Fields) { func (c *CustomLogger) ErrorFields(message string, fields Fields) {
logger.WithFields(map[string]interface{}(fields)).Error(c.prefix + message) GlobalLogger.WithFields(map[string]interface{}(fields)).Error(c.prefix + message)
} }
// Fatal level message // Fatal level message
func (c *CustomLogger) Fatal(message string) { func (c *CustomLogger) Fatal(message string) {
logger.Fatal(c.prefix + message) GlobalLogger.Fatal(c.prefix + message)
} }
// Fatalf - formatted message // Fatalf - formatted message
func (c *CustomLogger) Fatalf(message string, args ...interface{}) { func (c *CustomLogger) Fatalf(message string, args ...interface{}) {
logger.Fatalf(c.prefix+message, args...) GlobalLogger.Fatalf(c.prefix+message, args...)
} }
// FatalFields - message with fields // FatalFields - message with fields
func (c *CustomLogger) FatalFields(message string, fields Fields) { func (c *CustomLogger) FatalFields(message string, fields Fields) {
logger.WithFields(map[string]interface{}(fields)).Fatal(c.prefix + message) GlobalLogger.WithFields(map[string]interface{}(fields)).Fatal(c.prefix + message)
} }
// Panic level message // Panic level message
func (c *CustomLogger) Panic(message string) { func (c *CustomLogger) Panic(message string) {
logger.Panic(c.prefix + message) GlobalLogger.Panic(c.prefix + message)
} }
// Panicf - formatted message // Panicf - formatted message
func (c *CustomLogger) Panicf(message string, args ...interface{}) { func (c *CustomLogger) Panicf(message string, args ...interface{}) {
logger.Panicf(c.prefix+message, args...) GlobalLogger.Panicf(c.prefix+message, args...)
} }
// PanicFields - message with fields // PanicFields - message with fields
func (c *CustomLogger) PanicFields(message string, fields Fields) { func (c *CustomLogger) PanicFields(message string, fields Fields) {
logger.WithFields(map[string]interface{}(fields)).Panic(c.prefix + message) GlobalLogger.WithFields(map[string]interface{}(fields)).Panic(c.prefix + message)
} }

47
lib/logger/log.go Normal file
View File

@@ -0,0 +1,47 @@
package logger
import (
"os"
"strings"
"github.com/sirupsen/logrus"
)
// GlobalLogger is the global logger
var GlobalLogger = logrus.New()
// Fields is used by the customLogger object to output
// fields along with a message
type Fields map[string]interface{}
// Default options for the global logger
func init() {
GlobalLogger.SetOutput(os.Stdout)
GlobalLogger.SetLevel(logrus.DebugLevel)
}
// ErrorFields is a helper for logging fields to the global logger
func ErrorFields(message string, fields Fields) {
GlobalLogger.WithFields(map[string]interface{}(fields)).Error(message)
}
// SetLogLevel sets the log level to the given level
func SetLogLevel(level string) {
switch strings.ToLower(level) {
case "info":
GlobalLogger.SetLevel(logrus.InfoLevel)
case "debug":
GlobalLogger.SetLevel(logrus.DebugLevel)
case "warn":
GlobalLogger.SetLevel(logrus.WarnLevel)
case "error":
GlobalLogger.SetLevel(logrus.ErrorLevel)
case "fatal":
GlobalLogger.SetLevel(logrus.FatalLevel)
case "panic":
GlobalLogger.SetLevel(logrus.PanicLevel)
default:
GlobalLogger.SetLevel(logrus.DebugLevel)
GlobalLogger.Warnf("Log level '%s' not recognised. Setting to Debug.", level)
}
}

7
lib/messages/calldata.go Normal file
View File

@@ -0,0 +1,7 @@
package messages
// CallData represents a call to a Go function/method
type CallData struct {
BindingName string `json:"bindingName"`
Data string `json:"data,omitempty"`
}

View File

@@ -0,0 +1,7 @@
package messages
// EventData represents an event sent from the frontend
type EventData struct {
Name string `json:"name"`
Data interface{} `json:"data"`
}

Some files were not shown because too many files have changed in this diff Show More