Compare commits
183 Commits
463---keep
...
v1.13.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21bdc94941 | ||
|
|
a1bd1013cb | ||
|
|
2b6860b6c3 | ||
|
|
d4de8b4af0 | ||
|
|
a706b3f7e5 | ||
|
|
5e89392fce | ||
|
|
97160037ff | ||
|
|
97e6ef7894 | ||
|
|
c4b56e27a5 | ||
|
|
074961d139 | ||
|
|
0bbf1fd098 | ||
|
|
5329157240 | ||
|
|
ed2da4c349 | ||
|
|
1a7e762564 | ||
|
|
cb16ad1938 | ||
|
|
779095c988 | ||
|
|
eb7349efbc | ||
|
|
8ddc3e9527 | ||
|
|
0393cb3dec | ||
|
|
872b57eb4c | ||
|
|
17421552fe | ||
|
|
e8f269ca0a | ||
|
|
1b5ac3d2b6 | ||
|
|
c88aedc890 | ||
|
|
ec7fa44b44 | ||
|
|
4ce5aef237 | ||
|
|
f3c7ce2061 | ||
|
|
49a9a93e4e | ||
|
|
36feb41e3f | ||
|
|
9167508302 | ||
|
|
cbd9eca6c3 | ||
|
|
181a34f38d | ||
|
|
15556ad389 | ||
|
|
3fc0f05fab | ||
|
|
7c249e9c6b | ||
|
|
cb03409e3a | ||
|
|
40db3587cb | ||
|
|
6228328278 | ||
|
|
17a9cf4afb | ||
|
|
4a6e9d059c | ||
|
|
76b12b5b80 | ||
|
|
3567ec9865 | ||
|
|
1a3cefd180 | ||
|
|
7b603a2776 | ||
|
|
5ced28cb74 | ||
|
|
0d49a8cc83 | ||
|
|
9cd5ad69ce | ||
|
|
7dbf74c3e0 | ||
|
|
6613cff1d5 | ||
|
|
6a2700e0bf | ||
|
|
2a6162a91f | ||
|
|
4e54229dfb | ||
|
|
ce58e9eb6c | ||
|
|
3c49577d5b | ||
|
|
fb8aa8cc24 | ||
|
|
b45e04f2db | ||
|
|
026daf5e57 | ||
|
|
7c04a854da | ||
|
|
7832a3be19 | ||
|
|
39d687fa31 | ||
|
|
8a768cce77 | ||
|
|
ee04a9235d | ||
|
|
7e67562e19 | ||
|
|
25d8a8763a | ||
|
|
7929584ec5 | ||
|
|
73ee9ef530 | ||
|
|
003eecc4ff | ||
|
|
f97341abbe | ||
|
|
e2599c0f76 | ||
|
|
0c2c56e1dd | ||
|
|
39878c1a52 | ||
|
|
c0932f3fa4 | ||
|
|
dc605c1683 | ||
|
|
c7c9ace232 | ||
|
|
5be197b68f | ||
|
|
3e5c406c95 | ||
|
|
be6bebebe4 | ||
|
|
5b33ed28fd | ||
|
|
b7a59daee1 | ||
|
|
3d4ea3918b | ||
|
|
4347d950d1 | ||
|
|
5267968151 | ||
|
|
7b31c8ddd2 | ||
|
|
8e096ff0b0 | ||
|
|
6a03a5f8eb | ||
|
|
6116f5fc05 | ||
|
|
c49192e847 | ||
|
|
6fb2489dae | ||
|
|
c1acbed2c7 | ||
|
|
8f6275721a | ||
|
|
ef40a2eb8e | ||
|
|
4f7b5c71d1 | ||
|
|
49db62afd0 | ||
|
|
9098632aa3 | ||
|
|
f87a0f039a | ||
|
|
a03f5871bd | ||
|
|
46f026c04c | ||
|
|
5e2373acb1 | ||
|
|
918d6240f2 | ||
|
|
453a225427 | ||
|
|
2795684d5c | ||
|
|
e295a5abd9 | ||
|
|
fdf18b7dfa | ||
|
|
1e95d0eb44 | ||
|
|
d7f2d800de | ||
|
|
ef4d9ae97c | ||
|
|
e8a85d4cd6 | ||
|
|
84f407278c | ||
|
|
c72c6d2408 | ||
|
|
0ad0092aa2 | ||
|
|
a84f43d959 | ||
|
|
b48da620b3 | ||
|
|
ed8884a581 | ||
|
|
05d27dda64 | ||
|
|
fe2c5e8611 | ||
|
|
422ee22d0c | ||
|
|
22f94cfdb6 | ||
|
|
1e2bc5728a | ||
|
|
e0aab7c27f | ||
|
|
5d754f40de | ||
|
|
c9b26c6352 | ||
|
|
6f0696631f | ||
|
|
fefb54de12 | ||
|
|
b4224066f7 | ||
|
|
3d9ef75488 | ||
|
|
79ecb0704e | ||
|
|
8154887824 | ||
|
|
39ae91a250 | ||
|
|
861f5f2a1c | ||
|
|
89ed00d6ed | ||
|
|
1e1834158b | ||
|
|
214fcf03b9 | ||
|
|
82ac4f1358 | ||
|
|
8b7cd03428 | ||
|
|
4d2b4fec45 | ||
|
|
bc0478b2b2 | ||
|
|
d59849b952 | ||
|
|
806821ad49 | ||
|
|
a4cc95351f | ||
|
|
f851b89350 | ||
|
|
7f72189231 | ||
|
|
ef79dd95cf | ||
|
|
d49b146eaa | ||
|
|
8c051e004d | ||
|
|
c02b9ac032 | ||
|
|
35f839ae65 | ||
|
|
8a6c44963d | ||
|
|
d31c5522e9 | ||
|
|
6e5b2ce871 | ||
|
|
c2c9c331cd | ||
|
|
9d5280d4d6 | ||
|
|
0474f15c05 | ||
|
|
ba0af0c16d | ||
|
|
c9f1247284 | ||
|
|
baa661532d | ||
|
|
43a5f410d9 | ||
|
|
0ab6a93e0c | ||
|
|
485df87560 | ||
|
|
176c447e87 | ||
|
|
aa9cb5e58e | ||
|
|
9a7be38462 | ||
|
|
678c2194db | ||
|
|
9f9c9e27de | ||
|
|
01a1288364 | ||
|
|
5cd34e07b9 | ||
|
|
2290f36939 | ||
|
|
670986df5b | ||
|
|
086cd02cd4 | ||
|
|
d8c8dd57fa | ||
|
|
2d158d449a | ||
|
|
04577c242b | ||
|
|
ac0d4493d3 | ||
|
|
b123156331 | ||
|
|
23468ce7c7 | ||
|
|
f86996705b | ||
|
|
254aa664d7 | ||
|
|
c8371ee824 | ||
|
|
02e0250555 | ||
|
|
e1b025cab6 | ||
|
|
626854f1b7 | ||
|
|
98468d1c4d | ||
|
|
1062aeb136 | ||
|
|
aa93e5d8d2 |
12
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
github: [leaanthony]
|
||||||
|
patreon: # Replace with a single Patreon username
|
||||||
|
open_collective: # Replace with a single Open Collective username
|
||||||
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
|
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||||
|
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||||
|
liberapay: # Replace with a single Liberapay username
|
||||||
|
issuehunt: # Replace with a single IssueHunt username
|
||||||
|
otechie: # Replace with a single Otechie username
|
||||||
|
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||||
10
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -8,8 +8,12 @@ assignees: ''
|
|||||||
---
|
---
|
||||||
|
|
||||||
#####################################################
|
#####################################################
|
||||||
If you have a technical issue, please do not open a bug this way!
|
**If you have a technical issue, please do not open a bug this way!**
|
||||||
Please use the `wails issue` command!
|
Please use the `wails issue` command!
|
||||||
|
If you do not do this then the issue may be closed automatically.
|
||||||
|
|
||||||
|
NOTE: If your bug is related to Windows, make sure you read
|
||||||
|
the [Windows Developer Guide](https://wails.app/guides/windows/)
|
||||||
#####################################################
|
#####################################################
|
||||||
|
|
||||||
**Description**
|
**Description**
|
||||||
@@ -33,3 +37,5 @@ Please provide your platform, GO version and variables, etc
|
|||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
Add any other context about the problem here.
|
Add any other context about the problem here.
|
||||||
|
|
||||||
|
- [ ] This issue is for Windows and I have read the [Windows Developer Guide](https://wails.app/guides/windows/)
|
||||||
|
|||||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: enhancement
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
7
.gitignore
vendored
@@ -16,4 +16,9 @@ examples/**/example*
|
|||||||
cmd/wails/wails
|
cmd/wails/wails
|
||||||
.DS_Store
|
.DS_Store
|
||||||
tmp
|
tmp
|
||||||
node_modules/
|
node_modules/
|
||||||
|
v2/test/kitchensink/frontend/public
|
||||||
|
v2/internal/ffenestri/runtime.c
|
||||||
|
v2/internal/runtime/assets/desktop.js
|
||||||
|
v2/test/kitchensink/build/darwin/desktop/kitchensink
|
||||||
|
v2/test/kitchensink/frontend/package.json.md5
|
||||||
|
|||||||
@@ -29,3 +29,20 @@ Wails is what it is because of the time and effort given by these great people.
|
|||||||
* [dedo1911](https://github.com/dedo1911)
|
* [dedo1911](https://github.com/dedo1911)
|
||||||
* [Florian Didron](https://github.com/fdidron)
|
* [Florian Didron](https://github.com/fdidron)
|
||||||
* [Christopher Murphy](https://github.com/Splode)
|
* [Christopher Murphy](https://github.com/Splode)
|
||||||
|
* [Zámbó, Levente](https://github.com/Lyimmi)
|
||||||
|
* [artem](https://github.com/Unix4ever)
|
||||||
|
* [Tim Kipp](https://github.com/timkippdev)
|
||||||
|
* [Dmitry Gomzyakov](https://github.com/kyoto44)
|
||||||
|
* [Arthur Wiebe](https://github.com/artooro)
|
||||||
|
* [Ilgıt Yıldırım](https://github.com/ilgityildirim)
|
||||||
|
* [Altynbek](https://github.com/gelleson)
|
||||||
|
* [Kyle](https://github.com/kmuchmore)
|
||||||
|
* [Balakrishna Prasad Ganne](https://github.com/aayush420)
|
||||||
|
* [Charaf Rezrazi](https://github.com/Rezrazi)
|
||||||
|
* [misitebao](https://github.com/misitebao)
|
||||||
|
* [Elie Grenon](https://github.com/DrunkenPoney)
|
||||||
|
* [SophieAu](https://github.com/SophieAu)
|
||||||
|
* [Alexander Matviychuk](https://github.com/alexmat)
|
||||||
|
* [RH12503](https://github.com/RH12503)
|
||||||
|
* [hi019](https://github.com/hi019)
|
||||||
|
|
||||||
32
README.md
@@ -2,7 +2,7 @@
|
|||||||
<img src="logo_cropped.png" width="40%"><br/>
|
<img src="logo_cropped.png" width="40%"><br/>
|
||||||
</p>
|
</p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
A framework for building desktop applications using Go & Web Technologies.<br/><br/>
|
Build desktop applications using Go & Web Technologies.<br/><br/>
|
||||||
<a href="https://github.com/wailsapp/wails/blob/master/LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg"></a>
|
<a href="https://github.com/wailsapp/wails/blob/master/LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg"></a>
|
||||||
<a href="https://goreportcard.com/report/github.com/wailsapp/wails"><img src="https://goreportcard.com/badge/github.com/wailsapp/wails"/></a>
|
<a href="https://goreportcard.com/report/github.com/wailsapp/wails"><img src="https://goreportcard.com/badge/github.com/wailsapp/wails"/></a>
|
||||||
<a href="http://godoc.org/github.com/wailsapp/wails"><img src="https://img.shields.io/badge/godoc-reference-blue.svg"/></a>
|
<a href="http://godoc.org/github.com/wailsapp/wails"><img src="https://img.shields.io/badge/godoc-reference-blue.svg"/></a>
|
||||||
@@ -12,7 +12,6 @@
|
|||||||
<a href="https://houndci.com"><img src="https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg"/></a>
|
<a href="https://houndci.com"><img src="https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg"/></a>
|
||||||
<a href="https://github.com/avelino/awesome-go" rel="nofollow"><img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome"></a>
|
<a href="https://github.com/avelino/awesome-go" rel="nofollow"><img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome"></a>
|
||||||
<a href="https://github.com/wailsapp/wails/workflows/release/badge.svg?branch=master" rel="nofollow"><img src="https://github.com/wailsapp/wails/workflows/release/badge.svg?branch=master" alt="Release Pipelines"></a>
|
<a href="https://github.com/wailsapp/wails/workflows/release/badge.svg?branch=master" rel="nofollow"><img src="https://github.com/wailsapp/wails/workflows/release/badge.svg?branch=master" alt="Release Pipelines"></a>
|
||||||
<a href="https://github.com/wailsapp/wails/workflows/latest-pre/badge.svg?branch=masterr" rel="nofollow"><img src="https://github.com/wailsapp/wails/workflows/latest-pre/badge.svg?branch=master" alt="Pre-Release Pipelines"></a>
|
|
||||||
</p>
|
</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!
|
||||||
@@ -21,7 +20,7 @@ The official docs can be found at [https://wails.app](https://wails.app).
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Use standard Go libraries/frameworks for the backend
|
- Use standard Go for the backend
|
||||||
- Use any frontend technology to build your UI
|
- Use any frontend technology to build your UI
|
||||||
- Quickly create Vue, Vuetify or React frontends for your Go programs
|
- Quickly create Vue, Vuetify or React frontends for your Go programs
|
||||||
- Expose Go methods/functions to the frontend via a single bind command
|
- Expose Go methods/functions to the frontend via a single bind command
|
||||||
@@ -31,6 +30,23 @@ The official docs can be found at [https://wails.app](https://wails.app).
|
|||||||
- Powerful cli tool
|
- Powerful cli tool
|
||||||
- Multiplatform
|
- Multiplatform
|
||||||
|
|
||||||
|
## Sponsors
|
||||||
|
|
||||||
|
This project is supported by these kind people:
|
||||||
|
|
||||||
|
<a href="https://pace.dev" style="width:100px"><img src="pace.jpeg" width="100"/></a>
|
||||||
|
<a href="https://github.com/tc-hib" style="width:50px;border-radius: 50%">
|
||||||
|
<img src="https://github.com/tc-hib.png?size=50" width="50" style="border-radius: 50%"/>
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/picatz" style="width:50px;border-radius: 50%">
|
||||||
|
<img src="https://github.com/picatz.png?size=50" width="50" style="border-radius: 50%"/>
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/tylertravisty" style="width:50px;border-radius: 50%">
|
||||||
|
<img src="https://github.com/tylertravisty.png?size=50" width="50" style="border-radius: 50%"/>
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/picatz" style="width:50px;border-radius: 50%">
|
||||||
|
<img src="https://github.com/picatz.png?size=50" width="50" style="border-radius: 50%"/>
|
||||||
|
</a>
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@@ -57,7 +73,7 @@ _Ubuntu: 16.04, 18.04, 19.04_
|
|||||||
|
|
||||||
_Also succesfully tested on: Zorin 15, Parrot 4.7, Linuxmint 19, Elementary 5, Kali, Neon_, Pop!_OS
|
_Also succesfully tested on: Zorin 15, Parrot 4.7, Linuxmint 19, Elementary 5, Kali, Neon_, Pop!_OS
|
||||||
|
|
||||||
#### Arch Linux / ArchLabs
|
#### Arch Linux / ArchLabs / Ctlos Linux
|
||||||
|
|
||||||
`sudo pacman -S webkit2gtk gtk3`
|
`sudo pacman -S webkit2gtk gtk3`
|
||||||
|
|
||||||
@@ -148,7 +164,13 @@ This project was mainly coded to the following albums:
|
|||||||
|
|
||||||
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_large)
|
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_large)
|
||||||
|
|
||||||
## Special Thank You
|
## Special Thanks
|
||||||
|
|
||||||
|
<p align="center" style="text-align: center">
|
||||||
|
<a href="https://pace.dev"><img src="pace.jpeg"/></a><br/>
|
||||||
|
A *huge* thanks to <a href="https://pace.dev">Pace</a> for sponsoring the project and helping the efforts to get Wails ported to Apple Silicon!<br/><br/>
|
||||||
|
If you are looking for a Project Management tool that's powerful but quick and easy to use, check them out!<br/><br/>
|
||||||
|
</p>
|
||||||
|
|
||||||
<p align="center" style="text-align: center">
|
<p align="center" style="text-align: center">
|
||||||
A special thank you to JetBrains for donating licenses to us!<br/><br/>
|
A special thank you to JetBrains for donating licenses to us!<br/><br/>
|
||||||
|
|||||||
19
app.go
@@ -2,7 +2,6 @@ package wails
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/syossan27/tebata"
|
"github.com/syossan27/tebata"
|
||||||
@@ -13,6 +12,7 @@ import (
|
|||||||
"github.com/wailsapp/wails/lib/ipc"
|
"github.com/wailsapp/wails/lib/ipc"
|
||||||
"github.com/wailsapp/wails/lib/logger"
|
"github.com/wailsapp/wails/lib/logger"
|
||||||
"github.com/wailsapp/wails/lib/renderer"
|
"github.com/wailsapp/wails/lib/renderer"
|
||||||
|
wailsruntime "github.com/wailsapp/wails/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
// -------------------------------- Compile time Flags ------------------------------
|
// -------------------------------- Compile time Flags ------------------------------
|
||||||
@@ -20,6 +20,16 @@ import (
|
|||||||
// BuildMode indicates what mode we are in
|
// BuildMode indicates what mode we are in
|
||||||
var BuildMode = cmd.BuildModeProd
|
var BuildMode = cmd.BuildModeProd
|
||||||
|
|
||||||
|
// Runtime is the Go Runtime struct
|
||||||
|
type Runtime = wailsruntime.Runtime
|
||||||
|
|
||||||
|
// Store is a state store used for syncing with
|
||||||
|
// the front end
|
||||||
|
type Store = wailsruntime.Store
|
||||||
|
|
||||||
|
// CustomLogger is a specialised logger
|
||||||
|
type CustomLogger = logger.CustomLogger
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// App defines the main application struct
|
// App defines the main application struct
|
||||||
@@ -106,11 +116,6 @@ func (a *App) start() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable console for Windows debug builds
|
|
||||||
if runtime.GOOS == "windows" && BuildMode == cmd.BuildModeDebug {
|
|
||||||
a.renderer.EnableConsole()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start signal handler
|
// Start signal handler
|
||||||
t := tebata.New(os.Interrupt, os.Kill, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL)
|
t := tebata.New(os.Interrupt, os.Kill, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL)
|
||||||
t.Reserve(func() {
|
t.Reserve(func() {
|
||||||
@@ -125,7 +130,7 @@ func (a *App) start() error {
|
|||||||
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 = wailsruntime.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)
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ func (g *GitHubHelper) GetVersionTags() ([]*SemanticVersion, error) {
|
|||||||
result := []*SemanticVersion{}
|
result := []*SemanticVersion{}
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
resp, err := http.Get("https://api.github.com/repos/wailsapp/wails/tags")
|
resp, err := http.Get("https://api.github.com/repos/wailsapp/wails/releases")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ import (
|
|||||||
"github.com/leaanthony/spinner"
|
"github.com/leaanthony/spinner"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const xgoVersion = "1.0.1"
|
||||||
|
|
||||||
var fs = NewFSHelper()
|
var fs = NewFSHelper()
|
||||||
|
|
||||||
// ValidateFrontendConfig checks if the frontend config is valid
|
// ValidateFrontendConfig checks if the frontend config is valid
|
||||||
@@ -90,16 +92,17 @@ func InitializeCrossCompilation(verbose bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var packSpinner *spinner.Spinner
|
var packSpinner *spinner.Spinner
|
||||||
|
msg := fmt.Sprintf("Pulling wailsapp/xgo:%s docker image... (may take a while)", xgoVersion)
|
||||||
if !verbose {
|
if !verbose {
|
||||||
packSpinner = spinner.New("Pulling wailsapp/xgo:latest docker image... (may take a while)")
|
packSpinner = spinner.New(msg)
|
||||||
packSpinner.SetSpinSpeed(50)
|
packSpinner.SetSpinSpeed(50)
|
||||||
packSpinner.Start()
|
packSpinner.Start()
|
||||||
} else {
|
} else {
|
||||||
println("Pulling wailsapp/xgo:latest docker image... (may take a while)")
|
println(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := NewProgramHelper(verbose).RunCommandArray([]string{"docker",
|
err := NewProgramHelper(verbose).RunCommandArray([]string{"docker",
|
||||||
"pull", "wailsapp/xgo:latest"})
|
"pull", fmt.Sprintf("wailsapp/xgo:%s", xgoVersion)})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if packSpinner != nil {
|
if packSpinner != nil {
|
||||||
@@ -114,7 +117,7 @@ func InitializeCrossCompilation(verbose bool) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildDocker builds the project using the cross compiling wailsapp/xgo:latest container
|
// BuildDocker builds the project using the cross compiling wailsapp/xgo:<xgoVersion> container
|
||||||
func BuildDocker(binaryName string, buildMode string, projectOptions *ProjectOptions) error {
|
func BuildDocker(binaryName string, buildMode string, projectOptions *ProjectOptions) error {
|
||||||
var packSpinner *spinner.Spinner
|
var packSpinner *spinner.Spinner
|
||||||
if buildMode == BuildModeBridge {
|
if buildMode == BuildModeBridge {
|
||||||
@@ -140,24 +143,31 @@ func BuildDocker(binaryName string, buildMode string, projectOptions *ProjectOpt
|
|||||||
"-v", fmt.Sprintf("%s:/build", filepath.Join(fs.Cwd(), "build")),
|
"-v", fmt.Sprintf("%s:/build", filepath.Join(fs.Cwd(), "build")),
|
||||||
"-v", fmt.Sprintf("%s:/source", fs.Cwd()),
|
"-v", fmt.Sprintf("%s:/source", fs.Cwd()),
|
||||||
"-e", fmt.Sprintf("LOCAL_USER_ID=%v", userid),
|
"-e", fmt.Sprintf("LOCAL_USER_ID=%v", userid),
|
||||||
|
"-e", fmt.Sprintf("FLAG_TAGS=%s", projectOptions.Tags),
|
||||||
"-e", fmt.Sprintf("FLAG_LDFLAGS=%s", ldFlags(projectOptions, buildMode)),
|
"-e", fmt.Sprintf("FLAG_LDFLAGS=%s", ldFlags(projectOptions, buildMode)),
|
||||||
"-e", "FLAG_V=false",
|
"-e", "FLAG_V=false",
|
||||||
"-e", "FLAG_X=false",
|
"-e", "FLAG_X=false",
|
||||||
"-e", "FLAG_RACE=false",
|
"-e", "FLAG_RACE=false",
|
||||||
"-e", "FLAG_BUILDMODE=default",
|
"-e", "FLAG_BUILDMODE=default",
|
||||||
"-e", "FLAG_TRIMPATH=false",
|
"-e", "FLAG_TRIMPATH=false",
|
||||||
"-e", fmt.Sprintf("TARGETS=%s", projectOptions.Platform+"/"+projectOptions.Architecture),
|
"-e", fmt.Sprintf("TARGETS=%s/%s", projectOptions.Platform, projectOptions.Architecture),
|
||||||
"-e", "GOPROXY=",
|
"-e", "GOPROXY=",
|
||||||
"-e", "GO111MODULE=on",
|
"-e", "GO111MODULE=on",
|
||||||
"wailsapp/xgo:latest",
|
|
||||||
".",
|
|
||||||
} {
|
} {
|
||||||
buildCommand.Add(arg)
|
buildCommand.Add(arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if projectOptions.GoPath != "" {
|
||||||
|
buildCommand.Add("-v")
|
||||||
|
buildCommand.Add(fmt.Sprintf("%s:/go", projectOptions.GoPath))
|
||||||
|
}
|
||||||
|
|
||||||
|
buildCommand.Add(fmt.Sprintf("wailsapp/xgo:%s", xgoVersion))
|
||||||
|
buildCommand.Add(".")
|
||||||
|
|
||||||
compileMessage := fmt.Sprintf(
|
compileMessage := fmt.Sprintf(
|
||||||
"Packing + Compiling project for %s/%s using docker image wailsapp/xgo:latest",
|
"Packing + Compiling project for %s/%s using docker image wailsapp/xgo:%s",
|
||||||
projectOptions.Platform, projectOptions.Architecture)
|
projectOptions.Platform, projectOptions.Architecture, xgoVersion)
|
||||||
|
|
||||||
if buildMode == BuildModeDebug {
|
if buildMode == BuildModeDebug {
|
||||||
compileMessage += " (Debug Mode)"
|
compileMessage += " (Debug Mode)"
|
||||||
@@ -216,10 +226,6 @@ func BuildNative(binaryName string, forceRebuild bool, buildMode string, project
|
|||||||
buildCommand.Add("go")
|
buildCommand.Add("go")
|
||||||
|
|
||||||
buildCommand.Add("build")
|
buildCommand.Add("build")
|
||||||
if buildMode == BuildModeBridge {
|
|
||||||
// Ignore errors
|
|
||||||
buildCommand.Add("-i")
|
|
||||||
}
|
|
||||||
|
|
||||||
if binaryName != "" {
|
if binaryName != "" {
|
||||||
// Alter binary name based on OS
|
// Alter binary name based on OS
|
||||||
@@ -243,6 +249,10 @@ func BuildNative(binaryName string, forceRebuild bool, buildMode string, project
|
|||||||
|
|
||||||
buildCommand.AddSlice([]string{"-ldflags", ldFlags(projectOptions, buildMode)})
|
buildCommand.AddSlice([]string{"-ldflags", ldFlags(projectOptions, buildMode)})
|
||||||
|
|
||||||
|
if projectOptions.Tags != "" {
|
||||||
|
buildCommand.AddSlice([]string{"--tags", projectOptions.Tags})
|
||||||
|
}
|
||||||
|
|
||||||
if projectOptions.Verbose {
|
if projectOptions.Verbose {
|
||||||
fmt.Printf("Command: %v\n", buildCommand.AsSlice())
|
fmt.Printf("Command: %v\n", buildCommand.AsSlice())
|
||||||
}
|
}
|
||||||
@@ -293,9 +303,11 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
|
|||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if projectOptions.Platform == "windows" {
|
// Removed by popular demand
|
||||||
helper.CleanWindows(projectOptions)
|
// TODO: Potentially add a flag to cleanup
|
||||||
}
|
// if projectOptions.Platform == "windows" {
|
||||||
|
// helper.CleanWindows(projectOptions)
|
||||||
|
// }
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if projectOptions.CrossCompile {
|
if projectOptions.CrossCompile {
|
||||||
@@ -528,6 +540,9 @@ func InstallProdRuntime(projectDir string, projectOptions *ProjectOptions) error
|
|||||||
func ServeProject(projectOptions *ProjectOptions, logger *Logger) error {
|
func ServeProject(projectOptions *ProjectOptions, logger *Logger) error {
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
|
if projectOptions.Platform == "windows" {
|
||||||
|
logger.Yellow("*** Please note: Windows builds use mshtml which is only compatible with IE11. We strongly recommend only using IE11 when running 'wails serve'! For more information, please read https://wails.app/guides/windows/ ***")
|
||||||
|
}
|
||||||
logger.Green(">>>>> To connect, you will need to run '" + projectOptions.FrontEnd.Serve + "' in the '" + projectOptions.FrontEnd.Dir + "' directory <<<<<")
|
logger.Green(">>>>> To connect, you will need to run '" + projectOptions.FrontEnd.Serve + "' in the '" + projectOptions.FrontEnd.Dir + "' directory <<<<<")
|
||||||
}()
|
}()
|
||||||
location, err := filepath.Abs(filepath.Join("build", projectOptions.BinaryName))
|
location, err := filepath.Abs(filepath.Join("build", projectOptions.BinaryName))
|
||||||
@@ -559,6 +574,10 @@ func ldFlags(po *ProjectOptions, buildMode string) string {
|
|||||||
ldflags += "-H windowsgui "
|
ldflags += "-H windowsgui "
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if po.UseFirebug {
|
||||||
|
ldflags += "-X github.com/wailsapp/wails/lib/renderer.UseFirebug=true "
|
||||||
|
}
|
||||||
|
|
||||||
ldflags += "-X github.com/wailsapp/wails.BuildMode=" + buildMode
|
ldflags += "-X github.com/wailsapp/wails.BuildMode=" + buildMode
|
||||||
|
|
||||||
// Add additional ldflags passed in via the `ldflags` cli flag
|
// Add additional ldflags passed in via the `ldflags` cli flag
|
||||||
@@ -576,3 +595,9 @@ func ldFlags(po *ProjectOptions, buildMode string) string {
|
|||||||
}
|
}
|
||||||
return ldflags
|
return ldflags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getGitConfigValue(key string) (string, error) {
|
||||||
|
output, err := exec.Command("git", "config", "--get", "--null", key).Output()
|
||||||
|
// When using --null git appends a null character (\u0000) to the command output
|
||||||
|
return strings.TrimRight(string(output), "\u0000"), err
|
||||||
|
}
|
||||||
|
|||||||
23
cmd/linux.go
@@ -63,6 +63,12 @@ const (
|
|||||||
PopOS
|
PopOS
|
||||||
// Solus distribution
|
// Solus distribution
|
||||||
Solus
|
Solus
|
||||||
|
// Ctlos Linux distribution
|
||||||
|
Ctlos
|
||||||
|
// EndeavourOS linux distribution
|
||||||
|
EndeavourOS
|
||||||
|
// Crux linux distribution
|
||||||
|
Crux
|
||||||
)
|
)
|
||||||
|
|
||||||
// DistroInfo contains all the information relating to a linux distribution
|
// DistroInfo contains all the information relating to a linux distribution
|
||||||
@@ -129,6 +135,8 @@ func parseOsRelease(osRelease string) *DistroInfo {
|
|||||||
result.Distribution = Arch
|
result.Distribution = Arch
|
||||||
case "archlabs":
|
case "archlabs":
|
||||||
result.Distribution = ArchLabs
|
result.Distribution = ArchLabs
|
||||||
|
case "ctlos":
|
||||||
|
result.Distribution = Ctlos
|
||||||
case "debian":
|
case "debian":
|
||||||
result.Distribution = Debian
|
result.Distribution = Debian
|
||||||
case "ubuntu":
|
case "ubuntu":
|
||||||
@@ -167,6 +175,10 @@ func parseOsRelease(osRelease string) *DistroInfo {
|
|||||||
result.Distribution = PopOS
|
result.Distribution = PopOS
|
||||||
case "solus":
|
case "solus":
|
||||||
result.Distribution = Solus
|
result.Distribution = Solus
|
||||||
|
case "endeavouros":
|
||||||
|
result.Distribution = EndeavourOS
|
||||||
|
case "crux":
|
||||||
|
result.Distribution = Crux
|
||||||
default:
|
default:
|
||||||
result.Distribution = Unknown
|
result.Distribution = Unknown
|
||||||
}
|
}
|
||||||
@@ -247,6 +259,17 @@ func RpmInstalled(packageName string) (bool, error) {
|
|||||||
return exitCode == 0, nil
|
return exitCode == 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PrtGetInstalled uses prt-get to see if a package is installed
|
||||||
|
func PrtGetInstalled(packageName string) (bool, error) {
|
||||||
|
program := NewProgramHelper()
|
||||||
|
prtget := program.FindProgram("prt-get")
|
||||||
|
if prtget == nil {
|
||||||
|
return false, fmt.Errorf("cannot check dependencies: prt-get not found")
|
||||||
|
}
|
||||||
|
_, _, exitCode, _ := prtget.Run("isinst", packageName)
|
||||||
|
return exitCode == 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
// RequestSupportForDistribution promts the user to submit a request to support their
|
// RequestSupportForDistribution promts the user to submit a request to support their
|
||||||
// currently unsupported distribution
|
// currently unsupported distribution
|
||||||
func RequestSupportForDistribution(distroInfo *DistroInfo) error {
|
func RequestSupportForDistribution(distroInfo *DistroInfo) error {
|
||||||
|
|||||||
@@ -193,7 +193,25 @@ distributions:
|
|||||||
name: ArchLabs
|
name: ArchLabs
|
||||||
gccversioncommand: *gccdumpversion
|
gccversioncommand: *gccdumpversion
|
||||||
programs: *archdefaultprograms
|
programs: *archdefaultprograms
|
||||||
libraries: *archdefaultlibraries
|
libraries: *archdefaultlibraries
|
||||||
|
ctlos:
|
||||||
|
id: ctlos
|
||||||
|
releases:
|
||||||
|
default:
|
||||||
|
version: default
|
||||||
|
name: Ctlos Linux
|
||||||
|
gccversioncommand: *gccdumpversion
|
||||||
|
programs: *archdefaultprograms
|
||||||
|
libraries: *archdefaultlibraries
|
||||||
|
endeavouros:
|
||||||
|
id: endeavouros
|
||||||
|
releases:
|
||||||
|
default:
|
||||||
|
version: default
|
||||||
|
name: EndeavourOS
|
||||||
|
gccversioncommand: *gccdumpversion
|
||||||
|
programs: *archdefaultprograms
|
||||||
|
libraries: *archdefaultlibraries
|
||||||
manjaro:
|
manjaro:
|
||||||
id: manjaro
|
id: manjaro
|
||||||
releases:
|
releases:
|
||||||
@@ -289,3 +307,22 @@ distributions:
|
|||||||
gccversioncommand: *gccdumpfullversion
|
gccversioncommand: *gccdumpfullversion
|
||||||
programs: *opensusedefaultprograms
|
programs: *opensusedefaultprograms
|
||||||
libraries: *opensusedefaultlibraries
|
libraries: *opensusedefaultlibraries
|
||||||
|
crux:
|
||||||
|
id: crux
|
||||||
|
releases:
|
||||||
|
default:
|
||||||
|
version: default
|
||||||
|
name: Crux Linux
|
||||||
|
gccversioncommand: *gccdumpversion
|
||||||
|
programs:
|
||||||
|
- name: gcc
|
||||||
|
help: Please install with `sudo prt-get depinst gcc-c++ make` and try again
|
||||||
|
- name: pkg-config
|
||||||
|
help: Please install with `sudo prt-get depinst pkg-config` and try again
|
||||||
|
- name: npm
|
||||||
|
help: Please install with `sudo prt-get depinst nodejs` and try again
|
||||||
|
libraries:
|
||||||
|
- name: gtk3
|
||||||
|
help: Please install with `sudo prt-get depinst gtk3` and try again
|
||||||
|
- name: webkitgtk
|
||||||
|
help: Please install with `sudo prt-get depinst webkitgtk` and try again
|
||||||
|
|||||||
@@ -212,6 +212,8 @@ func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
|
|||||||
packageID := strings.Join([]string{"wails", name, version}, ".")
|
packageID := strings.Join([]string{"wails", name, version}, ".")
|
||||||
plistData := newPlistData(name, exe, packageID, version, author)
|
plistData := newPlistData(name, exe, packageID, version, author)
|
||||||
appname := po.Name + ".app"
|
appname := po.Name + ".app"
|
||||||
|
plistFilename := path.Join(build, appname, "Contents", "Info.plist")
|
||||||
|
customPlist := path.Join(b.fs.Cwd(), "info.plist")
|
||||||
|
|
||||||
// Check binary exists
|
// Check binary exists
|
||||||
source := path.Join(build, exe)
|
source := path.Join(build, exe)
|
||||||
@@ -230,28 +232,48 @@ func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
|
|||||||
// Remove the existing package
|
// Remove the existing package
|
||||||
os.RemoveAll(appname)
|
os.RemoveAll(appname)
|
||||||
|
|
||||||
|
// Create directories
|
||||||
exeDir := path.Join(build, appname, "/Contents/MacOS")
|
exeDir := path.Join(build, appname, "/Contents/MacOS")
|
||||||
b.fs.MkDirs(exeDir, 0755)
|
b.fs.MkDirs(exeDir, 0755)
|
||||||
resourceDir := path.Join(build, appname, "/Contents/Resources")
|
resourceDir := path.Join(build, appname, "/Contents/Resources")
|
||||||
b.fs.MkDirs(resourceDir, 0755)
|
b.fs.MkDirs(resourceDir, 0755)
|
||||||
tmpl := template.New("infoPlist")
|
|
||||||
plistFile := filepath.Join(b.getPackageFileBaseDir(), "info.plist")
|
|
||||||
infoPlist, err := ioutil.ReadFile(plistFile)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
tmpl.Parse(string(infoPlist))
|
|
||||||
|
|
||||||
// Write the template to a buffer
|
// Do we have a custom plist in the project directory?
|
||||||
var tpl bytes.Buffer
|
if !fs.FileExists(customPlist) {
|
||||||
err = tmpl.Execute(&tpl, plistData)
|
|
||||||
if err != nil {
|
// No - create a new plist from our defaults
|
||||||
return err
|
tmpl := template.New("infoPlist")
|
||||||
}
|
plistFile := filepath.Join(b.getPackageFileBaseDir(), "info.plist")
|
||||||
filename := path.Join(build, appname, "Contents", "Info.plist")
|
infoPlist, err := ioutil.ReadFile(plistFile)
|
||||||
err = ioutil.WriteFile(filename, tpl.Bytes(), 0644)
|
if err != nil {
|
||||||
if err != nil {
|
return err
|
||||||
return err
|
}
|
||||||
|
tmpl.Parse(string(infoPlist))
|
||||||
|
|
||||||
|
// Write the template to a buffer
|
||||||
|
var tpl bytes.Buffer
|
||||||
|
err = tmpl.Execute(&tpl, plistData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save to the package
|
||||||
|
err = ioutil.WriteFile(plistFilename, tpl.Bytes(), 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also write to project directory for customisation
|
||||||
|
err = ioutil.WriteFile(customPlist, tpl.Bytes(), 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Yes - we have a plist. Copy it to the package verbatim
|
||||||
|
err = fs.CopyFile(customPlist, plistFilename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy executable
|
// Copy executable
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -150,6 +151,7 @@ type ProjectOptions struct {
|
|||||||
Template string `json:"-"`
|
Template string `json:"-"`
|
||||||
BinaryName string `json:"binaryname"`
|
BinaryName string `json:"binaryname"`
|
||||||
FrontEnd *frontend `json:"frontend,omitempty"`
|
FrontEnd *frontend `json:"frontend,omitempty"`
|
||||||
|
Tags string `json:"tags"`
|
||||||
NPMProjectName string `json:"-"`
|
NPMProjectName string `json:"-"`
|
||||||
system *SystemHelper
|
system *SystemHelper
|
||||||
log *Logger
|
log *Logger
|
||||||
@@ -162,6 +164,25 @@ type ProjectOptions struct {
|
|||||||
Platform string
|
Platform string
|
||||||
Architecture string
|
Architecture string
|
||||||
LdFlags string
|
LdFlags string
|
||||||
|
GoPath string
|
||||||
|
UseFirebug bool
|
||||||
|
|
||||||
|
// Supported platforms
|
||||||
|
Platforms []string `json:"platforms,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PlatformSupported returns true if the template is supported
|
||||||
|
// on the current platform
|
||||||
|
func (po *ProjectOptions) PlatformSupported() bool {
|
||||||
|
|
||||||
|
// Default is all platforms supported
|
||||||
|
if len(po.Platforms) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the platform is in the list
|
||||||
|
platformsSupported := slicer.String(po.Platforms)
|
||||||
|
return platformsSupported.Contains(runtime.GOOS)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defaults sets the default project template
|
// Defaults sets the default project template
|
||||||
@@ -232,13 +253,16 @@ func (po *ProjectOptions) PromptForInputs() error {
|
|||||||
for _, k := range keys {
|
for _, k := range keys {
|
||||||
templateDetail := templateDetails[k]
|
templateDetail := templateDetails[k]
|
||||||
templateList.Add(templateDetail)
|
templateList.Add(templateDetail)
|
||||||
|
if !templateDetail.Metadata.PlatformSupported() {
|
||||||
|
templateDetail.Metadata.Name = "* " + templateDetail.Metadata.Name
|
||||||
|
}
|
||||||
options.Add(fmt.Sprintf("%s - %s", templateDetail.Metadata.Name, templateDetail.Metadata.ShortDescription))
|
options.Add(fmt.Sprintf("%s - %s", templateDetail.Metadata.Name, templateDetail.Metadata.ShortDescription))
|
||||||
}
|
}
|
||||||
|
|
||||||
templateIndex := 0
|
templateIndex := 0
|
||||||
|
|
||||||
if len(options.AsSlice()) > 1 {
|
if len(options.AsSlice()) > 1 {
|
||||||
templateIndex = PromptSelection("Please select a template", options.AsSlice(), 0)
|
templateIndex = PromptSelection("Please select a template (* means unsupported on current platform)", options.AsSlice(), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(templateList.AsSlice()) == 0 {
|
if len(templateList.AsSlice()) == 0 {
|
||||||
@@ -249,6 +273,10 @@ func (po *ProjectOptions) PromptForInputs() error {
|
|||||||
po.selectedTemplate = templateList.AsSlice()[templateIndex].(*TemplateDetails)
|
po.selectedTemplate = templateList.AsSlice()[templateIndex].(*TemplateDetails)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
po.selectedTemplate.Metadata.Name = strings.TrimPrefix(po.selectedTemplate.Metadata.Name, "* ")
|
||||||
|
if !po.selectedTemplate.Metadata.PlatformSupported() {
|
||||||
|
println("WARNING: This template is unsupported on this platform!")
|
||||||
|
}
|
||||||
fmt.Println("Template: " + po.selectedTemplate.Metadata.Name)
|
fmt.Println("Template: " + po.selectedTemplate.Metadata.Name)
|
||||||
|
|
||||||
// Setup NPM Project name
|
// Setup NPM Project name
|
||||||
@@ -371,5 +399,9 @@ func processTemplateMetadata(templateMetadata *TemplateMetadata, po *ProjectOpti
|
|||||||
}
|
}
|
||||||
po.FrontEnd.Serve = templateMetadata.Serve
|
po.FrontEnd.Serve = templateMetadata.Serve
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save platforms
|
||||||
|
po.Platforms = templateMetadata.Platforms
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,11 +24,19 @@ func NewSemanticVersion(version string) (*SemanticVersion, error) {
|
|||||||
|
|
||||||
// IsRelease returns true if it's a release version
|
// IsRelease returns true if it's a release version
|
||||||
func (s *SemanticVersion) IsRelease() bool {
|
func (s *SemanticVersion) IsRelease() bool {
|
||||||
|
// Limit to v1
|
||||||
|
if s.Version.Major() != 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return len(s.Version.Prerelease()) == 0 && len(s.Version.Metadata()) == 0
|
return len(s.Version.Prerelease()) == 0 && len(s.Version.Metadata()) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsPreRelease returns true if it's a prerelease version
|
// IsPreRelease returns true if it's a prerelease version
|
||||||
func (s *SemanticVersion) IsPreRelease() bool {
|
func (s *SemanticVersion) IsPreRelease() bool {
|
||||||
|
// Limit to v1
|
||||||
|
if s.Version.Major() != 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return len(s.Version.Prerelease()) > 0
|
return len(s.Version.Prerelease()) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
65
cmd/semver_test.go
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSemanticVersion_IsPreRelease(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
version string
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
{"v1.6.7-pre0", "v1.6.7-pre0", true},
|
||||||
|
{"v2.6.7+pre0", "v2.6.7+pre0", false},
|
||||||
|
{"v2.6.7", "v2.6.7", false},
|
||||||
|
{"v2.0.0+alpha.1", "v2.0.0+alpha.1", false},
|
||||||
|
{"v2.0.0-alpha.1", "v2.0.0-alpha.1", false},
|
||||||
|
{"v1.6.7", "v1.6.7", false},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
semanticversion, err := NewSemanticVersion(tt.version)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Invalid semantic version: %s", semanticversion)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s := &SemanticVersion{
|
||||||
|
Version: semanticversion.Version,
|
||||||
|
}
|
||||||
|
if got := s.IsPreRelease(); got != tt.want {
|
||||||
|
t.Errorf("IsPreRelease() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSemanticVersion_IsRelease(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
version string
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
{"v1.6.7", "v1.6.7", true},
|
||||||
|
{"v2.6.7-pre0", "v2.6.7-pre0", false},
|
||||||
|
{"v2.6.7", "v2.6.7", false},
|
||||||
|
{"v2.6.7+release", "v2.6.7+release", false},
|
||||||
|
{"v2.0.0-alpha.1", "v2.0.0-alpha.1", false},
|
||||||
|
{"v1.6.7-pre0", "v1.6.7-pre0", false},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
semanticversion, err := NewSemanticVersion(tt.version)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Invalid semantic version: %s", semanticversion)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s := &SemanticVersion{
|
||||||
|
Version: semanticversion.Version,
|
||||||
|
}
|
||||||
|
if got := s.IsRelease(); got != tt.want {
|
||||||
|
t.Errorf("IsRelease() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,13 +37,13 @@ func NewSystemHelper() *SystemHelper {
|
|||||||
// setSystemDirs calculates the system directories it is interested in
|
// setSystemDirs calculates the system directories it is interested in
|
||||||
func (s *SystemHelper) setSystemDirs() {
|
func (s *SystemHelper) setSystemDirs() {
|
||||||
var err error
|
var err error
|
||||||
s.homeDir, err = os.UserConfigDir()
|
s.homeDir, err = os.UserHomeDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Cannot find home directory! Please file a bug report!")
|
log.Fatal("Cannot find home directory! Please file a bug report!")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: A better config system
|
// TODO: A better config system
|
||||||
s.wailsSystemDir = filepath.Join(s.homeDir, "wails")
|
s.wailsSystemDir = filepath.Join(s.homeDir, ".wails")
|
||||||
s.wailsSystemConfig = filepath.Join(s.wailsSystemDir, s.configFilename)
|
s.wailsSystemConfig = filepath.Join(s.wailsSystemDir, s.configFilename)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,11 +99,16 @@ func (s *SystemHelper) setup() error {
|
|||||||
|
|
||||||
if config.Name != "" {
|
if config.Name != "" {
|
||||||
systemConfig["name"] = PromptRequired("What is your name", config.Name)
|
systemConfig["name"] = PromptRequired("What is your name", config.Name)
|
||||||
|
} else if n, err := getGitConfigValue("user.name"); err == nil && n != "" {
|
||||||
|
systemConfig["name"] = PromptRequired("What is your name", n)
|
||||||
} else {
|
} else {
|
||||||
systemConfig["name"] = PromptRequired("What is your name")
|
systemConfig["name"] = PromptRequired("What is your name")
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Email != "" {
|
if config.Email != "" {
|
||||||
systemConfig["email"] = PromptRequired("What is your email address", config.Email)
|
systemConfig["email"] = PromptRequired("What is your email address", config.Email)
|
||||||
|
} else if e, err := getGitConfigValue("user.email"); err == nil && e != "" {
|
||||||
|
systemConfig["email"] = PromptRequired("What is your email address", e)
|
||||||
} else {
|
} else {
|
||||||
systemConfig["email"] = PromptRequired("What is your email address")
|
systemConfig["email"] = PromptRequired("What is your email address")
|
||||||
}
|
}
|
||||||
@@ -180,7 +185,7 @@ func (s *SystemHelper) Initialise() error {
|
|||||||
return s.setup()
|
return s.setup()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SystemConfig - Defines system wode configuration data
|
// SystemConfig - Defines system wide configuration data
|
||||||
type SystemConfig struct {
|
type SystemConfig struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
@@ -276,7 +281,7 @@ func CheckDependencies(logger *Logger) (bool, error) {
|
|||||||
switch distroInfo.Distribution {
|
switch distroInfo.Distribution {
|
||||||
case Ubuntu, Debian, Zorin, Parrot, Linuxmint, Elementary, Kali, Neon, Deepin, Raspbian, PopOS:
|
case Ubuntu, Debian, Zorin, Parrot, Linuxmint, Elementary, Kali, Neon, Deepin, Raspbian, PopOS:
|
||||||
libraryChecker = DpkgInstalled
|
libraryChecker = DpkgInstalled
|
||||||
case Arch, ArcoLinux, ArchLabs, Manjaro, ManjaroARM:
|
case Arch, ArcoLinux, ArchLabs, Ctlos, Manjaro, ManjaroARM, EndeavourOS:
|
||||||
libraryChecker = PacmanInstalled
|
libraryChecker = PacmanInstalled
|
||||||
case CentOS, Fedora, Tumbleweed, Leap:
|
case CentOS, Fedora, Tumbleweed, Leap:
|
||||||
libraryChecker = RpmInstalled
|
libraryChecker = RpmInstalled
|
||||||
@@ -286,6 +291,8 @@ func CheckDependencies(logger *Logger) (bool, error) {
|
|||||||
libraryChecker = XbpsInstalled
|
libraryChecker = XbpsInstalled
|
||||||
case Solus:
|
case Solus:
|
||||||
libraryChecker = EOpkgInstalled
|
libraryChecker = EOpkgInstalled
|
||||||
|
case Crux:
|
||||||
|
libraryChecker = PrtGetInstalled
|
||||||
default:
|
default:
|
||||||
return false, RequestSupportForDistribution(distroInfo)
|
return false, RequestSupportForDistribution(distroInfo)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
@@ -29,6 +30,26 @@ type TemplateMetadata struct {
|
|||||||
Bridge string `json:"bridge"`
|
Bridge string `json:"bridge"`
|
||||||
WailsDir string `json:"wailsdir"`
|
WailsDir string `json:"wailsdir"`
|
||||||
TemplateDependencies []*TemplateDependency `json:"dependencies,omitempty"`
|
TemplateDependencies []*TemplateDependency `json:"dependencies,omitempty"`
|
||||||
|
|
||||||
|
// List of platforms that this template is supported on.
|
||||||
|
// No value means all platforms. A platform name is the same string
|
||||||
|
// as `runtime.GOOS` will return, eg: "darwin". NOTE: This is
|
||||||
|
// case sensitive.
|
||||||
|
Platforms []string `json:"platforms,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PlatformSupported returns true if this template supports the
|
||||||
|
// currently running platform
|
||||||
|
func (m *TemplateMetadata) PlatformSupported() bool {
|
||||||
|
|
||||||
|
// Default is all platforms supported
|
||||||
|
if len(m.Platforms) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the platform is in the list
|
||||||
|
platformsSupported := slicer.String(m.Platforms)
|
||||||
|
return platformsSupported.Contains(runtime.GOOS)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TemplateDependency defines a binary dependency for the template
|
// TemplateDependency defines a binary dependency for the template
|
||||||
@@ -128,11 +149,11 @@ func (t *TemplateHelper) GetTemplateDetails() (map[string]*TemplateDetails, erro
|
|||||||
result[name] = &TemplateDetails{
|
result[name] = &TemplateDetails{
|
||||||
Path: dir,
|
Path: dir,
|
||||||
}
|
}
|
||||||
_ = &TemplateMetadata{}
|
|
||||||
metadata, err := t.LoadMetadata(dir)
|
metadata, err := t.LoadMetadata(dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
result[name].Metadata = metadata
|
result[name].Metadata = metadata
|
||||||
if metadata.Name != "" {
|
if metadata.Name != "" {
|
||||||
result[name].Name = metadata.Name
|
result[name].Name = metadata.Name
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"ng": "npx ng",
|
"ng": "npx ng",
|
||||||
"start": "npx ng serve --poll=2000 --host=0.0.0.0",
|
"serve": "npx ng serve --poll=2000 --host=0.0.0.0",
|
||||||
"build": "npx ng build --single-bundle true --output-hashing none --prod --bundle-styles false",
|
"build": "npx ng build --single-bundle true --output-hashing none --prod --bundle-styles false",
|
||||||
"test": "npx ng test",
|
"test": "npx ng test",
|
||||||
"lint": "npx ng lint",
|
"lint": "npx ng lint",
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ const routes: Routes = [];
|
|||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
RouterModule.forRoot(routes)
|
RouterModule.forRoot(routes,{useHash:true})
|
||||||
],
|
],
|
||||||
exports: [RouterModule]
|
exports: [RouterModule]
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
"author": "bh90210 <ktc@pm.me>",
|
"author": "bh90210 <ktc@pm.me>",
|
||||||
"created": "2019-06-15 18:23:48.666414555 +0300 EEST m=+223.934866008",
|
"created": "2019-06-15 18:23:48.666414555 +0300 EEST m=+223.934866008",
|
||||||
"frontenddir": "frontend",
|
"frontenddir": "frontend",
|
||||||
"serve": "npx ng serve --poll=2000",
|
"serve": "npm run serve",
|
||||||
"bridge": "src",
|
"bridge": "src",
|
||||||
"wailsdir": ""
|
"wailsdir": ""
|
||||||
}
|
}
|
||||||
@@ -5,14 +5,14 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-js": "^3.6.4",
|
"core-js": "^3.6.4",
|
||||||
"react": "^16.13.0",
|
"react": "^16.13.1",
|
||||||
"react-dom": "^16.13.0",
|
"react-dom": "^16.13.1",
|
||||||
"wails-react-scripts": "3.0.1-2",
|
"wails-react-scripts": "3.0.1-2",
|
||||||
"react-modal": "3.11.2",
|
"react-modal": "3.11.2",
|
||||||
"@wailsapp/runtime": "^1.0.10"
|
"@wailsapp/runtime": "^1.0.10"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"serve": "react-scripts start",
|
||||||
"build": "react-scripts build",
|
"build": "react-scripts build",
|
||||||
"test": "react-scripts test",
|
"test": "react-scripts test",
|
||||||
"eject": "react-scripts eject"
|
"eject": "react-scripts eject"
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.1 KiB |
@@ -1,10 +1,13 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
|
||||||
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
|
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
|
<meta name="description" content="Web site created using create-react-app" />
|
||||||
|
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||||
<!--
|
<!--
|
||||||
manifest.json provides metadata used when your web app is installed on a
|
manifest.json provides metadata used when your web app is installed on a
|
||||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||||
@@ -20,8 +23,9 @@
|
|||||||
Learn how to configure a non-root public URL by running `npm run build`.
|
Learn how to configure a non-root public URL by running `npm run build`.
|
||||||
-->
|
-->
|
||||||
<title>React App</title>
|
<title>React App</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
|
||||||
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<!--
|
<!--
|
||||||
@@ -34,5 +38,6 @@
|
|||||||
To begin the development, run `npm start` or `yarn start`.
|
To begin the development, run `npm start` or `yarn start`.
|
||||||
To create a production bundle, use `npm run build` or `yarn build`.
|
To create a production bundle, use `npm run build` or `yarn build`.
|
||||||
-->
|
-->
|
||||||
</body>
|
</body>
|
||||||
</html>
|
|
||||||
|
</html>
|
||||||
BIN
cmd/templates/create-react-app/frontend/public/logo192.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
cmd/templates/create-react-app/frontend/public/logo512.png
Normal file
|
After Width: | Height: | Size: 176 KiB |
@@ -6,6 +6,16 @@
|
|||||||
"src": "favicon.ico",
|
"src": "favicon.ico",
|
||||||
"sizes": "64x64 32x32 24x24 16x16",
|
"sizes": "64x64 32x32 24x24 16x16",
|
||||||
"type": "image/x-icon"
|
"type": "image/x-icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "logo192.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"sizes": "192x192"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "logo512.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"sizes": "512x512"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"start_url": ".",
|
"start_url": ".",
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# https://www.robotstxt.org/robotstxt.html
|
||||||
|
User-agent: *
|
||||||
|
Disallow:
|
||||||
@@ -3,11 +3,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.App-logo {
|
.App-logo {
|
||||||
animation: App-logo-spin infinite 20s linear;
|
|
||||||
height: 40vmin;
|
height: 40vmin;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: no-preference) {
|
||||||
|
.App-logo {
|
||||||
|
animation: App-logo-spin infinite 20s linear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.App-header {
|
.App-header {
|
||||||
background-color: #282c34;
|
background-color: #282c34;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
|
|||||||
@@ -1,48 +1,35 @@
|
|||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import Modal from 'react-modal';
|
import Modal from 'react-modal';
|
||||||
|
|
||||||
class HelloWorld extends React.Component {
|
function HelloWorld() {
|
||||||
constructor(props, context) {
|
const [showModal, setShowModal] = useState(false);
|
||||||
super();
|
const [result, setResult] = useState(null);
|
||||||
this.state = {
|
|
||||||
showModal: false
|
|
||||||
};
|
|
||||||
|
|
||||||
this.handleOpenModal = this.handleOpenModal.bind(this);
|
const handleOpenModal = () => {
|
||||||
this.handleCloseModal = this.handleCloseModal.bind(this);
|
setShowModal(true);
|
||||||
}
|
|
||||||
|
|
||||||
handleOpenModal () {
|
window.backend.basic().then((result) => setResult(result));
|
||||||
this.setState({ showModal: true });
|
};
|
||||||
|
|
||||||
window.backend.basic().then(result =>
|
const handleCloseModal = () => {
|
||||||
this.setState({
|
setShowModal(false);
|
||||||
result
|
};
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleCloseModal () {
|
return (
|
||||||
this.setState({ showModal: false });
|
<div className="App">
|
||||||
}
|
<button onClick={() => handleOpenModal()} type="button">
|
||||||
|
Hello
|
||||||
render() {
|
</button>
|
||||||
const { result } = this.state;
|
<Modal
|
||||||
return (
|
appElement={document.getElementById("app")}
|
||||||
<div className="App">
|
isOpen={showModal}
|
||||||
<button onClick={this.handleOpenModal} type="button">
|
contentLabel="Minimal Modal Example"
|
||||||
Hello
|
>
|
||||||
</button>
|
<p>{result}</p>
|
||||||
<Modal
|
<button onClick={() => handleCloseModal()}>Close Modal</button>
|
||||||
isOpen={this.state.showModal}
|
</Modal>
|
||||||
contentLabel="Minimal Modal Example"
|
</div>
|
||||||
>
|
);
|
||||||
<p>{result}</p>
|
|
||||||
<button onClick={this.handleCloseModal}>Close Modal</button>
|
|
||||||
</Modal>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default HelloWorld;
|
export default HelloWorld;
|
||||||
|
|||||||
@@ -3,9 +3,20 @@ import ReactDOM from 'react-dom';
|
|||||||
import 'core-js/stable';
|
import 'core-js/stable';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
|
import * as serviceWorker from './serviceWorker';
|
||||||
|
|
||||||
import * as Wails from '@wailsapp/runtime';
|
import * as Wails from '@wailsapp/runtime';
|
||||||
|
|
||||||
Wails.Init(() => {
|
Wails.Init(() => {
|
||||||
ReactDOM.render(<App />, document.getElementById('app'));
|
ReactDOM.render(
|
||||||
|
<React.StrictMode>
|
||||||
|
<App />
|
||||||
|
</React.StrictMode>,
|
||||||
|
document.getElementById("app")
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// If you want your app to work offline and load faster, you can change
|
||||||
|
// unregister() to register() below. Note this comes with some pitfalls.
|
||||||
|
// Learn more about service workers: https://bit.ly/CRA-PWA
|
||||||
|
serviceWorker.unregister();
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
{
|
{
|
||||||
"name": "React JS",
|
"name": "React JS",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"shortdescription": "Create React App v3 template",
|
"shortdescription": "Create React App v4 template",
|
||||||
"description": "Create React App v3 standar tooling",
|
"description": "Create React App v4 standard tooling",
|
||||||
"install": "npm install",
|
"install": "npm install",
|
||||||
"build": "npm run build",
|
"build": "npm run build",
|
||||||
"author": "bh90210 <ktc@pm.me>",
|
"author": "bh90210 <ktc@pm.me>",
|
||||||
"created": "2019-06-07 18:23:48.666414555 +0300 EEST m=+223.934866008",
|
"created": "2019-06-07 18:23:48.666414555 +0300 EEST m=+223.934866008",
|
||||||
"frontenddir": "frontend",
|
"frontenddir": "frontend",
|
||||||
"serve": "npm run start",
|
"serve": "npm run serve",
|
||||||
"bridge": "src",
|
"bridge": "src",
|
||||||
"wailsdir": ""
|
"wailsdir": ""
|
||||||
}
|
}
|
||||||
|
|||||||
4
cmd/templates/svelte/frontend/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
/node_modules/
|
||||||
|
/public/build/
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
90
cmd/templates/svelte/frontend/README.md
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
*Looking for a shareable component template? Go here --> [sveltejs/component-template](https://github.com/sveltejs/component-template)*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# svelte app
|
||||||
|
|
||||||
|
This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template.
|
||||||
|
|
||||||
|
To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx degit sveltejs/template svelte-app
|
||||||
|
cd svelte-app
|
||||||
|
```
|
||||||
|
|
||||||
|
*Note that you will need to have [Node.js](https://nodejs.org) installed.*
|
||||||
|
|
||||||
|
|
||||||
|
## Get started
|
||||||
|
|
||||||
|
Install the dependencies...
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd svelte-app
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
...then start [Rollup](https://rollupjs.org):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Navigate to [localhost:5000](http://localhost:5000). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes.
|
||||||
|
|
||||||
|
By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`.
|
||||||
|
|
||||||
|
|
||||||
|
## Building and running in production mode
|
||||||
|
|
||||||
|
To create an optimised version of the app:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com).
|
||||||
|
|
||||||
|
|
||||||
|
## Single-page app mode
|
||||||
|
|
||||||
|
By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere.
|
||||||
|
|
||||||
|
If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json:
|
||||||
|
|
||||||
|
```js
|
||||||
|
"start": "sirv public --single"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deploying to the web
|
||||||
|
|
||||||
|
### With [Vercel](https://vercel.com)
|
||||||
|
|
||||||
|
Install `vercel` if you haven't already:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install -g vercel
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, from within your project folder:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd public
|
||||||
|
vercel deploy --name my-project
|
||||||
|
```
|
||||||
|
|
||||||
|
### With [surge](https://surge.sh/)
|
||||||
|
|
||||||
|
Install `surge` if you haven't already:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install -g surge
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, from within your project folder:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
surge public my-project.surge.sh
|
||||||
|
```
|
||||||
31
cmd/templates/svelte/frontend/package.json.template
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"name": "{{.NPMProjectName}}",
|
||||||
|
"author": "{{.Author.Name}}<{{.Author.Email}}>",
|
||||||
|
"scripts": {
|
||||||
|
"build": "rollup -c",
|
||||||
|
"serve": "rollup -c -w",
|
||||||
|
"start": "sirv public"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.11.6",
|
||||||
|
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||||
|
"@babel/plugin-transform-runtime": "^7.11.5",
|
||||||
|
"@babel/preset-env": "^7.11.5",
|
||||||
|
"@rollup/plugin-commonjs": "^14.0.0",
|
||||||
|
"@rollup/plugin-image": "^2.0.5",
|
||||||
|
"@rollup/plugin-node-resolve": "^8.0.0",
|
||||||
|
"core-js": "^3.6.5",
|
||||||
|
"rollup": "^2.3.4",
|
||||||
|
"rollup-plugin-babel": "^4.4.0",
|
||||||
|
"rollup-plugin-livereload": "^2.0.0",
|
||||||
|
"rollup-plugin-polyfill": "^3.0.0",
|
||||||
|
"rollup-plugin-svelte": "^6.0.0",
|
||||||
|
"rollup-plugin-terser": "^7.0.0",
|
||||||
|
"svelte": "^3.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"sirv-cli": "^1.0.0",
|
||||||
|
"@wailsapp/runtime": "^1.0.10",
|
||||||
|
"svelte-simple-modal": "^0.6.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
cmd/templates/svelte/frontend/public/favicon.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
17
cmd/templates/svelte/frontend/public/index.html
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8'>
|
||||||
|
<meta name='viewport' content='width=device-width,initial-scale=1'>
|
||||||
|
|
||||||
|
<title>Svelte app</title>
|
||||||
|
|
||||||
|
<link rel='icon' type='image/png' href='/favicon.png'>
|
||||||
|
<link rel='stylesheet' href='/build/bundle.css'>
|
||||||
|
|
||||||
|
<script defer src='/build/bundle.js'></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
109
cmd/templates/svelte/frontend/rollup.config.js
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
import svelte from 'rollup-plugin-svelte';
|
||||||
|
import resolve from '@rollup/plugin-node-resolve';
|
||||||
|
import commonjs from '@rollup/plugin-commonjs';
|
||||||
|
import livereload from 'rollup-plugin-livereload';
|
||||||
|
import { terser } from 'rollup-plugin-terser';
|
||||||
|
import image from '@rollup/plugin-image';
|
||||||
|
import babel from 'rollup-plugin-babel';
|
||||||
|
import polyfill from 'rollup-plugin-polyfill';
|
||||||
|
|
||||||
|
const production = !process.env.ROLLUP_WATCH;
|
||||||
|
|
||||||
|
function serve() {
|
||||||
|
let server;
|
||||||
|
|
||||||
|
function toExit() {
|
||||||
|
if (server) server.kill(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
writeBundle() {
|
||||||
|
if (server) return;
|
||||||
|
server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
|
||||||
|
stdio: ['ignore', 'inherit', 'inherit'],
|
||||||
|
shell: true
|
||||||
|
});
|
||||||
|
|
||||||
|
process.on('SIGTERM', toExit);
|
||||||
|
process.on('exit', toExit);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
input: 'src/main.js',
|
||||||
|
output: {
|
||||||
|
sourcemap: true,
|
||||||
|
format: 'iife',
|
||||||
|
name: 'app',
|
||||||
|
file: 'public/build/bundle.js'
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
image(),
|
||||||
|
svelte({
|
||||||
|
// enable run-time checks when not in production
|
||||||
|
dev: !production,
|
||||||
|
// we'll extract any component CSS out into
|
||||||
|
// a separate file - better for performance
|
||||||
|
css: css => {
|
||||||
|
css.write('bundle.css');
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
// If you have external dependencies installed from
|
||||||
|
// npm, you'll most likely need these plugins. In
|
||||||
|
// some cases you'll need additional configuration -
|
||||||
|
// consult the documentation for details:
|
||||||
|
// https://github.com/rollup/plugins/tree/master/packages/commonjs
|
||||||
|
resolve({
|
||||||
|
browser: true,
|
||||||
|
dedupe: ['svelte', 'svelte/transition', 'svelte/internal']
|
||||||
|
}),
|
||||||
|
commonjs(),
|
||||||
|
|
||||||
|
// In dev mode, call `npm run start` once
|
||||||
|
// the bundle has been generated
|
||||||
|
!production && serve(),
|
||||||
|
|
||||||
|
// Watch the `public` directory and refresh the
|
||||||
|
// browser on changes when not in production
|
||||||
|
!production && livereload('public'),
|
||||||
|
|
||||||
|
// Credit: https://blog.az.sg/posts/svelte-and-ie11/
|
||||||
|
babel({
|
||||||
|
extensions: [ '.js', '.jsx', '.es6', '.es', '.mjs', '.svelte', '.html' ],
|
||||||
|
runtimeHelpers: true,
|
||||||
|
exclude: [ 'node_modules/@babel/**', 'node_modules/core-js/**' ],
|
||||||
|
presets: [
|
||||||
|
[
|
||||||
|
'@babel/preset-env',
|
||||||
|
{
|
||||||
|
targets: '> 0.25%, not dead, IE 11',
|
||||||
|
modules: false,
|
||||||
|
useBuiltIns: 'usage',
|
||||||
|
forceAllTransforms: true,
|
||||||
|
corejs: 3,
|
||||||
|
},
|
||||||
|
|
||||||
|
]
|
||||||
|
],
|
||||||
|
plugins: [
|
||||||
|
'@babel/plugin-syntax-dynamic-import',
|
||||||
|
[
|
||||||
|
'@babel/plugin-transform-runtime',
|
||||||
|
{
|
||||||
|
useESModules: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
polyfill(['@webcomponents/webcomponentsjs']),
|
||||||
|
|
||||||
|
// If we're building for production (npm run build
|
||||||
|
// instead of npm run dev), minify
|
||||||
|
production && terser()
|
||||||
|
],
|
||||||
|
watch: {
|
||||||
|
clearScreen: false
|
||||||
|
}
|
||||||
|
};
|
||||||
69
cmd/templates/svelte/frontend/src/App.svelte
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Modal from 'svelte-simple-modal';
|
||||||
|
import HelloWorld from './components/HelloWorld.svelte'
|
||||||
|
import logo from './logo.png';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<div class="App">
|
||||||
|
<header class="App-header">
|
||||||
|
<Modal>
|
||||||
|
<img src={logo} class="App-logo" alt="logo" />
|
||||||
|
<p>Welcome to your new <code>wails/svelte</code> project.</p>
|
||||||
|
<HelloWorld/>
|
||||||
|
</Modal>
|
||||||
|
</header>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
:global(body) {
|
||||||
|
margin: 0;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
|
||||||
|
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
|
||||||
|
sans-serif;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.App {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.App-logo {
|
||||||
|
height: 40vmin;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: no-preference) {
|
||||||
|
.App-logo {
|
||||||
|
animation: App-logo-spin infinite 20s linear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.App-header {
|
||||||
|
background-color: #282c34;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: calc(10px + 2vmin);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes App-logo-spin {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<script>
|
||||||
|
import { getContext } from 'svelte';
|
||||||
|
import ModalContent from './ModalContent.svelte'
|
||||||
|
|
||||||
|
const { open } = getContext('simple-modal');
|
||||||
|
|
||||||
|
const handleOpenModal = () => {
|
||||||
|
window.backend.basic().then((result) => {
|
||||||
|
open(ModalContent, { message: result });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<p><button on:click={handleOpenModal}>Hello</button></p>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<style></style>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<script>
|
||||||
|
export let message;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
{message}
|
||||||
|
</p>
|
||||||
BIN
cmd/templates/svelte/frontend/src/logo.png
Normal file
|
After Width: | Height: | Size: 301 KiB |
13
cmd/templates/svelte/frontend/src/main.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import App from './App.svelte';
|
||||||
|
|
||||||
|
import * as Wails from '@wailsapp/runtime';
|
||||||
|
|
||||||
|
let app;
|
||||||
|
|
||||||
|
Wails.Init(() => {
|
||||||
|
app = new App({
|
||||||
|
target: document.body,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
export default app;
|
||||||
5
cmd/templates/svelte/go.mod.template
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module {{.BinaryName}}
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/wailsapp/wails {{.WailsVersion}}
|
||||||
|
)
|
||||||
27
cmd/templates/svelte/main.go.template
Normal 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/public/build/bundle.js")
|
||||||
|
css := mewn.String("./frontend/public/build/bundle.css")
|
||||||
|
|
||||||
|
app := wails.CreateApp(&wails.AppConfig{
|
||||||
|
Width: 1024,
|
||||||
|
Height: 768,
|
||||||
|
Title: "{{.Name}}",
|
||||||
|
JS: js,
|
||||||
|
CSS: css,
|
||||||
|
Colour: "#131313",
|
||||||
|
})
|
||||||
|
|
||||||
|
app.Bind(basic)
|
||||||
|
app.Run()
|
||||||
|
}
|
||||||
14
cmd/templates/svelte/template.json
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "Svelte",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"shortdescription": "A basic Svelte template",
|
||||||
|
"description": "A basic Svelte template",
|
||||||
|
"install": "npm install",
|
||||||
|
"build": "npm run build",
|
||||||
|
"author": "Tim Kipp <timkipp.22.developer@gmail.com>",
|
||||||
|
"created": "2020-09-06 13:06:10.469848 -0700 PDT m=+213.578828559",
|
||||||
|
"frontenddir": "frontend",
|
||||||
|
"serve": "npm run serve",
|
||||||
|
"bridge": "src",
|
||||||
|
"wailsdir": ""
|
||||||
|
}
|
||||||
46
cmd/templates/vanilla/counter.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Counter is what we use for counting
|
||||||
|
type Counter struct {
|
||||||
|
r *wails.Runtime
|
||||||
|
store *wails.Store
|
||||||
|
}
|
||||||
|
|
||||||
|
// WailsInit is called when the component is being initialised
|
||||||
|
func (c *Counter) WailsInit(runtime *wails.Runtime) error {
|
||||||
|
c.r = runtime
|
||||||
|
c.store = runtime.Store.New("Counter", 0)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RandomValue sets the counter to a random value
|
||||||
|
func (c *Counter) RandomValue() {
|
||||||
|
c.store.Set(rand.Intn(1000))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment will increment the counter
|
||||||
|
func (c *Counter) Increment() {
|
||||||
|
|
||||||
|
increment := func(data int) int {
|
||||||
|
return data + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the store using the increment function
|
||||||
|
c.store.Update(increment)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrement will decrement the counter
|
||||||
|
func (c *Counter) Decrement() {
|
||||||
|
|
||||||
|
decrement := func(data int) int {
|
||||||
|
return data - 1
|
||||||
|
}
|
||||||
|
// Update the store using the decrement function
|
||||||
|
c.store.Update(decrement)
|
||||||
|
}
|
||||||
@@ -2,20 +2,35 @@
|
|||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
width: 1024px;
|
color: black;
|
||||||
height: 768px;
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
background-color: rgb(254,254,254);
|
||||||
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
display: block;
|
display: block;
|
||||||
width:100%;
|
width:100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-top: 3rem;
|
margin-top: 1rem;
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
|
background-color: white;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result {
|
||||||
|
margin-top: 1rem;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ const runtime = require('@wailsapp/runtime');
|
|||||||
// Main entry point
|
// Main entry point
|
||||||
function start() {
|
function start() {
|
||||||
|
|
||||||
|
var mystore = runtime.Store.New('Counter');
|
||||||
|
|
||||||
// Ensure the default app div is 100% wide/high
|
// Ensure the default app div is 100% wide/high
|
||||||
var app = document.getElementById('app');
|
var app = document.getElementById('app');
|
||||||
app.style.width = '100%';
|
app.style.width = '100%';
|
||||||
@@ -13,17 +15,32 @@ function start() {
|
|||||||
app.innerHTML = `
|
app.innerHTML = `
|
||||||
<div class='logo'></div>
|
<div class='logo'></div>
|
||||||
<div class='container'>
|
<div class='container'>
|
||||||
<button id='button'>Click Me!</button>
|
<button onClick='window.backend.Counter.Increment()'>
|
||||||
<div id='result'/>
|
Increment Counter
|
||||||
|
</button>
|
||||||
|
<button onClick='window.backend.Counter.Decrement()'>
|
||||||
|
Decrement Counter
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class='result'>Counter: <span id='counter'></span></div>
|
||||||
|
<div class='container'>
|
||||||
|
<input id='newCounter' type="number" value="0"/>
|
||||||
|
<button id='setvalue'>Set Counter Value</button>
|
||||||
|
<button onclick='window.backend.Counter.RandomValue()'>Set to Random Value</button>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// Connect button to Go method
|
// Connect counter value button to Go method
|
||||||
document.getElementById('button').onclick = function() {
|
document.getElementById('setvalue').onclick = function() {
|
||||||
window.backend.basic().then( function(result) {
|
let newValue = parseInt(document.getElementById('newCounter').value,10);
|
||||||
document.getElementById('result').innerText = result;
|
mystore.set(newValue);
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mystore.subscribe( function(state) {
|
||||||
|
document.getElementById('counter').innerText = state;
|
||||||
|
});
|
||||||
|
|
||||||
|
mystore.set(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
// We provide our entrypoint as a callback for runtime.Init
|
// We provide our entrypoint as a callback for runtime.Init
|
||||||
|
|||||||
@@ -5,10 +5,6 @@ import (
|
|||||||
"github.com/wailsapp/wails"
|
"github.com/wailsapp/wails"
|
||||||
)
|
)
|
||||||
|
|
||||||
func basic() string {
|
|
||||||
return "Hello World!"
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
js := mewn.String("./frontend/build/main.js")
|
js := mewn.String("./frontend/build/main.js")
|
||||||
@@ -22,6 +18,6 @@ func main() {
|
|||||||
CSS: css,
|
CSS: css,
|
||||||
Colour: "#131313",
|
Colour: "#131313",
|
||||||
})
|
})
|
||||||
app.Bind(basic)
|
app.Bind(&Counter{})
|
||||||
app.Run()
|
app.Run()
|
||||||
}
|
}
|
||||||
|
|||||||
3
cmd/templates/vue3-full/frontend/.browserslistrc
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
> 1%
|
||||||
|
last 2 versions
|
||||||
|
not dead
|
||||||
29
cmd/templates/vue3-full/frontend/.eslintrc.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
env: {
|
||||||
|
node: true
|
||||||
|
},
|
||||||
|
'extends': [
|
||||||
|
'plugin:vue/vue3-essential',
|
||||||
|
'eslint:recommended',
|
||||||
|
'@vue/typescript/recommended'
|
||||||
|
],
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 2020
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||||
|
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: [
|
||||||
|
'**/__tests__/*.{j,t}s?(x)',
|
||||||
|
'**/tests/unit/**/*.spec.{j,t}s?(x)'
|
||||||
|
],
|
||||||
|
env: {
|
||||||
|
mocha: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
21
cmd/templates/vue3-full/frontend/.gitignore
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
.DS_Store
|
||||||
|
node_modules
|
||||||
|
/dist
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
|
||||||
|
# Log files
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw*
|
||||||
35
cmd/templates/vue3-full/frontend/README.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# vue basic
|
||||||
|
|
||||||
|
## Project setup
|
||||||
|
|
||||||
|
```
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compiles and hot-reloads for development
|
||||||
|
|
||||||
|
```
|
||||||
|
npm run serve
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compiles and minifies for production
|
||||||
|
|
||||||
|
```
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run your tests
|
||||||
|
|
||||||
|
```
|
||||||
|
npm run test
|
||||||
|
```
|
||||||
|
|
||||||
|
### Lints and fixes files
|
||||||
|
|
||||||
|
```
|
||||||
|
npm run lint
|
||||||
|
```
|
||||||
|
|
||||||
|
### Customize configuration
|
||||||
|
|
||||||
|
See [Configuration Reference](https://cli.vuejs.org/config/).
|
||||||
37
cmd/templates/vue3-full/frontend/package.json.template
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"name": "{{.NPMProjectName}}",
|
||||||
|
"author": "{{.Author.Name}}<{{.Author.Email}}>",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"serve": "vue-cli-service serve",
|
||||||
|
"build": "vue-cli-service build",
|
||||||
|
"test:unit": "vue-cli-service test:unit",
|
||||||
|
"lint": "vue-cli-service lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"vue": "^3.0.0-0",
|
||||||
|
"vue-router": "^4.0.0-0",
|
||||||
|
"regenerator-runtime": "^0.13.7",
|
||||||
|
"@wailsapp/runtime": "^1.1.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/chai": "^4.2.12",
|
||||||
|
"@types/mocha": "^8.0.3",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^4.3.0",
|
||||||
|
"@typescript-eslint/parser": "^4.3.0",
|
||||||
|
"@vue/cli-plugin-eslint": "~4.5.9",
|
||||||
|
"@vue/cli-plugin-router": "~4.5.9",
|
||||||
|
"@vue/cli-plugin-typescript": "~4.5.9",
|
||||||
|
"@vue/cli-plugin-unit-mocha": "~4.5.9",
|
||||||
|
"@vue/cli-service": "~4.5.9",
|
||||||
|
"@vue/compiler-sfc": "^3.0.0",
|
||||||
|
"@vue/eslint-config-typescript": "^7.0.0",
|
||||||
|
"@vue/test-utils": "^2.0.0-0",
|
||||||
|
"chai": "^4.2.0",
|
||||||
|
"eslint": "<7.0.0",
|
||||||
|
"eslint-plugin-vue": "^7.0.0",
|
||||||
|
"node-sass": "^4.14.1",
|
||||||
|
"sass-loader": "^10.0.2",
|
||||||
|
"typescript": "~4.0.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
32
cmd/templates/vue3-full/frontend/src/App.vue
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<template>
|
||||||
|
<div id=app>
|
||||||
|
<div id="nav">
|
||||||
|
<router-link to="/">Home</router-link> |
|
||||||
|
<router-link to="/about">About</router-link>
|
||||||
|
</div>
|
||||||
|
<router-view/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
#app {
|
||||||
|
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
text-align: center;
|
||||||
|
color: #2c3e50;
|
||||||
|
}
|
||||||
|
|
||||||
|
#nav {
|
||||||
|
padding: 30px;
|
||||||
|
|
||||||
|
a {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #2c3e50;
|
||||||
|
|
||||||
|
&.router-link-exact-active {
|
||||||
|
color: #42b983;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
BIN
cmd/templates/vue3-full/frontend/src/assets/appicon.png
Normal file
|
After Width: | Height: | Size: 106 KiB |
@@ -0,0 +1,34 @@
|
|||||||
|
<template>
|
||||||
|
<div class="hello">
|
||||||
|
<h1>{{ msg }}</h1>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'HelloWorld',
|
||||||
|
props: {
|
||||||
|
msg: String,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||||
|
<style scoped lang="scss">
|
||||||
|
h3 {
|
||||||
|
margin: 40px 0 0;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: #42b983;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
8
cmd/templates/vue3-full/frontend/src/main.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { createApp } from 'vue';
|
||||||
|
import App from './App.vue';
|
||||||
|
import router from './router';
|
||||||
|
import * as Wails from '@wailsapp/runtime';
|
||||||
|
|
||||||
|
Wails.Init(() => {
|
||||||
|
createApp(App).use(router).mount('#app');
|
||||||
|
});
|
||||||
27
cmd/templates/vue3-full/frontend/src/router/index.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { createRouter, createMemoryHistory, RouteRecordRaw } from 'vue-router'
|
||||||
|
import Home from '../views/Home.vue'
|
||||||
|
import About from '../views/About.vue'
|
||||||
|
|
||||||
|
const routes: Array<RouteRecordRaw> = [
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
name: 'Home',
|
||||||
|
component: Home
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/about',
|
||||||
|
name: 'About',
|
||||||
|
// route level code-splitting
|
||||||
|
// this generates a separate chunk (about.[hash].js) for this route
|
||||||
|
// which is lazy-loaded when the route is visited.
|
||||||
|
// component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
|
||||||
|
component: About
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const router = createRouter({
|
||||||
|
history: createMemoryHistory(),
|
||||||
|
routes
|
||||||
|
})
|
||||||
|
|
||||||
|
export default router
|
||||||
5
cmd/templates/vue3-full/frontend/src/shims-vue.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
declare module '*.vue' {
|
||||||
|
import { defineComponent } from 'vue'
|
||||||
|
const component: ReturnType<typeof defineComponent>
|
||||||
|
export default component
|
||||||
|
}
|
||||||
5
cmd/templates/vue3-full/frontend/src/views/About.vue
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<template>
|
||||||
|
<div class="about">
|
||||||
|
<h1>This is an about page</h1>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
40
cmd/templates/vue3-full/frontend/src/views/Home.vue
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<template>
|
||||||
|
<div class="home">
|
||||||
|
<img @click="getMessage" alt="Vue logo" src="../assets/appicon.png" :style="{ height: '400px' }"/>
|
||||||
|
<HelloWorld :msg="message" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { ref, defineComponent } from "vue";
|
||||||
|
import HelloWorld from "@/components/HelloWorld.vue"; // @ is an alias to /src
|
||||||
|
|
||||||
|
interface Backend {
|
||||||
|
basic(): Promise<string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
backend: Backend;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "Home",
|
||||||
|
components: {
|
||||||
|
HelloWorld,
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
|
||||||
|
const message = ref("Click the Icon");
|
||||||
|
|
||||||
|
const getMessage = () => {
|
||||||
|
window.backend.basic().then(result => {
|
||||||
|
message.value = result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return { message: message, getMessage: getMessage };
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
14
cmd/templates/vue3-full/frontend/tests/unit/example.spec.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { expect } from 'chai';
|
||||||
|
import { describe, it } from 'mocha';
|
||||||
|
import { shallowMount } from '@vue/test-utils';
|
||||||
|
import HelloWorld from '@/components/HelloWorld.vue';
|
||||||
|
|
||||||
|
describe('HelloWorld.vue', () => {
|
||||||
|
it('renders props.msg when passed', () => {
|
||||||
|
const msg = 'new message';
|
||||||
|
const wrapper = shallowMount(HelloWorld, {
|
||||||
|
props: { msg }
|
||||||
|
});
|
||||||
|
expect(wrapper.text()).to.include(msg);
|
||||||
|
});
|
||||||
|
});
|
||||||
41
cmd/templates/vue3-full/frontend/tsconfig.json
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"module": "esnext",
|
||||||
|
"strict": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"importHelpers": true,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"baseUrl": ".",
|
||||||
|
"types": [
|
||||||
|
"webpack-env",
|
||||||
|
"mocha",
|
||||||
|
"chai"
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"@/*": [
|
||||||
|
"src/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"lib": [
|
||||||
|
"esnext",
|
||||||
|
"dom",
|
||||||
|
"dom.iterable",
|
||||||
|
"scripthost"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src/**/*.ts",
|
||||||
|
"src/**/*.tsx",
|
||||||
|
"src/**/*.vue",
|
||||||
|
"tests/**/*.ts",
|
||||||
|
"tests/**/*.tsx"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules"
|
||||||
|
]
|
||||||
|
}
|
||||||
42
cmd/templates/vue3-full/frontend/vue.config.js
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
let cssConfig = {};
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV == 'production') {
|
||||||
|
cssConfig = {
|
||||||
|
extract: {
|
||||||
|
filename: '[name].css',
|
||||||
|
chunkFilename: '[name].css'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
chainWebpack: config => {
|
||||||
|
let limit = 9999999999999999;
|
||||||
|
config.module
|
||||||
|
.rule('images')
|
||||||
|
.test(/\.(png|gif|jpg)(\?.*)?$/i)
|
||||||
|
.use('url-loader')
|
||||||
|
.loader('url-loader')
|
||||||
|
.tap(options => Object.assign(options, { limit: limit }));
|
||||||
|
config.module
|
||||||
|
.rule('fonts')
|
||||||
|
.test(/\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/i)
|
||||||
|
.use('url-loader')
|
||||||
|
.loader('url-loader')
|
||||||
|
.options({
|
||||||
|
limit: limit
|
||||||
|
});
|
||||||
|
},
|
||||||
|
css: cssConfig,
|
||||||
|
configureWebpack: {
|
||||||
|
output: {
|
||||||
|
filename: '[name].js'
|
||||||
|
},
|
||||||
|
optimization: {
|
||||||
|
splitChunks: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
devServer: {
|
||||||
|
disableHostCheck: true
|
||||||
|
}
|
||||||
|
};
|
||||||
5
cmd/templates/vue3-full/go.mod.template
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module {{.BinaryName}}
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/wailsapp/wails {{.WailsVersion}}
|
||||||
|
)
|
||||||
27
cmd/templates/vue3-full/main.go.template
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/leaanthony/mewn"
|
||||||
|
"github.com/wailsapp/wails"
|
||||||
|
)
|
||||||
|
|
||||||
|
func basic() string {
|
||||||
|
return "Hello World!"
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
js := mewn.String("./frontend/dist/app.js")
|
||||||
|
css := mewn.String("./frontend/dist/app.css")
|
||||||
|
|
||||||
|
app := wails.CreateApp(&wails.AppConfig{
|
||||||
|
Width: 1024,
|
||||||
|
Height: 768,
|
||||||
|
Title: "{{.Name}}",
|
||||||
|
JS: js,
|
||||||
|
CSS: css,
|
||||||
|
Colour: "#131313",
|
||||||
|
})
|
||||||
|
app.Bind(basic)
|
||||||
|
app.Run()
|
||||||
|
}
|
||||||
15
cmd/templates/vue3-full/template.json
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "Vue3 Full",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"shortdescription": "Vue 3, Vuex, Vue-router, and Webpack4",
|
||||||
|
"description": "Vue3.0.0 Vuex, Vue-router, and Webpack 4",
|
||||||
|
"install": "npm install",
|
||||||
|
"build": "npm run build",
|
||||||
|
"author": "Kyle Muchmore <kmuchmor@gmail.com>",
|
||||||
|
"created": "2020-09-24 21:18:55.09417 +0000 UTC m=+90.125590001",
|
||||||
|
"frontenddir": "frontend",
|
||||||
|
"serve": "npm run serve",
|
||||||
|
"bridge": "src",
|
||||||
|
"wailsdir": "",
|
||||||
|
"platforms": ["linux", "darwin"]
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
"core-js": "^3.6.4",
|
"core-js": "^3.6.4",
|
||||||
"regenerator-runtime": "^0.13.3",
|
"regenerator-runtime": "^0.13.3",
|
||||||
"vue": "^2.6.11",
|
"vue": "^2.6.11",
|
||||||
"vuetify": "^2.2.15",
|
"vuetify": "^2.3.15",
|
||||||
"@wailsapp/runtime": "^1.0.10"
|
"@wailsapp/runtime": "^1.0.10"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -24,13 +24,13 @@
|
|||||||
<v-app-bar-nav-icon @click.stop="drawer = !drawer"></v-app-bar-nav-icon>
|
<v-app-bar-nav-icon @click.stop="drawer = !drawer"></v-app-bar-nav-icon>
|
||||||
<v-toolbar-title>Application</v-toolbar-title>
|
<v-toolbar-title>Application</v-toolbar-title>
|
||||||
</v-app-bar>
|
</v-app-bar>
|
||||||
<v-content>
|
<v-main>
|
||||||
<v-container fluid class="px-0">
|
<v-container fluid class="px-0">
|
||||||
<v-layout justify-center align-center class="px-0">
|
<v-layout justify-center align-center class="px-0">
|
||||||
<hello-world></hello-world>
|
<hello-world></hello-world>
|
||||||
</v-layout>
|
</v-layout>
|
||||||
</v-container>
|
</v-container>
|
||||||
</v-content>
|
</v-main>
|
||||||
<v-footer app fixed>
|
<v-footer app fixed>
|
||||||
<span style="margin-left:1em">© You</span>
|
<span style="margin-left:1em">© You</span>
|
||||||
</v-footer>
|
</v-footer>
|
||||||
@@ -57,4 +57,4 @@
|
|||||||
.logo {
|
.logo {
|
||||||
width: 16em;
|
width: 16em;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
// Version - Wails version
|
// Version - Wails version
|
||||||
const Version = "v1.7.1"
|
const Version = "v1.13.0"
|
||||||
|
|||||||
@@ -26,10 +26,13 @@ func init() {
|
|||||||
var packageApp = false
|
var packageApp = false
|
||||||
var forceRebuild = false
|
var forceRebuild = false
|
||||||
var debugMode = false
|
var debugMode = false
|
||||||
|
var usefirebug = false
|
||||||
|
var gopath = ""
|
||||||
var typescriptFilename = ""
|
var typescriptFilename = ""
|
||||||
var verbose = false
|
var verbose = false
|
||||||
var platform = ""
|
var platform = ""
|
||||||
var ldflags = ""
|
var ldflags = ""
|
||||||
|
var tags = ""
|
||||||
|
|
||||||
buildSpinner := spinner.NewSpinner()
|
buildSpinner := spinner.NewSpinner()
|
||||||
buildSpinner.SetSpinSpeed(50)
|
buildSpinner.SetSpinSpeed(50)
|
||||||
@@ -40,9 +43,12 @@ func init() {
|
|||||||
BoolFlag("p", "Package application on successful build", &packageApp).
|
BoolFlag("p", "Package application on successful build", &packageApp).
|
||||||
BoolFlag("f", "Force rebuild of application components", &forceRebuild).
|
BoolFlag("f", "Force rebuild of application components", &forceRebuild).
|
||||||
BoolFlag("d", "Build in Debug mode", &debugMode).
|
BoolFlag("d", "Build in Debug mode", &debugMode).
|
||||||
|
BoolFlag("firebug", "Enable firebug console for debug builds", &usefirebug).
|
||||||
BoolFlag("verbose", "Verbose output", &verbose).
|
BoolFlag("verbose", "Verbose output", &verbose).
|
||||||
StringFlag("t", "Generate Typescript definitions to given file (at runtime)", &typescriptFilename).
|
StringFlag("t", "Generate Typescript definitions to given file (at runtime)", &typescriptFilename).
|
||||||
StringFlag("ldflags", "Extra options for -ldflags", &ldflags)
|
StringFlag("ldflags", "Extra options for -ldflags", &ldflags).
|
||||||
|
StringFlag("gopath", "Specify your GOPATH location. Mounted to /go during cross-compilation.", &gopath).
|
||||||
|
StringFlag("tags", "Build tags to pass to the go compiler (quoted and space separated)", &tags)
|
||||||
|
|
||||||
var b strings.Builder
|
var b strings.Builder
|
||||||
for _, plat := range getSupportedPlatforms() {
|
for _, plat := range getSupportedPlatforms() {
|
||||||
@@ -67,6 +73,7 @@ func init() {
|
|||||||
// Project options
|
// Project options
|
||||||
projectOptions := &cmd.ProjectOptions{}
|
projectOptions := &cmd.ProjectOptions{}
|
||||||
projectOptions.Verbose = verbose
|
projectOptions.Verbose = verbose
|
||||||
|
projectOptions.UseFirebug = usefirebug
|
||||||
|
|
||||||
// Check we are in project directory
|
// Check we are in project directory
|
||||||
// Check project.json loads correctly
|
// Check project.json loads correctly
|
||||||
@@ -76,6 +83,14 @@ func init() {
|
|||||||
return fmt.Errorf("Unable to find 'project.json'. Please check you are in a Wails project directory")
|
return fmt.Errorf("Unable to find 'project.json'. Please check you are in a Wails project directory")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set firebug flag
|
||||||
|
projectOptions.UseFirebug = usefirebug
|
||||||
|
|
||||||
|
// Check that this platform is supported
|
||||||
|
if !projectOptions.PlatformSupported() {
|
||||||
|
logger.Yellow("WARNING: This project is unsupported on %s - it probably won't work!\n Valid platforms: %s\n", runtime.GOOS, strings.Join(projectOptions.Platforms, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
// Set cross-compile
|
// Set cross-compile
|
||||||
projectOptions.Platform = runtime.GOOS
|
projectOptions.Platform = runtime.GOOS
|
||||||
if len(platform) > 0 {
|
if len(platform) > 0 {
|
||||||
@@ -97,6 +112,10 @@ func init() {
|
|||||||
|
|
||||||
// Add ldflags
|
// Add ldflags
|
||||||
projectOptions.LdFlags = ldflags
|
projectOptions.LdFlags = ldflags
|
||||||
|
projectOptions.GoPath = gopath
|
||||||
|
|
||||||
|
// Add tags
|
||||||
|
projectOptions.Tags = tags
|
||||||
|
|
||||||
// Validate config
|
// Validate config
|
||||||
// Check if we have a frontend
|
// Check if we have a frontend
|
||||||
@@ -181,6 +200,10 @@ func init() {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if projectOptions.Platform == "windows" {
|
||||||
|
logger.Yellow("*** Please note: Windows builds use mshtml which is only compatible with IE11. For more information, please read https://wails.app/guides/windows/ ***")
|
||||||
|
}
|
||||||
|
|
||||||
logger.Yellow("Awesome! Project '%s' built!", projectOptions.Name)
|
logger.Yellow("Awesome! Project '%s' built!", projectOptions.Name)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.Yellow("Awesome! Project '%s' built!", projectOptions.Name)
|
logger.Yellow("Awesome! Project '%s' built!", projectOptions.Name)
|
||||||
|
|
||||||
return cmd.ServeProject(projectOptions, logger)
|
return cmd.ServeProject(projectOptions, logger)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
123
config.go
@@ -1,20 +1,49 @@
|
|||||||
package wails
|
package wails
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/leaanthony/mewn"
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/runtime"
|
"github.com/wailsapp/wails/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AppConfig is the configuration structure used when creating a Wails App object
|
// AppConfig is the configuration structure used when creating a Wails App object
|
||||||
type AppConfig struct {
|
type AppConfig struct {
|
||||||
Width, Height int
|
// The width and height of your application in pixels
|
||||||
Title string
|
Width, Height int
|
||||||
defaultHTML string
|
|
||||||
HTML string
|
// The title to put in the title bar
|
||||||
JS string
|
Title string
|
||||||
CSS string
|
|
||||||
Colour string
|
// The HTML your app should use. If you leave it blank, a default will be used:
|
||||||
Resizable bool
|
// <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="IE=edge" content="IE=edge"></head><body><div id="app"></div><script type="text/javascript"></script></body></html>
|
||||||
|
HTML string
|
||||||
|
|
||||||
|
// The Javascript your app should use. Normally this should be generated by a bundler.
|
||||||
|
JS string
|
||||||
|
|
||||||
|
// The CSS your app should use. Normally this should be generated by a bundler.
|
||||||
|
CSS string
|
||||||
|
|
||||||
|
// The colour of your window. Can take "#fff", "rgb(255,255,255)", "rgba(255,255,255,1)" formats
|
||||||
|
Colour string
|
||||||
|
|
||||||
|
// Indicates whether your app should be resizable
|
||||||
|
Resizable bool
|
||||||
|
|
||||||
|
// Minimum width of a resizable window. If set, MinHeight should also be set.
|
||||||
|
MinWidth int
|
||||||
|
|
||||||
|
// Minimum height of a resizable window. If set, MinWidth should also be set.
|
||||||
|
MinHeight int
|
||||||
|
|
||||||
|
// Maximum width of a resizable window. If set, MaxHeight should also be set.
|
||||||
|
MaxWidth int
|
||||||
|
|
||||||
|
// Maximum height of a resizable window. If set, MaxWidth should also be set.
|
||||||
|
MaxHeight int
|
||||||
|
|
||||||
|
// Indicated if the devtools should be disabled
|
||||||
DisableInspector bool
|
DisableInspector bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,9 +62,14 @@ func (a *AppConfig) GetTitle() string {
|
|||||||
return a.Title
|
return a.Title
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDefaultHTML returns the default HTML
|
// GetHTML returns the default HTML
|
||||||
func (a *AppConfig) GetDefaultHTML() string {
|
func (a *AppConfig) GetHTML() string {
|
||||||
return a.defaultHTML
|
if len(a.HTML) > 0 {
|
||||||
|
a.HTML = url.QueryEscape(a.HTML)
|
||||||
|
a.HTML = "data:text/html," + strings.ReplaceAll(a.HTML, "+", "%20")
|
||||||
|
a.HTML = strings.ReplaceAll(a.HTML, "%3D", "=")
|
||||||
|
}
|
||||||
|
return a.HTML
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetResizable returns true if the window should be resizable
|
// GetResizable returns true if the window should be resizable
|
||||||
@@ -43,6 +77,26 @@ func (a *AppConfig) GetResizable() bool {
|
|||||||
return a.Resizable
|
return a.Resizable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetMinWidth returns the minimum width of the window
|
||||||
|
func (a *AppConfig) GetMinWidth() int {
|
||||||
|
return a.MinWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMinHeight returns the minimum height of the window
|
||||||
|
func (a *AppConfig) GetMinHeight() int {
|
||||||
|
return a.MinHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMaxWidth returns the maximum width of the window
|
||||||
|
func (a *AppConfig) GetMaxWidth() int {
|
||||||
|
return a.MaxWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMaxHeight returns the maximum height of the window
|
||||||
|
func (a *AppConfig) GetMaxHeight() int {
|
||||||
|
return a.MaxHeight
|
||||||
|
}
|
||||||
|
|
||||||
// GetDisableInspector returns true if the inspector should be disabled
|
// GetDisableInspector returns true if the inspector should be disabled
|
||||||
func (a *AppConfig) GetDisableInspector() bool {
|
func (a *AppConfig) GetDisableInspector() bool {
|
||||||
return a.DisableInspector
|
return a.DisableInspector
|
||||||
@@ -75,16 +129,41 @@ func (a *AppConfig) merge(in *AppConfig) error {
|
|||||||
a.Colour = in.Colour
|
a.Colour = in.Colour
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if in.HTML != "" {
|
||||||
|
a.HTML = in.HTML
|
||||||
|
}
|
||||||
|
|
||||||
if in.JS != "" {
|
if in.JS != "" {
|
||||||
a.JS = in.JS
|
a.JS = in.JS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if in.HTML != "" {
|
||||||
|
a.HTML = in.HTML
|
||||||
|
}
|
||||||
|
|
||||||
if in.Width != 0 {
|
if in.Width != 0 {
|
||||||
a.Width = in.Width
|
a.Width = in.Width
|
||||||
}
|
}
|
||||||
if in.Height != 0 {
|
if in.Height != 0 {
|
||||||
a.Height = in.Height
|
a.Height = in.Height
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if in.MinWidth != 0 {
|
||||||
|
a.MinWidth = in.MinWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
if in.MinHeight != 0 {
|
||||||
|
a.MinHeight = in.MinHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
if in.MaxWidth != 0 {
|
||||||
|
a.MaxWidth = in.MaxWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
if in.MaxHeight != 0 {
|
||||||
|
a.MaxHeight = in.MaxHeight
|
||||||
|
}
|
||||||
|
|
||||||
a.Resizable = in.Resizable
|
a.Resizable = in.Resizable
|
||||||
a.DisableInspector = in.DisableInspector
|
a.DisableInspector = in.DisableInspector
|
||||||
|
|
||||||
@@ -97,9 +176,13 @@ func newConfig(userConfig *AppConfig) (*AppConfig, error) {
|
|||||||
Width: 800,
|
Width: 800,
|
||||||
Height: 600,
|
Height: 600,
|
||||||
Resizable: true,
|
Resizable: true,
|
||||||
|
MinWidth: -1,
|
||||||
|
MinHeight: -1,
|
||||||
|
MaxWidth: -1,
|
||||||
|
MaxHeight: -1,
|
||||||
Title: "My Wails App",
|
Title: "My Wails App",
|
||||||
Colour: "#FFF", // White by default
|
Colour: "#FFF", // White by default
|
||||||
HTML: mewn.String("./runtime/assets/default.html"),
|
HTML: defaultHTML,
|
||||||
}
|
}
|
||||||
|
|
||||||
if userConfig != nil {
|
if userConfig != nil {
|
||||||
@@ -111,3 +194,17 @@ func newConfig(userConfig *AppConfig) (*AppConfig, error) {
|
|||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var defaultHTML = `<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>`
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ func (b *boundMethod) processWailsInit() error {
|
|||||||
// It must be *wails.Runtime
|
// It must be *wails.Runtime
|
||||||
inputName := b.inputs[0].String()
|
inputName := b.inputs[0].String()
|
||||||
b.log.Debugf("WailsInit input type: %s", inputName)
|
b.log.Debugf("WailsInit input type: %s", inputName)
|
||||||
if inputName != "*wails.Runtime" {
|
if inputName != "*runtime.Runtime" {
|
||||||
return fmt.Errorf("Invalid WailsInit() definition. Expected input to be wails.Runtime, but got %s", inputName)
|
return fmt.Errorf("Invalid WailsInit() definition. Expected input to be wails.Runtime, but got %s", inputName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,7 +219,7 @@ func (b *boundMethod) processWailsInit() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *boundMethod) processWailsShutdown() error {
|
func (b *boundMethod) processWailsShutdown() error {
|
||||||
// We must have only 1 input, it must be *wails.Runtime
|
// We must not have any inputs
|
||||||
if len(b.inputs) != 0 {
|
if len(b.inputs) != 0 {
|
||||||
return fmt.Errorf("Invalid WailsShutdown() definition. Expected 0 inputs, but got %d", len(b.inputs))
|
return fmt.Errorf("Invalid WailsShutdown() definition. Expected 0 inputs, but got %d", len(b.inputs))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ type Manager struct {
|
|||||||
log *logger.CustomLogger
|
log *logger.CustomLogger
|
||||||
renderer interfaces.Renderer // Messages will be dispatched to the frontend
|
renderer interfaces.Renderer // Messages will be dispatched to the frontend
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
mu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewManager creates a new event manager with a 100 event buffer
|
// NewManager creates a new event manager with a 100 event buffer
|
||||||
@@ -42,12 +43,12 @@ func (e *Manager) PushEvent(eventData *messages.EventData) {
|
|||||||
// means it does not expire (default).
|
// means it does not expire (default).
|
||||||
type eventListener struct {
|
type eventListener struct {
|
||||||
callback func(...interface{}) // Function to call with emitted event data
|
callback func(...interface{}) // Function to call with emitted event data
|
||||||
counter int // Expire after counter callbacks. 0 = infinite
|
counter uint // Expire after counter callbacks. 0 = infinite
|
||||||
expired bool // Indicates if the listener has expired
|
expired bool // Indicates if the listener has expired
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new event listener from the given callback function
|
// Creates a new event listener from the given callback function
|
||||||
func (e *Manager) addEventListener(eventName string, callback func(...interface{}), counter int) error {
|
func (e *Manager) addEventListener(eventName string, callback func(...interface{}), counter uint) error {
|
||||||
|
|
||||||
// Sanity check inputs
|
// Sanity check inputs
|
||||||
if callback == nil {
|
if callback == nil {
|
||||||
@@ -75,7 +76,30 @@ func (e *Manager) addEventListener(eventName string, callback func(...interface{
|
|||||||
// On adds a listener for the given event
|
// On adds a listener for the given event
|
||||||
func (e *Manager) On(eventName string, callback func(...interface{})) {
|
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)
|
err := e.addEventListener(eventName, callback, 0)
|
||||||
|
if err != nil {
|
||||||
|
e.log.Error(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Once adds a listener for the given event that will auto remove
|
||||||
|
// after one callback
|
||||||
|
func (e *Manager) Once(eventName string, callback func(...interface{})) {
|
||||||
|
// Add a persistent eventListener (counter = 0)
|
||||||
|
err := e.addEventListener(eventName, callback, 1)
|
||||||
|
if err != nil {
|
||||||
|
e.log.Error(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnMultiple adds a listener for the given event that will trigger
|
||||||
|
// at most <counter> times.
|
||||||
|
func (e *Manager) OnMultiple(eventName string, callback func(...interface{}), counter uint) {
|
||||||
|
// Add a persistent eventListener (counter = 0)
|
||||||
|
err := e.addEventListener(eventName, callback, counter)
|
||||||
|
if err != nil {
|
||||||
|
e.log.Error(err.Error())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit broadcasts the given event to the subscribed listeners
|
// Emit broadcasts the given event to the subscribed listeners
|
||||||
@@ -108,20 +132,24 @@ func (e *Manager) Start(renderer interfaces.Renderer) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Notify renderer
|
// Notify renderer
|
||||||
e.renderer.NotifyEvent(event)
|
err := e.renderer.NotifyEvent(event)
|
||||||
|
if err != nil {
|
||||||
|
e.log.Error(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
// Notify Go listeners
|
e.mu.Lock()
|
||||||
var listenersToRemove []*eventListener
|
|
||||||
|
|
||||||
// Iterate listeners
|
// Iterate listeners
|
||||||
for _, listener := range e.listeners[event.Name] {
|
for _, listener := range e.listeners[event.Name] {
|
||||||
|
|
||||||
// Call listener, perhaps with data
|
if !listener.expired {
|
||||||
if event.Data == nil {
|
// Call listener, perhaps with data
|
||||||
go listener.callback()
|
if event.Data == nil {
|
||||||
} else {
|
go listener.callback()
|
||||||
unpacked := event.Data.([]interface{})
|
} else {
|
||||||
go listener.callback(unpacked...)
|
unpacked := event.Data.([]interface{})
|
||||||
|
go listener.callback(unpacked...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update listen counter
|
// Update listen counter
|
||||||
@@ -133,15 +161,8 @@ func (e *Manager) Start(renderer interfaces.Renderer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove expired listeners in place
|
e.mu.Unlock()
|
||||||
if len(listenersToRemove) > 0 {
|
|
||||||
listeners := e.listeners[event.Name][:0]
|
|
||||||
for _, listener := range listeners {
|
|
||||||
if !listener.expired {
|
|
||||||
listeners = append(listeners, listener)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case <-e.quitChannel:
|
case <-e.quitChannel:
|
||||||
e.running = false
|
e.running = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,14 @@ type AppConfig interface {
|
|||||||
GetWidth() int
|
GetWidth() int
|
||||||
GetHeight() int
|
GetHeight() int
|
||||||
GetTitle() string
|
GetTitle() string
|
||||||
|
GetMinWidth() int
|
||||||
|
GetMinHeight() int
|
||||||
|
GetMaxWidth() int
|
||||||
|
GetMaxHeight() int
|
||||||
GetResizable() bool
|
GetResizable() bool
|
||||||
GetDefaultHTML() string
|
GetHTML() string
|
||||||
GetDisableInspector() bool
|
GetDisableInspector() bool
|
||||||
GetColour() string
|
GetColour() string
|
||||||
GetCSS() string
|
GetCSS() string
|
||||||
GetJS() string
|
GetJS() string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import "github.com/wailsapp/wails/lib/messages"
|
|||||||
type EventManager interface {
|
type EventManager interface {
|
||||||
PushEvent(*messages.EventData)
|
PushEvent(*messages.EventData)
|
||||||
Emit(eventName string, optionalData ...interface{})
|
Emit(eventName string, optionalData ...interface{})
|
||||||
|
OnMultiple(eventName string, callback func(...interface{}), counter uint)
|
||||||
|
Once(eventName string, callback func(...interface{}))
|
||||||
On(eventName string, callback func(...interface{}))
|
On(eventName string, callback func(...interface{}))
|
||||||
Start(Renderer)
|
Start(Renderer)
|
||||||
Shutdown()
|
Shutdown()
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
type Renderer interface {
|
type Renderer interface {
|
||||||
Initialise(AppConfig, IPCManager, EventManager) error
|
Initialise(AppConfig, IPCManager, EventManager) error
|
||||||
Run() error
|
Run() error
|
||||||
EnableConsole()
|
|
||||||
|
|
||||||
// Binding
|
// Binding
|
||||||
NewBinding(bindingName string) error
|
NewBinding(bindingName string) error
|
||||||
@@ -23,6 +22,10 @@ type Renderer interface {
|
|||||||
|
|
||||||
// Window Runtime
|
// Window Runtime
|
||||||
SetColour(string) error
|
SetColour(string) error
|
||||||
|
|
||||||
|
SetMinSize(width, height int)
|
||||||
|
SetMaxSize(width, height int)
|
||||||
|
|
||||||
Fullscreen()
|
Fullscreen()
|
||||||
UnFullscreen()
|
UnFullscreen()
|
||||||
SetTitle(title string)
|
SetTitle(title string)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package interfaces
|
package interfaces
|
||||||
|
|
||||||
// Runtime interface
|
// Runtime interface
|
||||||
type Runtime interface {}
|
type Runtime interface{}
|
||||||
|
|||||||
@@ -56,10 +56,6 @@ func (h *Bridge) Initialise(appConfig interfaces.AppConfig, ipcManager interface
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnableConsole not needed for bridge!
|
|
||||||
func (h *Bridge) EnableConsole() {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Bridge) wsBridgeHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *Bridge) wsBridgeHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
conn, err := websocket.Upgrade(w, r, w.Header(), 1024, 1024)
|
conn, err := websocket.Upgrade(w, r, w.Header(), 1024, 1024)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -152,12 +148,19 @@ func (h *Bridge) NotifyEvent(event *messages.EventData) error {
|
|||||||
// Marshall the data
|
// Marshall the data
|
||||||
data, err = json.Marshal(event.Data)
|
data, err = json.Marshal(event.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.log.Errorf("Cannot unmarshall JSON data in event: %s ", err.Error())
|
h.log.Errorf("Cannot marshal JSON data in event: %s ", err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message := fmt.Sprintf("window.wails._.Notify('%s','%s')", event.Name, data)
|
// Double encode data to ensure everything is escaped correctly.
|
||||||
|
data, err = json.Marshal(string(data))
|
||||||
|
if err != nil {
|
||||||
|
h.log.Errorf("Cannot marshal JSON data in event: %s ", err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
message := "window.wails._.Notify('" + event.Name + "'," + string(data) + ")"
|
||||||
dead := []*session{}
|
dead := []*session{}
|
||||||
for _, session := range h.sessions {
|
for _, session := range h.sessions {
|
||||||
err := session.evalJS(message, notifyMessage)
|
err := session.evalJS(message, notifyMessage)
|
||||||
@@ -183,6 +186,18 @@ func (h *Bridge) SetColour(colour string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetMinSize is unsupported for Bridge but required
|
||||||
|
// for the Renderer interface
|
||||||
|
func (h *Bridge) SetMinSize(width, height int) {
|
||||||
|
h.log.Warn("SetMinSize() unsupported in bridge mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMaxSize is unsupported for Bridge but required
|
||||||
|
// for the Renderer interface
|
||||||
|
func (h *Bridge) SetMaxSize(width, height int) {
|
||||||
|
h.log.Warn("SetMaxSize() unsupported in bridge mode")
|
||||||
|
}
|
||||||
|
|
||||||
// Fullscreen is unsupported for Bridge but required
|
// Fullscreen is unsupported for Bridge but required
|
||||||
// for the Renderer interface
|
// for the Renderer interface
|
||||||
func (h *Bridge) Fullscreen() {
|
func (h *Bridge) Fullscreen() {
|
||||||
|
|||||||
9
lib/renderer/bridge/renderer-mewn.go
Normal file
@@ -2,7 +2,6 @@ package renderer
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/leaanthony/mewn"
|
"github.com/leaanthony/mewn"
|
||||||
@@ -50,7 +49,7 @@ func (s *session) Identifier() string {
|
|||||||
|
|
||||||
func (s *session) sendMessage(msg string) error {
|
func (s *session) sendMessage(msg string) error {
|
||||||
if !s.done {
|
if !s.done {
|
||||||
s.writeChan <- *(*[]byte)(unsafe.Pointer(&msg))
|
s.writeChan <- []byte(msg)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,14 +18,19 @@ import (
|
|||||||
|
|
||||||
// WebView defines the main webview application window
|
// WebView defines the main webview application window
|
||||||
// Default values in []
|
// Default values in []
|
||||||
|
|
||||||
|
// UseFirebug indicates whether to inject the firebug console
|
||||||
|
var UseFirebug = ""
|
||||||
|
|
||||||
type WebView struct {
|
type WebView struct {
|
||||||
window wv.WebView // The webview object
|
window wv.WebView // The webview object
|
||||||
ipc interfaces.IPCManager
|
ipc interfaces.IPCManager
|
||||||
log *logger.CustomLogger
|
log *logger.CustomLogger
|
||||||
config interfaces.AppConfig
|
config interfaces.AppConfig
|
||||||
eventManager interfaces.EventManager
|
eventManager interfaces.EventManager
|
||||||
bindingCache []string
|
bindingCache []string
|
||||||
enableConsole bool
|
|
||||||
|
maximumSizeSet bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWebView returns a new WebView struct
|
// NewWebView returns a new WebView struct
|
||||||
@@ -49,18 +54,55 @@ func (w *WebView) Initialise(config interfaces.AppConfig, ipc interfaces.IPCMana
|
|||||||
// Save the config
|
// Save the config
|
||||||
w.config = config
|
w.config = config
|
||||||
|
|
||||||
|
width := config.GetWidth()
|
||||||
|
height := config.GetHeight()
|
||||||
|
|
||||||
|
// Clamp width and height
|
||||||
|
minWidth, minHeight := config.GetMinWidth(), config.GetMinHeight()
|
||||||
|
maxWidth, maxHeight := config.GetMaxWidth(), config.GetMaxHeight()
|
||||||
|
setMinSize := minWidth != -1 && minHeight != -1
|
||||||
|
setMaxSize := maxWidth != -1 && maxHeight != -1
|
||||||
|
|
||||||
|
if setMinSize {
|
||||||
|
if width < minWidth {
|
||||||
|
width = minWidth
|
||||||
|
}
|
||||||
|
if height < minHeight {
|
||||||
|
height = minHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if setMaxSize {
|
||||||
|
if width > maxWidth {
|
||||||
|
width = maxWidth
|
||||||
|
}
|
||||||
|
if height > maxHeight {
|
||||||
|
height = maxHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create the WebView instance
|
// Create the WebView instance
|
||||||
w.window = wv.NewWebview(wv.Settings{
|
w.window = wv.NewWebview(wv.Settings{
|
||||||
Width: config.GetWidth(),
|
Width: width,
|
||||||
Height: config.GetHeight(),
|
Height: height,
|
||||||
Title: config.GetTitle(),
|
Title: config.GetTitle(),
|
||||||
Resizable: config.GetResizable(),
|
Resizable: config.GetResizable(),
|
||||||
URL: config.GetDefaultHTML(),
|
URL: config.GetHTML(),
|
||||||
Debug: !config.GetDisableInspector(),
|
Debug: !config.GetDisableInspector(),
|
||||||
ExternalInvokeCallback: func(_ wv.WebView, message string) {
|
ExternalInvokeCallback: func(_ wv.WebView, message string) {
|
||||||
w.ipc.Dispatch(message, w.callback)
|
w.ipc.Dispatch(message, w.callback)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
fmt.Println("Control")
|
||||||
|
|
||||||
|
// Set minimum and maximum sizes
|
||||||
|
if setMinSize {
|
||||||
|
w.SetMinSize(minWidth, minHeight)
|
||||||
|
}
|
||||||
|
if setMaxSize {
|
||||||
|
w.SetMaxSize(maxWidth, maxHeight)
|
||||||
|
fmt.Println("Max")
|
||||||
|
}
|
||||||
|
|
||||||
// SignalManager.OnExit(w.Exit)
|
// SignalManager.OnExit(w.Exit)
|
||||||
|
|
||||||
@@ -71,6 +113,7 @@ func (w *WebView) Initialise(config interfaces.AppConfig, ipc interfaces.IPCMana
|
|||||||
}
|
}
|
||||||
|
|
||||||
w.log.Info("Initialised")
|
w.log.Info("Initialised")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,11 +147,6 @@ func (w *WebView) evalJS(js string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnableConsole enables the console!
|
|
||||||
func (w *WebView) EnableConsole() {
|
|
||||||
w.enableConsole = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Escape the Javascripts!
|
// Escape the Javascripts!
|
||||||
func escapeJS(js string) (string, error) {
|
func escapeJS(js string) (string, error) {
|
||||||
result := strings.Replace(js, "\\", "\\\\", -1)
|
result := strings.Replace(js, "\\", "\\\\", -1)
|
||||||
@@ -179,10 +217,9 @@ func (w *WebView) Run() error {
|
|||||||
w.log.Info("Running...")
|
w.log.Info("Running...")
|
||||||
|
|
||||||
// Inject firebug in debug mode on Windows
|
// Inject firebug in debug mode on Windows
|
||||||
if w.enableConsole {
|
if UseFirebug != "" {
|
||||||
w.log.Debug("Enabling Wails console")
|
w.log.Debug("Injecting Firebug")
|
||||||
console := mewn.String("../../runtime/assets/console.js")
|
w.evalJS(`window.usefirebug=true;`)
|
||||||
w.evalJS(console)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Runtime assets
|
// Runtime assets
|
||||||
@@ -259,6 +296,9 @@ func (w *WebView) SelectFile(title string, filter string) string {
|
|||||||
wg.Done()
|
wg.Done()
|
||||||
})
|
})
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
defer w.focus() // Ensure the main window is put back into focus afterwards
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -277,6 +317,9 @@ func (w *WebView) SelectDirectory() string {
|
|||||||
wg.Done()
|
wg.Done()
|
||||||
})
|
})
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
defer w.focus() // Ensure the main window is put back into focus afterwards
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -295,10 +338,20 @@ func (w *WebView) SelectSaveFile(title string, filter string) string {
|
|||||||
wg.Done()
|
wg.Done()
|
||||||
})
|
})
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
defer w.focus() // Ensure the main window is put back into focus afterwards
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// focus puts the main window into focus
|
||||||
|
func (w *WebView) focus() {
|
||||||
|
w.window.Dispatch(func() {
|
||||||
|
w.window.Focus()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// callback sends a callback to the frontend
|
// callback sends a callback to the frontend
|
||||||
func (w *WebView) callback(data string) error {
|
func (w *WebView) callback(data string) error {
|
||||||
callbackCMD := fmt.Sprintf("window.wails._.Callback('%s');", data)
|
callbackCMD := fmt.Sprintf("window.wails._.Callback('%s');", data)
|
||||||
@@ -329,15 +382,48 @@ func (w *WebView) NotifyEvent(event *messages.EventData) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message := fmt.Sprintf("wails._.Notify('%s','%s')", event.Name, data)
|
// Double encode data to ensure everything is escaped correctly.
|
||||||
|
data, err = json.Marshal(string(data))
|
||||||
|
if err != nil {
|
||||||
|
w.log.Errorf("Cannot marshal JSON data in event: %s ", err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
message := "window.wails._.Notify('" + event.Name + "'," + string(data) + ")"
|
||||||
return w.evalJS(message)
|
return w.evalJS(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetMinSize sets the minimum size of a resizable window
|
||||||
|
func (w *WebView) SetMinSize(width, height int) {
|
||||||
|
if w.config.GetResizable() == false {
|
||||||
|
w.log.Warn("Cannot call SetMinSize() - App.Resizable = false")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.window.Dispatch(func() {
|
||||||
|
w.window.SetMinSize(width, height)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMaxSize sets the maximum size of a resizable window
|
||||||
|
func (w *WebView) SetMaxSize(width, height int) {
|
||||||
|
if w.config.GetResizable() == false {
|
||||||
|
w.log.Warn("Cannot call SetMaxSize() - App.Resizable = false")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.maximumSizeSet = true
|
||||||
|
w.window.Dispatch(func() {
|
||||||
|
w.window.SetMaxSize(width, height)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Fullscreen makes the main window go fullscreen
|
// Fullscreen makes the main window go fullscreen
|
||||||
func (w *WebView) Fullscreen() {
|
func (w *WebView) Fullscreen() {
|
||||||
if w.config.GetResizable() == false {
|
if w.config.GetResizable() == false {
|
||||||
w.log.Warn("Cannot call Fullscreen() - App.Resizable = false")
|
w.log.Warn("Cannot call Fullscreen() - App.Resizable = false")
|
||||||
return
|
return
|
||||||
|
} else if w.maximumSizeSet {
|
||||||
|
w.log.Warn("Cannot call Fullscreen() - Maximum size of window set")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
w.window.Dispatch(func() {
|
w.window.Dispatch(func() {
|
||||||
w.window.SetFullscreen(true)
|
w.window.SetFullscreen(true)
|
||||||
|
|||||||
@@ -65,6 +65,18 @@ static inline void CgoWebViewSetTitle(void *w, char *title) {
|
|||||||
webview_set_title((struct webview *)w, title);
|
webview_set_title((struct webview *)w, title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void CgoWebViewFocus(void *w) {
|
||||||
|
webview_focus((struct webview *)w);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void CgoWebViewMinSize(void *w, int width, int height) {
|
||||||
|
webview_minsize((struct webview *)w, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void CgoWebViewMaxSize(void *w, int width, int height) {
|
||||||
|
webview_maxsize((struct webview *)w, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void CgoWebViewSetFullscreen(void *w, int fullscreen) {
|
static inline void CgoWebViewSetFullscreen(void *w, int fullscreen) {
|
||||||
webview_set_fullscreen((struct webview *)w, fullscreen);
|
webview_set_fullscreen((struct webview *)w, fullscreen);
|
||||||
}
|
}
|
||||||
@@ -170,6 +182,16 @@ type WebView interface {
|
|||||||
// SetTitle() changes window title. This method must be called from the main
|
// SetTitle() changes window title. This method must be called from the main
|
||||||
// thread only. See Dispatch() for more details.
|
// thread only. See Dispatch() for more details.
|
||||||
SetTitle(title string)
|
SetTitle(title string)
|
||||||
|
|
||||||
|
// Focus() puts the main window into focus
|
||||||
|
Focus()
|
||||||
|
|
||||||
|
// SetMinSize() sets the minimum size of the window
|
||||||
|
SetMinSize(width, height int)
|
||||||
|
|
||||||
|
// SetMaxSize() sets the maximum size of the window
|
||||||
|
SetMaxSize(width, height int)
|
||||||
|
|
||||||
// SetFullscreen() controls window full-screen mode. This method must be
|
// SetFullscreen() controls window full-screen mode. This method must be
|
||||||
// called from the main thread only. See Dispatch() for more details.
|
// called from the main thread only. See Dispatch() for more details.
|
||||||
SetFullscreen(fullscreen bool)
|
SetFullscreen(fullscreen bool)
|
||||||
@@ -307,6 +329,18 @@ func (w *webview) SetColor(r, g, b, a uint8) {
|
|||||||
C.CgoWebViewSetColor(w.w, C.uint8_t(r), C.uint8_t(g), C.uint8_t(b), C.uint8_t(a))
|
C.CgoWebViewSetColor(w.w, C.uint8_t(r), C.uint8_t(g), C.uint8_t(b), C.uint8_t(a))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *webview) Focus() {
|
||||||
|
C.CgoWebViewFocus(w.w)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *webview) SetMinSize(width, height int) {
|
||||||
|
C.CgoWebViewMinSize(w.w, C.int(width), C.int(height))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *webview) SetMaxSize(width, height int) {
|
||||||
|
C.CgoWebViewMaxSize(w.w, C.int(width), C.int(height))
|
||||||
|
}
|
||||||
|
|
||||||
func (w *webview) SetFullscreen(fullscreen bool) {
|
func (w *webview) SetFullscreen(fullscreen bool) {
|
||||||
C.CgoWebViewSetFullscreen(w.w, C.int(boolToInt(fullscreen)))
|
C.CgoWebViewSetFullscreen(w.w, C.int(boolToInt(fullscreen)))
|
||||||
}
|
}
|
||||||
@@ -353,7 +387,9 @@ func _webviewDispatchGoCallback(index unsafe.Pointer) {
|
|||||||
f = fns[uintptr(index)]
|
f = fns[uintptr(index)]
|
||||||
delete(fns, uintptr(index))
|
delete(fns, uintptr(index))
|
||||||
m.Unlock()
|
m.Unlock()
|
||||||
f()
|
if f != nil {
|
||||||
|
f()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//export _webviewExternalInvokeCallback
|
//export _webviewExternalInvokeCallback
|
||||||
@@ -369,5 +405,7 @@ func _webviewExternalInvokeCallback(w unsafe.Pointer, data unsafe.Pointer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
m.Unlock()
|
m.Unlock()
|
||||||
cb(wv, C.GoString((*C.char)(data)))
|
if cb != nil {
|
||||||
|
cb(wv, C.GoString((*C.char)(data)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ extern "C"
|
|||||||
int ready;
|
int ready;
|
||||||
int js_busy;
|
int js_busy;
|
||||||
int should_exit;
|
int should_exit;
|
||||||
|
|
||||||
|
int min_width;
|
||||||
|
int min_height;
|
||||||
|
int max_width;
|
||||||
|
int max_height;
|
||||||
};
|
};
|
||||||
#elif defined(WEBVIEW_WINAPI)
|
#elif defined(WEBVIEW_WINAPI)
|
||||||
#define CINTERFACE
|
#define CINTERFACE
|
||||||
@@ -75,6 +80,11 @@ struct webview_priv
|
|||||||
DWORD saved_style;
|
DWORD saved_style;
|
||||||
DWORD saved_ex_style;
|
DWORD saved_ex_style;
|
||||||
RECT saved_rect;
|
RECT saved_rect;
|
||||||
|
|
||||||
|
int min_width;
|
||||||
|
int min_height;
|
||||||
|
int max_width;
|
||||||
|
int max_height;
|
||||||
};
|
};
|
||||||
#elif defined(WEBVIEW_COCOA)
|
#elif defined(WEBVIEW_COCOA)
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
@@ -168,6 +178,9 @@ struct webview_priv
|
|||||||
WEBVIEW_API int webview_eval(struct webview *w, const char *js);
|
WEBVIEW_API int webview_eval(struct webview *w, const char *js);
|
||||||
WEBVIEW_API int webview_inject_css(struct webview *w, const char *css);
|
WEBVIEW_API int webview_inject_css(struct webview *w, const char *css);
|
||||||
WEBVIEW_API void webview_set_title(struct webview *w, const char *title);
|
WEBVIEW_API void webview_set_title(struct webview *w, const char *title);
|
||||||
|
WEBVIEW_API void webview_focus(struct webview *w);
|
||||||
|
WEBVIEW_API void webview_minsize(struct webview *w, int width, int height);
|
||||||
|
WEBVIEW_API void webview_maxsize(struct webview *w, int width, int height);
|
||||||
WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen);
|
WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen);
|
||||||
WEBVIEW_API void webview_set_color(struct webview *w, uint8_t r, uint8_t g,
|
WEBVIEW_API void webview_set_color(struct webview *w, uint8_t r, uint8_t g,
|
||||||
uint8_t b, uint8_t a);
|
uint8_t b, uint8_t a);
|
||||||
@@ -329,6 +342,12 @@ struct webview_priv
|
|||||||
w->priv.should_exit = 0;
|
w->priv.should_exit = 0;
|
||||||
w->priv.queue = g_async_queue_new();
|
w->priv.queue = g_async_queue_new();
|
||||||
w->priv.window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
w->priv.window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||||
|
|
||||||
|
w->priv.min_width = -1;
|
||||||
|
w->priv.min_height = -1;
|
||||||
|
w->priv.max_width = -1;
|
||||||
|
w->priv.max_height = -1;
|
||||||
|
|
||||||
gtk_window_set_title(GTK_WINDOW(w->priv.window), w->title);
|
gtk_window_set_title(GTK_WINDOW(w->priv.window), w->title);
|
||||||
|
|
||||||
if (w->resizable)
|
if (w->resizable)
|
||||||
@@ -364,6 +383,7 @@ struct webview_priv
|
|||||||
webkit_web_view_get_settings(WEBKIT_WEB_VIEW(w->priv.webview));
|
webkit_web_view_get_settings(WEBKIT_WEB_VIEW(w->priv.webview));
|
||||||
webkit_settings_set_enable_write_console_messages_to_stdout(settings, true);
|
webkit_settings_set_enable_write_console_messages_to_stdout(settings, true);
|
||||||
webkit_settings_set_enable_developer_extras(settings, true);
|
webkit_settings_set_enable_developer_extras(settings, true);
|
||||||
|
webkit_settings_set_hardware_acceleration_policy(settings, WEBKIT_HARDWARE_ACCELERATION_POLICY_ALWAYS);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -395,6 +415,49 @@ struct webview_priv
|
|||||||
gtk_window_set_title(GTK_WINDOW(w->priv.window), title);
|
gtk_window_set_title(GTK_WINDOW(w->priv.window), title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WEBVIEW_API void webview_focus(struct webview *w)
|
||||||
|
{
|
||||||
|
gtk_window_present(GTK_WINDOW(w->priv.window));
|
||||||
|
}
|
||||||
|
|
||||||
|
WEBVIEW_API void webview_minsize(struct webview *w, int width, int height) {
|
||||||
|
|
||||||
|
w->priv.min_width = width;
|
||||||
|
w->priv.min_height = height;
|
||||||
|
|
||||||
|
GdkGeometry hints;
|
||||||
|
GdkWindowHints usedHints = (GdkWindowHints) GDK_HINT_MIN_SIZE;
|
||||||
|
|
||||||
|
hints.min_width = w->priv.min_width;
|
||||||
|
hints.min_height = w->priv.min_height;
|
||||||
|
if (w->priv.max_width != -1) {
|
||||||
|
hints.max_width = w->priv.max_width;
|
||||||
|
hints.max_height = w->priv.max_height;
|
||||||
|
usedHints = (GdkWindowHints)(GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_window_set_geometry_hints(GTK_WINDOW(w->priv.window), w->priv.window, &hints, usedHints);
|
||||||
|
}
|
||||||
|
|
||||||
|
WEBVIEW_API void webview_maxsize(struct webview *w, int width, int height) {
|
||||||
|
|
||||||
|
w->priv.max_width = width;
|
||||||
|
w->priv.max_height = height;
|
||||||
|
|
||||||
|
GdkGeometry hints;
|
||||||
|
GdkWindowHints usedHints = (GdkWindowHints) GDK_HINT_MAX_SIZE;
|
||||||
|
|
||||||
|
if (w->priv.min_width != -1) {
|
||||||
|
hints.min_width = w->priv.min_width;
|
||||||
|
hints.min_height = w->priv.min_height;
|
||||||
|
usedHints = (GdkWindowHints)(GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
|
||||||
|
}
|
||||||
|
hints.max_width = w->priv.max_width;
|
||||||
|
hints.max_height = w->priv.max_height;
|
||||||
|
|
||||||
|
gtk_window_set_geometry_hints(GTK_WINDOW(w->priv.window), w->priv.window, &hints, usedHints);
|
||||||
|
}
|
||||||
|
|
||||||
WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen)
|
WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen)
|
||||||
{
|
{
|
||||||
if (fullscreen)
|
if (fullscreen)
|
||||||
@@ -1330,7 +1393,39 @@ struct webview_priv
|
|||||||
case WM_CREATE:
|
case WM_CREATE:
|
||||||
w = (struct webview *)((CREATESTRUCT *)lParam)->lpCreateParams;
|
w = (struct webview *)((CREATESTRUCT *)lParam)->lpCreateParams;
|
||||||
w->priv.hwnd = hwnd;
|
w->priv.hwnd = hwnd;
|
||||||
|
|
||||||
return EmbedBrowserObject(w);
|
return EmbedBrowserObject(w);
|
||||||
|
case WM_GETMINMAXINFO:
|
||||||
|
{
|
||||||
|
if (w != NULL) {
|
||||||
|
// get pixel density
|
||||||
|
HDC hDC = GetDC(NULL);
|
||||||
|
double DPIScaleX = GetDeviceCaps(hDC, 88)/96.0;
|
||||||
|
double DPIScaleY = GetDeviceCaps(hDC, 90)/96.0;
|
||||||
|
ReleaseDC(NULL, hDC);
|
||||||
|
|
||||||
|
RECT rcClient, rcWind;
|
||||||
|
POINT ptDiff;
|
||||||
|
GetClientRect(hwnd, &rcClient);
|
||||||
|
GetWindowRect(hwnd, &rcWind);
|
||||||
|
|
||||||
|
int widthExtra = (rcWind.right - rcWind.left) - rcClient.right;
|
||||||
|
int heightExtra = (rcWind.bottom - rcWind.top) - rcClient.bottom;
|
||||||
|
|
||||||
|
LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
|
||||||
|
|
||||||
|
if (w->priv.min_width != -1) {
|
||||||
|
lpMMI->ptMinTrackSize.x = w->priv.min_width * DPIScaleX + widthExtra;
|
||||||
|
lpMMI->ptMinTrackSize.y = w->priv.min_height * DPIScaleY + heightExtra;
|
||||||
|
}
|
||||||
|
if (w->priv.max_width != -1) {
|
||||||
|
lpMMI->ptMaxTrackSize.x = w->priv.max_width * DPIScaleX + widthExtra;
|
||||||
|
lpMMI->ptMaxTrackSize.y = w->priv.max_height * DPIScaleY + heightExtra;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
case WM_DESTROY:
|
case WM_DESTROY:
|
||||||
UnEmbedBrowserObject(w);
|
UnEmbedBrowserObject(w);
|
||||||
PostQuitMessage(0);
|
PostQuitMessage(0);
|
||||||
@@ -1395,6 +1490,9 @@ struct webview_priv
|
|||||||
|
|
||||||
WEBVIEW_API int webview_init(struct webview *w)
|
WEBVIEW_API int webview_init(struct webview *w)
|
||||||
{
|
{
|
||||||
|
w->priv.min_width = -1;
|
||||||
|
w->priv.max_width = -1;
|
||||||
|
|
||||||
WNDCLASSEX wc;
|
WNDCLASSEX wc;
|
||||||
HINSTANCE hInstance;
|
HINSTANCE hInstance;
|
||||||
DWORD style;
|
DWORD style;
|
||||||
@@ -1431,6 +1529,13 @@ struct webview_priv
|
|||||||
style = WS_OVERLAPPED | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU;
|
style = WS_OVERLAPPED | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scale
|
||||||
|
// Credit: https://github.com/webview/webview/issues/54#issuecomment-379528243
|
||||||
|
HDC hDC = GetDC(NULL);
|
||||||
|
w->width = GetDeviceCaps(hDC, 88)*w->width/96.0;
|
||||||
|
w->height = GetDeviceCaps(hDC, 90)*w->height/96.0;
|
||||||
|
ReleaseDC(NULL, hDC);
|
||||||
|
|
||||||
rect.left = 0;
|
rect.left = 0;
|
||||||
rect.top = 0;
|
rect.top = 0;
|
||||||
rect.right = w->width;
|
rect.right = w->width;
|
||||||
@@ -1633,6 +1738,21 @@ struct webview_priv
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WEBVIEW_API void webview_focus(struct webview *w)
|
||||||
|
{
|
||||||
|
SetFocus(w->priv.hwnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
WEBVIEW_API void webview_minsize(struct webview *w, int width, int height) {
|
||||||
|
w->priv.min_width = width;
|
||||||
|
w->priv.min_height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
WEBVIEW_API void webview_maxsize(struct webview *w, int width, int height) {
|
||||||
|
w->priv.max_width = width;
|
||||||
|
w->priv.max_height = height;
|
||||||
|
}
|
||||||
|
|
||||||
WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen)
|
WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen)
|
||||||
{
|
{
|
||||||
if (w->priv.is_fullscreen == !!fullscreen)
|
if (w->priv.is_fullscreen == !!fullscreen)
|
||||||
@@ -2200,6 +2320,30 @@ struct webview_priv
|
|||||||
[w->priv.window setTitle:nsTitle];
|
[w->priv.window setTitle:nsTitle];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WEBVIEW_API void webview_focus(struct webview *w)
|
||||||
|
{
|
||||||
|
[w->priv.window makeKeyWindow];
|
||||||
|
}
|
||||||
|
|
||||||
|
WEBVIEW_API void webview_minsize(struct webview *w, int width, int height) {
|
||||||
|
NSSize size;
|
||||||
|
size.width = width;
|
||||||
|
size.height = height;
|
||||||
|
[w->priv.window setMinSize:size];
|
||||||
|
}
|
||||||
|
|
||||||
|
WEBVIEW_API void webview_maxsize(struct webview *w, int width, int height) {
|
||||||
|
NSSize size;
|
||||||
|
size.width = width;
|
||||||
|
size.height = height;
|
||||||
|
[w->priv.window setMaxSize:size];
|
||||||
|
|
||||||
|
[w->priv.window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary|NSWindowCollectionBehaviorFullScreenNone|NSWindowCollectionBehaviorFullScreenDisallowsTiling];
|
||||||
|
|
||||||
|
NSButton *button = [w->priv.window standardWindowButton:NSWindowZoomButton];
|
||||||
|
[button setEnabled: NO];
|
||||||
|
}
|
||||||
|
|
||||||
WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen)
|
WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen)
|
||||||
{
|
{
|
||||||
int b = ((([w->priv.window styleMask] & NSWindowStyleMaskFullScreen) ==
|
int b = ((([w->priv.window styleMask] & NSWindowStyleMaskFullScreen) ==
|
||||||
@@ -2354,4 +2498,4 @@ struct webview_priv
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* WEBVIEW_H */
|
#endif /* WEBVIEW_H */
|
||||||
3
package-lock.json
generated
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"lockfileVersion": 1
|
||||||
|
}
|
||||||
32
runtime.go
@@ -1,32 +0,0 @@
|
|||||||
package wails
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/wailsapp/wails/lib/interfaces"
|
|
||||||
"github.com/wailsapp/wails/lib/logger"
|
|
||||||
"github.com/wailsapp/wails/runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CustomLogger type alias
|
|
||||||
type CustomLogger = logger.CustomLogger
|
|
||||||
|
|
||||||
// Runtime is the Wails Runtime Interface, given to a user who has defined the WailsInit method
|
|
||||||
type Runtime struct {
|
|
||||||
Events *runtime.Events
|
|
||||||
Log *runtime.Log
|
|
||||||
Dialog *runtime.Dialog
|
|
||||||
Window *runtime.Window
|
|
||||||
Browser *runtime.Browser
|
|
||||||
FileSystem *runtime.FileSystem
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRuntime creates a new Runtime struct
|
|
||||||
func NewRuntime(eventManager interfaces.EventManager, renderer interfaces.Renderer) *Runtime {
|
|
||||||
return &Runtime{
|
|
||||||
Events: runtime.NewEvents(eventManager),
|
|
||||||
Log: runtime.NewLog(),
|
|
||||||
Dialog: runtime.NewDialog(renderer),
|
|
||||||
Window: runtime.NewWindow(renderer),
|
|
||||||
Browser: runtime.NewBrowser(),
|
|
||||||
FileSystem: runtime.NewFileSystem(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
<script type="text/javascript">function AddScript(js, callbackID) {
|
|
||||||
var script = document.createElement('script');
|
|
||||||
script.text = js;
|
|
||||||
document.body.appendChild(script);
|
|
||||||
}</script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
@@ -19,6 +19,16 @@ func (r *Events) On(eventName string, callback func(optionalData ...interface{})
|
|||||||
r.eventManager.On(eventName, callback)
|
r.eventManager.On(eventName, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Once pass through
|
||||||
|
func (r *Events) Once(eventName string, callback func(optionalData ...interface{})) {
|
||||||
|
r.eventManager.Once(eventName, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnMultiple pass through
|
||||||
|
func (r *Events) OnMultiple(eventName string, callback func(optionalData ...interface{}), counter uint) {
|
||||||
|
r.eventManager.OnMultiple(eventName, callback, counter)
|
||||||
|
}
|
||||||
|
|
||||||
// Emit pass through
|
// Emit pass through
|
||||||
func (r *Events) Emit(eventName string, optionalData ...interface{}) {
|
func (r *Events) Emit(eventName string, optionalData ...interface{}) {
|
||||||
r.eventManager.Emit(eventName, optionalData...)
|
r.eventManager.Emit(eventName, optionalData...)
|
||||||
|
|||||||
@@ -13,8 +13,9 @@ import * as Browser from './browser';
|
|||||||
import { On, OnMultiple, Emit, Notify, Heartbeat, Acknowledge } from './events';
|
import { On, OnMultiple, Emit, Notify, Heartbeat, Acknowledge } from './events';
|
||||||
import { NewBinding } from './bindings';
|
import { NewBinding } from './bindings';
|
||||||
import { Callback } from './calls';
|
import { Callback } from './calls';
|
||||||
import { AddScript, InjectCSS } from './utils';
|
import { AddScript, InjectCSS, InjectFirebug } from './utils';
|
||||||
import { AddIPCListener } from './ipc';
|
import { AddIPCListener } from './ipc';
|
||||||
|
import * as Store from './store';
|
||||||
|
|
||||||
// Initialise global if not already
|
// Initialise global if not already
|
||||||
window.wails = window.wails || {};
|
window.wails = window.wails || {};
|
||||||
@@ -42,6 +43,7 @@ var runtime = {
|
|||||||
Heartbeat,
|
Heartbeat,
|
||||||
Acknowledge,
|
Acknowledge,
|
||||||
},
|
},
|
||||||
|
Store,
|
||||||
_: internal,
|
_: internal,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -58,6 +60,11 @@ window.onerror = function (msg, url, lineNo, columnNo, error) {
|
|||||||
window.wails.Log.Error('error: ' + error);
|
window.wails.Log.Error('error: ' + error);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Use firebug?
|
||||||
|
if( window.usefirebug ) {
|
||||||
|
InjectFirebug();
|
||||||
|
}
|
||||||
|
|
||||||
// Emit loaded event
|
// Emit loaded event
|
||||||
Emit('wails:loaded');
|
Emit('wails:loaded');
|
||||||
|
|
||||||
|
|||||||
82
runtime/js/core/store.js
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
_ __ _ __
|
||||||
|
| | / /___ _(_) /____
|
||||||
|
| | /| / / __ `/ / / ___/
|
||||||
|
| |/ |/ / /_/ / / (__ )
|
||||||
|
|__/|__/\__,_/_/_/____/
|
||||||
|
The lightweight framework for web-like apps
|
||||||
|
(c) Lea Anthony 2019-present
|
||||||
|
*/
|
||||||
|
/* jshint esversion: 6 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new sync store with the given name and optional default value
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @param {string} name
|
||||||
|
* @param {*} optionalDefault
|
||||||
|
*/
|
||||||
|
export function New(name, optionalDefault) {
|
||||||
|
|
||||||
|
var data;
|
||||||
|
|
||||||
|
// Check we are initialised
|
||||||
|
if( !window.wails) {
|
||||||
|
throw Error('Wails is not initialised');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store for the callbacks
|
||||||
|
let callbacks = [];
|
||||||
|
|
||||||
|
// Subscribe to updates by providing a callback
|
||||||
|
this.subscribe = (callback) => {
|
||||||
|
callbacks.push(callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
// sets the store data to the provided `newdata` value
|
||||||
|
this.set = (newdata) => {
|
||||||
|
|
||||||
|
data = newdata;
|
||||||
|
|
||||||
|
// Emit a notification to back end
|
||||||
|
window.wails.Events.Emit('wails:sync:store:updatedbyfrontend:'+name, JSON.stringify(data));
|
||||||
|
|
||||||
|
// Notify callbacks
|
||||||
|
callbacks.forEach( function(callback) {
|
||||||
|
callback(data);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// update mutates the value in the store by calling the
|
||||||
|
// provided method with the current value. The value returned
|
||||||
|
// by the updater function will be set as the new store value
|
||||||
|
this.update = (updater) => {
|
||||||
|
var newValue = updater(data);
|
||||||
|
this.set(newValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Setup event callback
|
||||||
|
window.wails.Events.On('wails:sync:store:updatedbybackend:'+name, function(result) {
|
||||||
|
|
||||||
|
// Parse data
|
||||||
|
result = JSON.parse(result);
|
||||||
|
|
||||||
|
// Todo: Potential preprocessing?
|
||||||
|
|
||||||
|
// Save data
|
||||||
|
data = result;
|
||||||
|
|
||||||
|
// Notify callbacks
|
||||||
|
callbacks.forEach( function(callback) {
|
||||||
|
callback(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set to the optional default if set
|
||||||
|
if( optionalDefault ) {
|
||||||
|
this.set(optionalDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
@@ -20,6 +20,18 @@ export function AddScript(js, callbackID) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function InjectFirebug() {
|
||||||
|
// set the debug attribute on HTML
|
||||||
|
var html = document.getElementsByTagName('html')[0];
|
||||||
|
html.setAttribute('debug', 'true');
|
||||||
|
var firebugURL = 'https://wails.app/assets/js/firebug-lite.js#startOpened=true,disableWhenFirebugActive=false';
|
||||||
|
var script = document.createElement('script');
|
||||||
|
script.src = firebugURL;
|
||||||
|
script.type = 'application/javascript';
|
||||||
|
document.head.appendChild(script);
|
||||||
|
window.wails.Log.Info('Injected firebug');
|
||||||
|
}
|
||||||
|
|
||||||
// Adapted from webview - thanks zserge!
|
// Adapted from webview - thanks zserge!
|
||||||
export function InjectCSS(css) {
|
export function InjectCSS(css) {
|
||||||
var elem = document.createElement('style');
|
var elem = document.createElement('style');
|
||||||
|
|||||||
6897
runtime/js/package-lock.json
generated
@@ -29,15 +29,15 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/wailsapp/runtime#readme",
|
"homepage": "https://github.com/wailsapp/runtime#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.5.0",
|
"@babel/cli": "^7.11.5",
|
||||||
"@babel/core": "^7.5.4",
|
"@babel/core": "^7.11.5",
|
||||||
"@babel/plugin-transform-object-assign": "^7.2.0",
|
"@babel/plugin-transform-object-assign": "^7.10.4",
|
||||||
"@babel/preset-env": "^7.5.4",
|
"@babel/preset-env": "^7.11.5",
|
||||||
"babel-loader": "^8.0.6",
|
"babel-loader": "^8.1.0",
|
||||||
"babel-preset-minify": "^0.5.0",
|
"babel-preset-minify": "^0.5.1",
|
||||||
"core-js": "^3.1.4",
|
"core-js": "^3.6.5",
|
||||||
"eslint": "^6.5.1",
|
"eslint": "^7.8.1",
|
||||||
"webpack": "^4.35.3",
|
"webpack": "^4.44.1",
|
||||||
"webpack-cli": "^3.3.5"
|
"webpack-cli": "^3.3.12"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,10 +13,12 @@ const Log = require('./log');
|
|||||||
const Browser = require('./browser');
|
const Browser = require('./browser');
|
||||||
const Events = require('./events');
|
const Events = require('./events');
|
||||||
const Init = require('./init');
|
const Init = require('./init');
|
||||||
|
const Store = require('./store');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
Log: Log,
|
Log: Log,
|
||||||
Browser: Browser,
|
Browser: Browser,
|
||||||
Events: Events,
|
Events: Events,
|
||||||
Init: Init
|
Init: Init,
|
||||||
|
Store: Store,
|
||||||
};
|
};
|
||||||