Compare commits

...

196 Commits

Author SHA1 Message Date
Lea\Anthony
b296fbbb99 Fix signatures
(cherry picked from commit 0f09e8d433)
2021-12-30 11:20:54 +11:00
Lea Anthony
26c4f112e3 [linux] Dialogs WIP 2021-12-29 09:47:31 +11:00
Lea\Anthony
f338dff171 Fix EventsOff in JS runtime 2021-12-29 09:11:12 +11:00
Lea\Anthony
3c6ed12637 New build flag: -debug 2021-12-29 06:54:52 +11:00
Lea Anthony
e2f3a11a33 [mac] Fix for cancelling Dialogs. Fixes #1047 2021-12-28 20:04:30 +11:00
Lea Anthony
0571deb290 Merge pull request #1046 from buddyabaddon/master
Make linuxdb.yaml an embedded resource
2021-12-28 17:27:59 +11:00
Matt McKenzie
451b357e40 Make linuxdb.yaml an embedded resource 2021-12-27 18:22:03 -08:00
Lea\Anthony
84b67a8f53 Add -u flag to sync project go.mod with CLI version 2021-12-28 06:40:44 +11:00
Lea Anthony
448cf731bb [mac] Fix for Save Dialog 2021-12-27 20:09:03 +11:00
Lea\Anthony
9cb480f0f0 v2.0.0-beta.27 2021-12-27 19:40:56 +11:00
Lea\Anthony
6825a631f5 Commit MicrosoftEdgeWebview2Setup.exe 2021-12-27 19:40:19 +11:00
Lea\Anthony
39f91a030f v2.0.0-beta.26 2021-12-27 18:12:48 +11:00
Lea\Anthony
202e4d5be8 Actually commit sudo_mattn 2021-12-27 18:11:12 +11:00
Lea\Anthony
045e58778a Actually commit webview2runtime 2021-12-27 18:09:41 +11:00
Lea\Anthony
e375d60c67 Updated modules 2021-12-27 05:23:18 +11:00
Lea\Anthony
fcb5499d3a v2.0.0-beta.25 2021-12-27 05:21:17 +11:00
Lea\Anthony
dd5a54a8e0 Remove replace line 2021-12-27 05:21:17 +11:00
Lea Anthony
9f24a46b8a Merge pull request #1042 from flin7/patch-1
Add template for React
2021-12-26 21:19:53 +11:00
flin7
d7eaab97dd Add template for React 2021-12-26 17:21:19 +08:00
Lea\Anthony
a03d1e5ac5 v2.0.0-beta.24 2021-12-26 20:13:42 +11:00
Lea\Anthony
d5d4d88481 [v2] Fix webview2 runtime detection. Fixes #1038 2021-12-26 19:24:59 +11:00
Lea\Anthony
1c823b09c4 [v2] Fix compile issue 2021-12-25 08:54:23 +11:00
Lea\Anthony
e5732bcee1 [v2] Update to webview2runtime v1.3.0 2021-12-25 08:51:43 +11:00
Lea Anthony
c0f283335a [mac] Fix for submenu titles. Fixes #1026. 2021-12-24 08:00:37 +11:00
Lea\Anthony
64cdf64751 [v2] export interfaces in runtime.d.ts 2021-12-23 06:27:49 +11:00
Lea Anthony
609bfc35c0 Update options.mdx 2021-12-22 21:17:46 +11:00
Lea\Anthony
121d11db55 [v2] Update sponsors 2021-12-22 06:36:18 +11:00
Lea\Anthony
5c357f012d [v2] Update context error 2021-12-22 06:28:47 +11:00
Lea\Anthony
56285f8637 [v2] Update docs 2021-12-21 08:53:48 +11:00
Lea Anthony
b61158d329 Merge pull request #1030 from raitonoberu/patch-1
Add Svelte template
2021-12-21 08:04:23 +11:00
Denis
0233197073 Add wails-svelte-template 2021-12-20 20:40:42 +07:00
Lea\Anthony
d883397d75 Update sponsors 2021-12-20 20:24:22 +11:00
Lea\Anthony
5bd82c4637 Update sponsors 2021-12-16 07:41:33 +11:00
Lea\Anthony
e942867635 Update sponsors 2021-12-16 07:41:14 +11:00
Lea Anthony
29749ed7cb Merge pull request #1025 from AlienRecall/patch-1
Added react template
2021-12-16 07:35:22 +11:00
AlienRecall
0288f33556 Added react template 2021-12-15 13:53:25 +01:00
Lea\Anthony
ddeac08991 v2.0.0-beta.23 2021-12-15 19:36:45 +11:00
Lea Anthony
30e12d681c [mac] Fix for save dialog 2021-12-15 19:16:43 +11:00
Lea Anthony
f9fce9f2a7 Merge pull request #1024 from achhabra2/patch-1
Add Riftshare to community showcase
2021-12-15 06:15:16 +11:00
Aman Chhabra
9c5bb8c6eb Add Riftshare to community showcase 2021-12-14 07:22:35 -08:00
Lea Anthony
f2ab409284 Update README.md 2021-12-13 20:40:50 +11:00
Lea\Anthony
7c190810fd Update easyweb logo 2021-12-13 20:40:03 +11:00
Lea\Anthony
2b2cd21674 Update sponsors 2021-12-13 20:32:55 +11:00
Lea Anthony
f025234c85 Merge pull request #1021 from dedo1911/master
[v2] feature / Add flag to skip mod tidy
2021-12-13 05:58:53 +11:00
Dario Emerson
44035637f7 Add flag to skip mod tidy 2021-12-12 15:01:16 +01:00
Lea Anthony
008a5c70b9 [mac] Fix linking issue. Removed warnings. 2021-12-11 20:06:42 +11:00
Lea\Anthony
24eaef1604 [mac] fix dynamically linking UTIFramework during cgo build 2021-12-11 19:43:21 +11:00
Lea\Anthony
62adcab722 [mac] try dynamically linking UTIFramework during cgo build 2021-12-11 19:36:17 +11:00
Lea Anthony
e12b630dfb [mac] Attempt to fix 10.14 compilation issue 2021-12-11 07:29:47 +11:00
Lea\Anthony
81b3ecb056 v1.16.9 2021-12-10 19:04:22 +11:00
Lea\Anthony
b4d14644ee Only generate ico if not there 2021-12-10 19:04:10 +11:00
Lea\Anthony
69fd584c32 Update sponsors 2021-12-10 19:00:26 +11:00
Lea Anthony
3444ec50a7 Merge pull request #1017 from stffabi/feature/add-upx-info-windows
[docs] Add info about upx and antivirus vendors
2021-12-09 21:55:52 +11:00
stffabi
02d4c65e01 [docs] Add info about upx and antivirus vendors 2021-12-09 11:03:53 +01:00
Lea Anthony
efdcfe9985 [v2] Remove AllowFiles & AllowDirectories 2021-12-09 08:16:45 +11:00
Lea Anthony
5884b7a87c Update supported platforms 2021-12-08 19:50:11 +11:00
Lea\Anthony
7229446ce7 v2.0.0-beta.22 2021-12-08 19:17:45 +11:00
Lea Anthony
c355d63768 Update bug_report.md 2021-12-08 18:44:36 +11:00
Lea Anthony
eb0030adeb Merge pull request #1012 from meatherly/fix_for_950
Fix for #950
2021-12-08 07:36:10 +11:00
Lea Anthony
fe224d9ecd Merge pull request #1013 from stffabi/feature/fsfs-docs-improvements
[v2] Update docs with new assetdir management and add reloaddirs
2021-12-07 17:08:45 +11:00
stffabi
a98d55db58 [v2] Update wails.json with updated reloaddirs from wails dev 2021-12-07 03:34:51 +01:00
stffabi
f034163da5 [v2] Update wails.json with updated assetdir from wails dev
Makes the code consistent with the docs
2021-12-07 03:34:51 +01:00
stffabi
d8fe011509 [v2] Update docs with new assetdir management and add reloaddirs 2021-12-07 03:34:19 +01:00
stffabi
e7bb3b3e83 [v2] Omit empty assetdir and reloaddirs in wails.json 2021-12-07 03:26:55 +01:00
meatherly
3201206d4f locking the event manager before mutating it. this should resolve issue #950 2021-12-06 16:21:35 -06:00
Lea Anthony
69c14d2a5d Merge pull request #1001 from stffabi/feature/fsfs-assets
proposal: [v2] Support fs.FS for assets
2021-12-07 06:03:59 +11:00
stffabi
778cbe04d9 [v2] Add reloaddirs flag to add additional reload directories
This is interesting if someone uses an asset FS which is not an embed.FS,
but still has some special handling to include loading data from disk in
dev mode. E.g. one might conditionally use an embed.FS or os.DirFS
depending on the build mode.
2021-12-06 13:47:16 +01:00
stffabi
131a8f421d [v2] Infer assetDir from embed.FS
AssetDir is now inferred from the assets, if the assets is an
embed.FS, by taking the relativ path to the index.html joined with
the project root.

The assetDir flag still exists and can be used if the inferring doesn't
work, because the provided embed.FS wasn't defined in the main
package.
2021-12-06 13:47:16 +01:00
stffabi
6fcd4b7bd4 [v2] Support fs.FS for assets
Reloading changed asset files in dev mode will only work
if an embed.FS has been provided for the assets.
2021-12-06 08:50:39 +01:00
Lea Anthony
f3b2f6ab76 Merge pull request #1011 from misitebao/optimize-documentation
docs: synchronize and optimize documents
2021-12-06 17:37:44 +11:00
misitebao
b556e860c4 docs: fix document translation 2021-12-06 11:10:36 +08:00
misitebao
eb01a005dc docs: fix document translation 2021-12-06 11:09:22 +08:00
misitebao
6dcee51940 docs: optimize english documents 2021-12-06 11:06:08 +08:00
misitebao
4c7a53b72b docs: synchronize chinese documents 2021-12-06 11:05:37 +08:00
Lea\Anthony
73c9fba731 [website] Added Angular router guide 2021-12-05 22:23:02 +11:00
Lea\Anthony
0726ae9e83 [website] Added router guide 2021-12-05 22:18:52 +11:00
Lea\Anthony
9ba4ca10ca [website] Link to Awesome Wails 2021-12-05 19:31:42 +11:00
Lea\Anthony
38caa645e5 [v2] A better approach to delayed IPC 2021-12-05 14:23:48 +11:00
Lea Anthony
41507e966a [linux] Remove signal handlers. Weird errors. 2021-12-04 20:10:37 +11:00
Lea Anthony
3092f04bcf [linux] Clean up signal handlers 2021-12-04 14:35:32 +11:00
Lea\Anthony
ffc0765a2f [website] Add OnBeforeClose docs 2021-12-04 14:31:59 +11:00
Lea Anthony
ac803aa426 Merge pull request #1007 from Ironpark/feature/on_before_close
[v2] feature / on-before-close resolve #978
2021-12-04 14:17:58 +11:00
ironpark
92b63d9fad window delegate modify for onBeforeClose hook 2021-12-04 07:52:34 +09:00
ironpark
fda3323386 basic implement 2021-12-04 04:55:36 +09:00
Lea Anthony
b7a4aba5f3 Merge pull request #1004 from stffabi/feature/improve-processrequest
[v2] Improve processRequest: Handle errors and behave more like a webserver
2021-12-04 05:01:36 +11:00
Lea Anthony
7848a028e3 Merge pull request #1002 from ianmjones/fix-cannot-use-uri-as-string-error
Fix error: cannot use uri (type *_Ctype_char) as type string in argument to common.TranslateUriToFile.
2021-12-04 04:51:09 +11:00
stffabi
d827aafe89 [v2] Improve processRequest: Handle errors and behave more like a webserver
This also fixes that requests remain in "pending" state on
darwin if e.g. a file is not found or an error occurs during
loading of the file.
2021-12-03 16:41:51 +01:00
Ian M. Jones
db8094cd68 Fix error: cannot use uri (type *_Ctype_char) as type string in argument to common.TranslateUriToFile. 2021-12-03 15:25:58 +00:00
Lea Anthony
59d29dc12f Merge pull request #998 from marcio199226/master
added ytd app to showcase
2021-12-03 01:56:53 -08:00
Lea Anthony
7aad934dae Remove yarn.lock 2021-12-03 20:56:30 +11:00
Oskar
0b1e33748a added ytd app to showcase 2021-12-02 21:29:43 +01:00
Lea Anthony
97be694d2a Merge pull request #996 from stffabi/feature/improved-translate-uri
[v2] Improve translation of URI to file to be loaded
2021-12-02 05:38:04 -08:00
Lea Anthony
576e574399 Merge pull request #994 from stffabi/feature/fix-webresourcerequest-memoryleak
[v2] Fix memory leak in processRequest for windows and darwin
2021-12-02 04:01:22 -08:00
Lea Anthony
6d9a195830 Merge pull request #991 from stffabi/feature/windows-frameless-border
[windows] Support drawing a frame for frameless to support hiding the titlebar
2021-12-02 04:00:01 -08:00
stffabi
8107a8bd1e [v2] Improve translation of URI to file to be loaded 2021-12-02 11:53:32 +01:00
stffabi
47d783291d [windows] Support drawing a frame for frameless to support hiding the titlebar 2021-12-02 11:16:13 +01:00
stffabi
0295f8dee2 [v2] Fix memory leak in processRequest for windows and darwin 2021-12-02 11:04:24 +01:00
stffabi
d915f73c6c [v2] Remove replace and bump winc 2021-12-02 11:01:30 +01:00
Lea Anthony
187bf3085c Merge pull request #989 from stffabi/feature/non-blocking-backend-calls
[v2] Do not block during processing of messages
2021-12-02 01:17:03 -08:00
stffabi
a353a653d1 [windows] Replace dispatch with invoke 2021-12-01 13:24:54 +01:00
stffabi
155f1fde49 [v2] Do not block during processing of messages
On windows blocking here results in a blocked main thread
and a blocked webview.
2021-12-01 13:24:19 +01:00
Lea Anthony
ec1a535acb Merge pull request #988 from stffabi/feature/windows-versioninfo
[v2] Windows: Add file information for windows
2021-12-01 03:09:04 -08:00
stffabi
fb5bcdc364 [v2] Windows: Add file information for windows 2021-12-01 11:59:46 +01:00
stffabi
e6f42247e7 [v2] Add missing import 2021-12-01 11:51:43 +01:00
Lea Anthony
4bc0b30231 [linux] Support closing window, hide window on close. 2021-12-01 20:32:23 +11:00
Lea\Anthony
1cd2645b87 [v2] Fix logging in prod builds. Fixes #983 2021-12-01 19:39:00 +11:00
Lea\Anthony
7904d0aadc [v2] Remove export in experimental TS generation for bindings 2021-12-01 19:19:28 +11:00
Lea\Anthony
06fa6850a1 [v2] Update experimental TS generation for bindings 2021-12-01 19:17:57 +11:00
Lea\Anthony
485f5831ac [v2] Experimental TS generation for bindings 2021-11-30 22:14:29 +11:00
Lea Anthony
587bcd8e21 Merge pull request #980 from stffabi/feature/winarm64-port
[v2] windows: Add arm64 support
2021-11-30 01:25:30 -08:00
stffabi
d43b7b1882 [windows] Add arm64 support 2021-11-30 10:07:27 +01:00
Lea\Anthony
ca147143ad [website] Improve binding docs in "how does it work" guide 2021-11-30 19:49:21 +11:00
Lea\Anthony
3371967dad [website] Update bleeding edge guide 2021-11-30 19:15:58 +11:00
Lea\Anthony
b09825ab0f [website] Fix bleeding edge guide 2021-11-30 19:14:48 +11:00
Lea\Anthony
5edf45468c [website] Add bleeding edge guide 2021-11-30 19:14:20 +11:00
Lea\Anthony
507e8d5222 [v2] Fix slash escaping in git username 2021-11-30 19:02:20 +11:00
Lea Anthony
b9283009df Merge pull request #974 from letheanVPN/npm-json-update
Adding name and author, + json handling improvement
2021-11-29 23:48:47 -08:00
Lea Anthony
60ddaf449d Update Sponsors 2021-11-30 18:41:42 +11:00
Lea Anthony
5bad81e182 Merge pull request #982 from stffabi/feature/windows-startstate-only-once
[v2] windows: Do not apply WindowStartState on reloads
2021-11-29 10:55:42 -08:00
stffabi
2e15f22621 [v2] Windows do not apply WindowStartState on reloads 2021-11-29 15:14:03 +01:00
Lea Anthony
6a3a822640 [linux] Fix content length in responses 2021-11-29 20:32:09 +11:00
Lea Anthony
e5057e1627 [linux] Fix installing cli 2021-11-29 20:25:11 +11:00
Lea Anthony
0a8f720586 [linux] Hook up runtime Window methods 2021-11-29 20:19:18 +11:00
Lea Anthony
5dbfb447b1 [linux] Support drag. 2021-11-29 20:04:57 +11:00
Lea Anthony
1f21dfbcfd [v2] Improved runtime builds. 2021-11-29 20:04:38 +11:00
Lea Anthony
53481830a9 [linux] Basic webview working 2021-11-29 08:25:42 +11:00
Lea Anthony
7eb8e6456e [linux] Devtools + dispatch. 2021-11-28 20:35:40 +11:00
Lea Anthony
5f0352404b [linux] Add basic webview. 2021-11-28 14:21:02 +11:00
Lea Anthony
b036b8c547 [linux] Support Window start state. fixed warnings. 2021-11-28 08:40:10 +11:00
Lea Anthony
39ca977b18 [linux] basic windowing pt2 2021-11-27 20:36:48 +11:00
Lea Anthony
abc078fb1b Merge pull request #976 from misitebao/optimize-documentation
docs: optimize document
2021-11-25 03:54:55 -08:00
misitebao
166490845c docs: fix translation 2021-11-25 19:34:53 +08:00
misitebao
c2399e3620 docs: optimize document content links 2021-11-25 19:26:31 +08:00
Lea Anthony
a2890b6d0d Merge pull request #956 from wailsapp/dependabot/npm_and_yarn/v2/internal/runtime/js/ssri-6.0.2
Bump ssri from 6.0.1 to 6.0.2 in /v2/internal/runtime/js
2021-11-25 00:00:05 -08:00
Lea Anthony
a1dee989c7 Merge pull request #957 from wailsapp/dependabot/npm_and_yarn/v2/internal/runtime/js/browserslist-4.18.1
Bump browserslist from 4.11.1 to 4.18.1 in /v2/internal/runtime/js
2021-11-24 23:59:42 -08:00
Lea Anthony
6ff1dac925 Merge pull request #958 from wailsapp/dependabot/npm_and_yarn/v2/internal/runtime/js/path-parse-1.0.7
Bump path-parse from 1.0.6 to 1.0.7 in /v2/internal/runtime/js
2021-11-24 23:59:26 -08:00
Lea Anthony
0b011929bf Merge pull request #959 from wailsapp/dependabot/npm_and_yarn/v2/internal/runtime/js/y18n-4.0.3
Bump y18n from 4.0.0 to 4.0.3 in /v2/internal/runtime/js
2021-11-24 23:59:08 -08:00
Lea Anthony
be3d1ff9e1 Merge pull request #960 from wailsapp/dependabot/npm_and_yarn/v2/internal/runtime/js/lodash-4.17.21
Bump lodash from 4.17.15 to 4.17.21 in /v2/internal/runtime/js
2021-11-24 23:58:48 -08:00
Lea Anthony
9c73b7285f Merge pull request #975 from Juneezee/deprecate-ioutil
refactor: move from io/ioutil to io and os packages
2021-11-24 23:57:51 -08:00
Lea Anthony
810793aba7 Merge pull request #973 from misitebao/fix-image-path
docs: fix image path errors and optimize assets paths
2021-11-24 23:40:29 -08:00
Eng Zer Jun
ef8d7d2fd7 refactor: move from io/ioutil to io and os packages
The io/ioutil package has been deprecated as of Go 1.16, see
https://golang.org/doc/go1.16#ioutil. This commit replaces the existing
io/ioutil functions with their new definitions in io and os packages.

Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
2021-11-25 12:15:43 +08:00
Eng Zer Jun
ae341be638 chore: run go fmt ./... and go mod tidy
Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
2021-11-25 12:14:27 +08:00
Snider
dcef8679d2 Adding name and author, also found out while trying to find options for value escaping the string conversion isnt needed :)
Signed-off-by: Snider <snider@lt.hn>
2021-11-24 18:50:26 +00:00
misitebao
0bb09a53ea docs: fix image path errors and optimize assets paths 2021-11-25 02:13:56 +08:00
Lea Anthony
deb1156916 Merge pull request #970 from stffabi/feature/use-winc-invoke
[v2] Use invoke to dispatch callbacks on windows
2021-11-24 04:21:39 -08:00
stffabi
1d87a81f63 [v2] Use invoke to dispatch callbacks on windows 2021-11-24 13:05:31 +01:00
stffabi
8ef8b2528b [v2] Bump winc to 0330cfc6d50c 2021-11-24 13:05:30 +01:00
Lea Anthony
f05109232e Merge pull request #961 from wailsapp/dependabot/npm_and_yarn/v2/internal/runtime/js/elliptic-6.5.4
Bump elliptic from 6.5.2 to 6.5.4 in /v2/internal/runtime/js
2021-11-24 03:06:21 -08:00
Lea Anthony
cf1001bffc Merge pull request #962 from wailsapp/dependabot/npm_and_yarn/v2/internal/runtime/js/ini-1.3.8
Bump ini from 1.3.5 to 1.3.8 in /v2/internal/runtime/js
2021-11-24 03:06:01 -08:00
Lea Anthony
7bf2218c36 Merge pull request #967 from misitebao/synchronize-documents
docs: synchronize and optimize chinese documents
2021-11-24 03:05:21 -08:00
Lea Anthony
48c9879bc4 Merge pull request #966 from wailsapp/dependabot/npm_and_yarn/website/algoliasearch-helper-3.6.2
Bump algoliasearch-helper from 3.5.5 to 3.6.2 in /website
2021-11-24 03:02:41 -08:00
Lea Anthony
2fe5e5ed01 Merge pull request #971 from letheanVPN/npm-workspace
Adding workspace to npm which better integrates wails and frontend npm.
2021-11-24 03:01:43 -08:00
Snider
38fd09bd9a Adding workspace to npm which better integrates wails and frontend npm.
Running `npm install` will now run on the top level of a generated project and additionally the "frontend" workspace (we can add plugins for wails like this, auto update, package, sign, etc, etc)

Other commands that use workspaces (including pre/post hooks mostly) and might be helpful to Wails are `docs`, `install`, `rebuild`, `publish`, `pkg`, `pack`, `ci`

For example, during wails build, you could ask for data from the frontend/package.json to get version, title, etc with.

`npm pkg get name version --workspace=frontend`

Signed-off-by: Snider <snider@lt.hn>
2021-11-24 10:34:29 +00:00
misitebao
4c5a81782b docs: sync the latest blog content 2021-11-24 13:28:35 +08:00
misitebao
ace3122e07 docs: optimize blog content 2021-11-24 13:27:41 +08:00
misitebao
f5c35487d9 docs: synchronize and optimize chinese documents 2021-11-24 12:52:36 +08:00
dependabot[bot]
06df0e1ee4 Bump algoliasearch-helper from 3.5.5 to 3.6.2 in /website
Bumps [algoliasearch-helper](https://github.com/algolia/algoliasearch-helper-js) from 3.5.5 to 3.6.2.
- [Release notes](https://github.com/algolia/algoliasearch-helper-js/releases)
- [Changelog](https://github.com/algolia/algoliasearch-helper-js/blob/develop/CHANGELOG)
- [Commits](https://github.com/algolia/algoliasearch-helper-js/compare/3.5.5...3.6.2)

---
updated-dependencies:
- dependency-name: algoliasearch-helper
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-23 21:42:58 +00:00
Lea Anthony
9735bd1b01 [website] v2.0.0-beta.21 2021-11-24 06:58:09 +11:00
Lea Anthony
cd8bad58cd [v] v2.0.0-beta.21 2021-11-24 06:42:34 +11:00
Lea Anthony
53a3cd9422 Merge pull request #965 from stffabi/feature/winguildflag-crosscompile
[v2] Add windowsgui ldflag when crosscompiling for windows
2021-11-23 10:39:10 -08:00
stffabi
5e2f25af9b [v2] Add windowsgui ldflag when crosscompiling for windows 2021-11-23 14:16:50 +01:00
dependabot[bot]
865d118651 Bump ini from 1.3.5 to 1.3.8 in /v2/internal/runtime/js
Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.8.
- [Release notes](https://github.com/isaacs/ini/releases)
- [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.8)

---
updated-dependencies:
- dependency-name: ini
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-23 11:51:06 +00:00
dependabot[bot]
6ea6bfeed0 Bump y18n from 4.0.0 to 4.0.3 in /v2/internal/runtime/js
Bumps [y18n](https://github.com/yargs/y18n) from 4.0.0 to 4.0.3.
- [Release notes](https://github.com/yargs/y18n/releases)
- [Changelog](https://github.com/yargs/y18n/blob/y18n-v4.0.3/CHANGELOG.md)
- [Commits](https://github.com/yargs/y18n/compare/v4.0.0...y18n-v4.0.3)

---
updated-dependencies:
- dependency-name: y18n
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-23 11:51:05 +00:00
dependabot[bot]
48527eb90a Bump lodash from 4.17.15 to 4.17.21 in /v2/internal/runtime/js
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.21)

---
updated-dependencies:
- dependency-name: lodash
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-23 11:51:05 +00:00
dependabot[bot]
33d8f98da9 Bump elliptic from 6.5.2 to 6.5.4 in /v2/internal/runtime/js
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.2 to 6.5.4.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.2...v6.5.4)

---
updated-dependencies:
- dependency-name: elliptic
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-23 11:51:05 +00:00
dependabot[bot]
658a30d16a Bump path-parse from 1.0.6 to 1.0.7 in /v2/internal/runtime/js
Bumps [path-parse](https://github.com/jbgutierrez/path-parse) from 1.0.6 to 1.0.7.
- [Release notes](https://github.com/jbgutierrez/path-parse/releases)
- [Commits](https://github.com/jbgutierrez/path-parse/commits/v1.0.7)

---
updated-dependencies:
- dependency-name: path-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-23 11:51:04 +00:00
dependabot[bot]
0189d1cb55 Bump browserslist from 4.11.1 to 4.18.1 in /v2/internal/runtime/js
Bumps [browserslist](https://github.com/browserslist/browserslist) from 4.11.1 to 4.18.1.
- [Release notes](https://github.com/browserslist/browserslist/releases)
- [Changelog](https://github.com/browserslist/browserslist/blob/main/CHANGELOG.md)
- [Commits](https://github.com/browserslist/browserslist/compare/4.11.1...4.18.1)

---
updated-dependencies:
- dependency-name: browserslist
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-23 11:51:01 +00:00
dependabot[bot]
8df94fa02b Bump ssri from 6.0.1 to 6.0.2 in /v2/internal/runtime/js
Bumps [ssri](https://github.com/npm/ssri) from 6.0.1 to 6.0.2.
- [Release notes](https://github.com/npm/ssri/releases)
- [Changelog](https://github.com/npm/ssri/blob/v6.0.2/CHANGELOG.md)
- [Commits](https://github.com/npm/ssri/compare/v6.0.1...v6.0.2)

---
updated-dependencies:
- dependency-name: ssri
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-23 11:51:00 +00:00
Lea Anthony
f5f89c31eb Merge pull request #955 from letheanVPN/generated-project-helper
Helper NPM scripts for developers working on a Wails GUI project
2021-11-23 03:50:29 -08:00
Snider
46cb34f2ec Adds a package.json with basic start / setup npm scripts to assist non golang developers working on an end project. 2021-11-23 11:22:25 +00:00
Lea Anthony
f6f13540c8 Merge pull request #954 from stffabi/feature/fix-mac-bgcolor
[macOS] Fix background color
2021-11-23 03:06:33 -08:00
stffabi
21ce7709ab [macOS] Fix background color 2021-11-23 11:18:00 +01:00
Lea Anthony
d569e37b81 [mac] Fix open panel in dev 2021-11-23 21:04:01 +11:00
Lea Anthony
c9c6edeb84 [mac] Fix fullscreen / start fullscreen 2021-11-23 20:06:56 +11:00
Lea Anthony
9525667ebd [windows] Add Frameless resize 2021-11-22 06:47:09 +11:00
Lea Anthony
28a3d86348 Merge pull request #951 from letheanVPN/snider-patch-1
Update Lethean project url
2021-11-20 01:07:43 -08:00
Snider
fc8aa58e62 Update Lethean project url 2021-11-20 07:10:41 +00:00
Lea Anthony
cb2bbacae8 Fix website 2021-11-20 18:02:23 +11:00
Lea Anthony
c3c6261a2d Update sponsors 2021-11-20 17:55:17 +11:00
Lea Anthony
8bfec24108 Support slices + out params in Models.ts generation. Update website with runtime info 2021-11-18 17:54:09 +11:00
Lea Anthony
9ad2665ad8 [mac] Conditionally import UTType header 2021-11-17 21:13:25 +11:00
Lea Anthony
28894868e3 [mac] Fix for file filters MacOS 11+. Some memory leak fixes. 2021-11-17 21:03:40 +11:00
Lea Anthony
a8fcd994c9 Merge branch '930_-_default_window_state' 2021-11-16 18:23:43 +11:00
Lea Anthony
c678ab7d01 [mac] Potential file dialog fix. Fix for starthidden. Partial WindowStartState 2021-11-16 18:20:41 +11:00
Lea Anthony
3a93c08813 [linux] basic windowing 2021-11-14 22:40:37 +11:00
Lea Anthony
ab1469638f [linux] get compiling working 2021-11-13 17:06:48 -08:00
Lea Anthony
9073caf287 Add build flag 2021-11-13 16:31:57 -08:00
Lea Anthony
1bed8234c9 [v2] Fix OnShutdown for production build 2021-11-11 06:05:50 +11:00
Lea Anthony
621c70253d [v2] Remove build constraint for DesktopIPC 2021-11-10 18:12:46 +11:00
Lea Anthony
56ef4ddd47 [v2] Add WindowStartState. Fix startHidden option. Only windows supported atm 2021-11-10 18:11:54 +11:00
Lea Anthony
bad9ad3dd7 [v2] Refactor app options 2021-11-10 08:42:04 +11:00
Lea Anthony
36570645ff [v2] v2.0.0-beta.20 2021-11-09 20:37:44 +11:00
Lea Anthony
3711bdc41e [v2] Add default wailsjsdir when generating module 2021-11-09 20:31:51 +11:00
Lea Anthony
cbdcd9f63e [v2] Add default wailsjsdir to templates 2021-11-09 20:31:31 +11:00
Lea Anthony
a9268bc56e [v2] Re-enable cli flags for assetdir if needed. Fixes debugging from IDE. 2021-11-09 20:11:34 +11:00
Lea Anthony
f489347fca [website] Update sponsors 2021-11-09 06:39:36 +11:00
194 changed files with 4842 additions and 1131 deletions

View File

@@ -8,7 +8,7 @@ assignees: ''
---
#####################################################
**If you have a technical issue, please do not open a bug this way!**
**V1 users: If you have a technical issue, please do not open a bug this way!**
Please use the `wails issue` command!
If you do not do this then the issue may be closed automatically.
@@ -33,7 +33,7 @@ A clear and concise description of what you expected to happen.
If applicable, add screenshots to help explain your problem.
**System Details**
Please provide your platform, GO version and variables, etc
V2 users: Please add the output of `wails doctor`.
**Additional context**
Add any other context about the problem here.

View File

@@ -1,17 +1,35 @@
<p align="center" style="text-align: center">
<img src="logo.png" width="55%"><br/>
<img src="logo.png" width="55%"><br/>
</p>
<p align="center">
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://goreportcard.com/report/github.com/wailsapp/wails"><img src="https://goreportcard.com/badge/github.com/wailsapp/wails"/></a>
<a href="http://godoc.org/github.com/wailsapp/wails"><img src="https://img.shields.io/badge/godoc-reference-blue.svg"/></a>
<a href="https://www.codefactor.io/repository/github/wailsapp/wails"><img src="https://www.codefactor.io/repository/github/wailsapp/wails/badge" alt="CodeFactor" /></a>
<a href="https://github.com/wailsapp/wails/issues"><img src="https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat" alt="CodeFactor" /></a>
<a href="https://app.fossa.io/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_shield" alt="FOSSA Status"><img src="https://app.fossa.io/api/projects/git%2Bgithub.com%2Fwailsapp%2Fwails.svg?type=shield"/></a>
<a href="https://houndci.com"><img src="https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg"/></a>
<a href="https://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>
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://goreportcard.com/report/github.com/wailsapp/wails">
<img src="https://goreportcard.com/badge/github.com/wailsapp/wails"/>
</a>
<a href="http://godoc.org/github.com/wailsapp/wails">
<img src="https://img.shields.io/badge/godoc-reference-blue.svg"/>
</a>
<a href="https://www.codefactor.io/repository/github/wailsapp/wails">
<img src="https://www.codefactor.io/repository/github/wailsapp/wails/badge" alt="CodeFactor" />
</a>
<a href="https://github.com/wailsapp/wails/issues">
<img src="https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat" alt="CodeFactor" />
</a>
<a href="https://app.fossa.io/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_shield" alt="FOSSA Status">
<img src="https://app.fossa.io/api/projects/git%2Bgithub.com%2Fwailsapp%2Fwails.svg?type=shield"/>
</a>
<a href="https://houndci.com">
<img src="https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg"/>
</a>
<a href="https://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>
</p>
<span id="nav-1"></span>
@@ -88,6 +106,21 @@ Click [here](https://wails.io) if you are interested in trying out v2 Beta for W
This project is supported by these kind people / companies:
<p align="center">
<a href="https://www.easywebadv.it/" style="width:150px;">
<img src="website/static/img/easyweb.png" width="150"/>
</a>
</p>
<br/>
<br/>
<a href="https://github.com/sponsors/leaanthony" style="width:100px;">
<img src="sponsors/silver%20sponsor.png" width="100"/>
</a>
<a href="https://github.com/letheanVPN" style="width:100px;">
<img src="https://github.com/letheanVPN.png?size=100" width="100"/>
</a>
<br/>
<br/>
<a href="https://github.com/sponsors/leaanthony" style="width:100px;">
<img src="sponsors/bronze%20sponsor.png" width="100"/>
</a>
@@ -97,13 +130,16 @@ This project is supported by these kind people / companies:
<a href="https://github.com/codydbentley" style="width:100px">
<img src="https://github.com/codydbentley.png?size=100" width="100"/>
</a>
<a href="https://github.com/CrackDavid" style="width:100px">
<img src="https://github.com/CrackDavid.png?size=100" width="100"/>
</a>
<br/>
<br/>
<a href="https://github.com/matryer" style="width:100px">
<img src="https://github.com/matryer.png" width="100"/>
</a>
<a href="https://www.jetbrains.com?from=Wails" style="width:100px">
<img src="/img/jetbrains-grayscale.png" width="100"/>
<img src="/assets/images/jetbrains-grayscale.png" width="100"/>
</a>
<a href="https://github.com/tc-hib" style="width:55px">
<img src="https://github.com/tc-hib.png?size=55" width="55"/>
@@ -147,15 +183,27 @@ This project is supported by these kind people / companies:
<a href="https://github.com/ilgityildirim" style="width:50px">
<img src="https://github.com/ilgityildirim.png?size=50" width="50"/>
</a>
<a href="https://github.com/ondoki" style="width:65px">
<img src="https://github.com/ondoki.png?size=65" width="65"/>
</a>
<a href="https://github.com/questrail" style="width:50px">
<img src="https://github.com/questrail.png?size=50" width="50"/>
</a>
<a href="https://github.com/DonTomato" style="width:45px">
<img src="https://github.com/DonTomato.png?size=45" width="45"/>
</a>
<a href="https://github.com/taigrr" style="width:45px">
<img src="https://github.com/taigrr.png?size=45" width="45"/>
</a>
<a href="https://github.com/charlie-dee" style="width:55px">
<img src="https://github.com/charlie-dee.png?size=55" width="55"/>
</a>
<a href="https://github.com/EdenNetworkItalia" style="width:65px">
<img src="https://github.com/EdenNetworkItalia.png?size=65" width="65"/>
</a>
<a href="https://github.com/michaelolson1996" style="width:55px">
<img src="https://github.com/michaelolson1996.png?size=55" width="55"/>
</a>
<a href="https://github.com/GargantuaX" style="width:45px">
<img src="https://github.com/GargantuaX.png?size=45" width="45"/>
</a>
<span id="nav-6"></span>
@@ -319,11 +367,11 @@ It is recommended at this stage to read the comprehensive documentation at [http
<a href="https://github.com/SophieAu"><img src="https://github.com/SophieAu.png?size=40" width="40"/></a>
<a href="https://github.com/alexmat"><img src="https://github.com/alexmat.png?size=40" width="40"/></a>
<a href="https://github.com/RH12503"><img src="https://github.com/RH12503.png?size=40" width="40"/></a>
<a href="https://github.com/hi019"><img src="https://github.com/hi019.png?size=40" width="40"/></a></a>
<a href="https://github.com/Igogrek"><img src="https://github.com/Igogrek.png?size=40" width="40"/></a></a>
<a href="https://github.com/aschey"><img src="https://github.com/aschey.png?size=40" width="40"/></a></a>
<a href="https://github.com/akhudek"><img src="https://github.com/akhudek.png?size=40" width="40"/></a></a>
<a href="https://github.com/s12chung"><img src="https://github.com/s12chung.png?size=40" width="40"/></a></a>
<a href="https://github.com/hi019"><img src="https://github.com/hi019.png?size=40" width="40"/></a>
<a href="https://github.com/Igogrek"><img src="https://github.com/Igogrek.png?size=40" width="40"/></a>
<a href="https://github.com/aschey"><img src="https://github.com/aschey.png?size=40" width="40"/></a>
<a href="https://github.com/akhudek"><img src="https://github.com/akhudek.png?size=40" width="40"/></a>
<a href="https://github.com/s12chung"><img src="https://github.com/s12chung.png?size=40" width="40"/></a>
<span id="nav-10"></span>
@@ -359,7 +407,7 @@ This project was mainly coded to the following albums:
## Special Thanks
<p align="center" style="text-align: center">
<a href="https://pace.dev"><img src="pace.jpeg"/></a><br/>
<a href="https://pace.dev"><img src="/assets/images/pace.jpeg"/></a><br/>
A <i>huge</i> 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>
@@ -367,5 +415,5 @@ This project was mainly coded to the following albums:
<p align="center" style="text-align: center">
A special thank you to JetBrains for donating licenses to us!<br/><br/>
Please click the logo to let them know your appreciation!<br/><br/>
<a href="https://www.jetbrains.com?from=Wails"><img src="jetbrains-grayscale.png" width="30%"></a>
<a href="https://www.jetbrains.com?from=Wails"><img src="/assets/images/jetbrains-grayscale.png" width="30%"></a>
</p>

View File

@@ -2,16 +2,34 @@
<img src="logo.png" width="55%"><br/>
</p>
<p align="center">
使用 Go 和 Web 技术构建桌面应用程序。<br/><br/>
<a href="https://github.com/wailsapp/wails/blob/master/LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg"></a>
<a href="https://goreportcard.com/report/github.com/wailsapp/wails"><img src="https://goreportcard.com/badge/github.com/wailsapp/wails"/></a>
<a href="http://godoc.org/github.com/wailsapp/wails"><img src="https://img.shields.io/badge/godoc-reference-blue.svg"/></a>
<a href="https://www.codefactor.io/repository/github/wailsapp/wails"><img src="https://www.codefactor.io/repository/github/wailsapp/wails/badge" alt="CodeFactor" /></a>
<a href="https://github.com/wailsapp/wails/issues"><img src="https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat" alt="CodeFactor" /></a>
<a href="https://app.fossa.io/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_shield" alt="FOSSA Status"><img src="https://app.fossa.io/api/projects/git%2Bgithub.com%2Fwailsapp%2Fwails.svg?type=shield"/></a>
<a href="https://houndci.com"><img src="https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg"/></a>
<a href="https://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>
使用 Go 和 Web 技术构建桌面应用程序。<br/><br/>
<a href="https://github.com/wailsapp/wails/blob/master/LICENSE">
<img src="https://img.shields.io/badge/License-MIT-blue.svg">
</a>
<a href="https://goreportcard.com/report/github.com/wailsapp/wails">
<img src="https://goreportcard.com/badge/github.com/wailsapp/wails"/>
</a>
<a href="http://godoc.org/github.com/wailsapp/wails">
<img src="https://img.shields.io/badge/godoc-reference-blue.svg"/>
</a>
<a href="https://www.codefactor.io/repository/github/wailsapp/wails">
<img src="https://www.codefactor.io/repository/github/wailsapp/wails/badge" alt="CodeFactor" />
</a>
<a href="https://github.com/wailsapp/wails/issues">
<img src="https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat" alt="CodeFactor" />
</a>
<a href="https://app.fossa.io/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_shield" alt="FOSSA Status">
<img src="https://app.fossa.io/api/projects/git%2Bgithub.com%2Fwailsapp%2Fwails.svg?type=shield"/>
</a>
<a href="https://houndci.com">
<img src="https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg"/>
</a>
<a href="https://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>
</p>
<span id="nav-1"></span>
@@ -91,6 +109,21 @@
这个项目由以下这些人或者公司支持:
<p align="center">
<a href="https://www.easywebadv.it/" style="width:100px;">
<img src="website/static/img/easyweb.png" width="120"/>
</a>
</p>
<br/>
<br/>
<a href="https://github.com/sponsors/leaanthony" style="width:100px;">
<img src="sponsors/silver%20sponsor.png" width="100"/>
</a>
<a href="https://github.com/letheanVPN" style="width:100px;">
<img src="https://github.com/letheanVPN.png?size=100" width="100"/>
</a>
<br/>
<br/>
<a href="https://github.com/sponsors/leaanthony" style="width:100px;">
<img src="sponsors/bronze%20sponsor.png" width="100"/>
</a>
@@ -100,13 +133,16 @@
<a href="https://github.com/codydbentley" style="width:100px">
<img src="https://github.com/codydbentley.png?size=100" width="100"/>
</a>
<a href="https://github.com/CrackDavid" style="width:100px">
<img src="https://github.com/CrackDavid.png?size=100" width="100"/>
</a>
<br/>
<br/>
<a href="https://github.com/matryer" style="width:100px">
<img src="https://github.com/matryer.png" width="100"/>
</a>
<a href="https://www.jetbrains.com?from=Wails" style="width:100px">
<img src="/img/jetbrains-grayscale.png" width="100"/>
<img src="/assets/images/jetbrains-grayscale.png" width="100"/>
</a>
<a href="https://github.com/tc-hib" style="width:55px">
<img src="https://github.com/tc-hib.png?size=55" width="55"/>
@@ -150,15 +186,27 @@
<a href="https://github.com/ilgityildirim" style="width:50px">
<img src="https://github.com/ilgityildirim.png?size=50" width="50"/>
</a>
<a href="https://github.com/ondoki" style="width:65px">
<img src="https://github.com/ondoki.png?size=65" width="65"/>
</a>
<a href="https://github.com/questrail" style="width:50px">
<img src="https://github.com/questrail.png?size=50" width="50"/>
</a>
<a href="https://github.com/DonTomato" style="width:45px">
<img src="https://github.com/DonTomato.png?size=45" width="45"/>
</a>
<a href="https://github.com/taigrr" style="width:45px">
<img src="https://github.com/taigrr.png?size=45" width="45"/>
</a>
<a href="https://github.com/charlie-dee" style="width:55px">
<img src="https://github.com/charlie-dee.png?size=55" width="55"/>
</a>
<a href="https://github.com/EdenNetworkItalia" style="width:65px">
<img src="https://github.com/EdenNetworkItalia.png?size=65" width="65"/>
</a>
<a href="https://github.com/michaelolson1996" style="width:55px">
<img src="https://github.com/michaelolson1996.png?size=55" width="55"/>
</a>
<a href="https://github.com/GargantuaX" style="width:45px">
<img src="https://github.com/GargantuaX.png?size=45" width="45"/>
</a>
<span id="nav-6"></span>
@@ -315,11 +363,11 @@ go get -u github.com/wailsapp/wails/cmd/wails
<a href="https://github.com/SophieAu"><img src="https://github.com/SophieAu.png?size=40" width="40"/></a>
<a href="https://github.com/alexmat"><img src="https://github.com/alexmat.png?size=40" width="40"/></a>
<a href="https://github.com/RH12503"><img src="https://github.com/RH12503.png?size=40" width="40"/></a>
<a href="https://github.com/hi019"><img src="https://github.com/hi019.png?size=40" width="40"/></a></a>
<a href="https://github.com/Igogrek"><img src="https://github.com/Igogrek.png?size=40" width="40"/></a></a>
<a href="https://github.com/aschey"><img src="https://github.com/aschey.png?size=40" width="40"/></a></a>
<a href="https://github.com/akhudek"><img src="https://github.com/akhudek.png?size=40" width="40"/></a></a>
<a href="https://github.com/s12chung"><img src="https://github.com/s12chung.png?size=40" width="40"/></a></a>
<a href="https://github.com/hi019"><img src="https://github.com/hi019.png?size=40" width="40"/></a>
<a href="https://github.com/Igogrek"><img src="https://github.com/Igogrek.png?size=40" width="40"/></a>
<a href="https://github.com/aschey"><img src="https://github.com/aschey.png?size=40" width="40"/></a>
<a href="https://github.com/akhudek"><img src="https://github.com/akhudek.png?size=40" width="40"/></a>
<a href="https://github.com/s12chung"><img src="https://github.com/s12chung.png?size=40" width="40"/></a>
<span id="nav-10"></span>
@@ -352,7 +400,7 @@ go get -u github.com/wailsapp/wails/cmd/wails
## 特别感谢
<p align="center" style="text-align: center">
<a href="https://pace.dev"><img src="pace.jpeg"/></a><br/>
<a href="https://pace.dev"><img src="/assets/images/pace.jpeg"/></a><br/>
<i>非常</i> 感谢<a href="https://pace.dev">Pace</a>对项目的赞助,并帮助将 Wails 移植到 Apple Silicon !<br/><br/>
如果您正在寻找一个强大并且快速和易于使用的项目管理工具,可以看看他们!<br/><br/>
</p>
@@ -360,5 +408,5 @@ go get -u github.com/wailsapp/wails/cmd/wails
<p align="center" style="text-align: center">
特别感谢 JetBrains 向我们捐赠许可!<br/><br/>
请点击 logo 让他们知道你的感激之情!<br/><br/>
<a href="https://www.jetbrains.com?from=Wails"><img src="jetbrains-grayscale.png" width="30%"></a>
<a href="https://www.jetbrains.com?from=Wails"><img src="/assets/images/jetbrains-grayscale.png" width="30%"></a>
</p>

View File

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 103 KiB

View File

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -6,7 +6,6 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"path"
@@ -50,7 +49,7 @@ func (fs *FSHelper) FileExists(path string) bool {
// FindFile returns the first occurrence of match inside path.
func (fs *FSHelper) FindFile(path, match string) (string, error) {
files, err := ioutil.ReadDir(path)
files, err := os.ReadDir(path)
if err != nil {
return "", err
}
@@ -69,7 +68,7 @@ func (fs *FSHelper) FindFile(path, match string) (string, error) {
func (fs *FSHelper) CreateFile(filename string, data []byte) error {
// Ensure directory exists
fs.MkDirs(filepath.Dir(filename))
return ioutil.WriteFile(filename, data, 0644)
return os.WriteFile(filename, data, 0644)
}
// MkDirs creates the given nested directories.
@@ -149,21 +148,11 @@ func (fs *FSHelper) LocalDir(dir string) (*Dir, error) {
}, err
}
// LoadRelativeFile loads the given file relative to the caller's directory
func (fs *FSHelper) LoadRelativeFile(relativePath string) ([]byte, error) {
_, filename, _, _ := runtime.Caller(0)
fullPath, err := filepath.Abs(filepath.Join(path.Dir(filename), relativePath))
if err != nil {
return nil, err
}
return ioutil.ReadFile(fullPath)
}
// GetSubdirs will return a list of FQPs to subdirectories in the given directory
func (d *Dir) GetSubdirs() (map[string]string, error) {
// Read in the directory information
fileInfo, err := ioutil.ReadDir(d.fullPath)
fileInfo, err := os.ReadDir(d.fullPath)
if err != nil {
return nil, err
}
@@ -215,7 +204,7 @@ func (fs *FSHelper) SaveAsJSON(data interface{}, filename string) error {
e.SetIndent("", " ")
e.Encode(data)
err := ioutil.WriteFile(filename, buf.Bytes(), 0755)
err := os.WriteFile(filename, buf.Bytes(), 0755)
if err != nil {
return err
}
@@ -231,7 +220,7 @@ func (fs *FSHelper) LoadAsString(filename string) (string, error) {
// LoadAsBytes returns the contents of the file as a byte slice
func (fs *FSHelper) LoadAsBytes(filename string) ([]byte, error) {
return ioutil.ReadFile(filename)
return os.ReadFile(filename)
}
// FileMD5 returns the md5sum of the given file

View File

@@ -3,7 +3,7 @@ package cmd
import (
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net/http"
"sort"
)
@@ -28,7 +28,7 @@ func (g *GitHubHelper) GetVersionTags() ([]*SemanticVersion, error) {
if err != nil {
return result, err
}
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
return result, err
}

View File

@@ -2,7 +2,6 @@ package cmd
import (
"fmt"
"io/ioutil"
"net/url"
"os"
"runtime"
@@ -75,7 +74,6 @@ const (
NixOS
// Artix linux distribution
ArtixLinux
)
// DistroInfo contains all the information relating to a linux distribution
@@ -96,7 +94,7 @@ func GetLinuxDistroInfo() *DistroInfo {
}
_, err := os.Stat("/etc/os-release")
if !os.IsNotExist(err) {
osRelease, _ := ioutil.ReadFile("/etc/os-release")
osRelease, _ := os.ReadFile("/etc/os-release")
result = parseOsRelease(string(osRelease))
}
return result

View File

@@ -1,11 +1,15 @@
package cmd
import (
_ "embed"
"log"
"gopkg.in/yaml.v3"
)
//go:embed linuxdb.yaml
var LinuxDBYaml []byte
// LinuxDB is the database for linux distribution data.
type LinuxDB struct {
Distributions map[string]*Distribution `yaml:"distributions"`
@@ -78,14 +82,10 @@ func (l *LinuxDB) GetDistro(distro string) *Distribution {
// NewLinuxDB creates a new LinuxDB instance from the bundled
// linuxdb.yaml file.
func NewLinuxDB() *LinuxDB {
data, err := fs.LoadRelativeFile("./linuxdb.yaml")
if err != nil {
log.Fatal("Could not load linuxdb.yaml")
}
result := LinuxDB{
Distributions: make(map[string]*Distribution),
}
err = result.ImportData(data)
err := result.ImportData(LinuxDBYaml)
if err != nil {
log.Fatal(err)
}

View File

@@ -7,7 +7,6 @@ import (
"fmt"
"image"
"image/png"
"io/ioutil"
"os"
"path"
"path/filepath"
@@ -244,7 +243,7 @@ func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
// No - create a new plist from our defaults
tmpl := template.New("infoPlist")
plistFile := filepath.Join(b.getPackageFileBaseDir(), "info.plist")
infoPlist, err := ioutil.ReadFile(plistFile)
infoPlist, err := os.ReadFile(plistFile)
if err != nil {
return err
}
@@ -258,13 +257,13 @@ func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
}
// Save to the package
err = ioutil.WriteFile(plistFilename, tpl.Bytes(), 0644)
err = os.WriteFile(plistFilename, tpl.Bytes(), 0644)
if err != nil {
return err
}
// Also write to project directory for customisation
err = ioutil.WriteFile(customPlist, tpl.Bytes(), 0644)
err = os.WriteFile(customPlist, tpl.Bytes(), 0644)
if err != nil {
return err
}
@@ -314,10 +313,12 @@ func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
return err
}
// Generate icon from PNG
err = generateWindowsIcon(icon, basename+".ico")
if err != nil {
return err
// Generate icon from PNG if it doesn't exist
if !fs.FileExists(basename + ".ico") {
err = generateWindowsIcon(icon, basename+".ico")
if err != nil {
return err
}
}
// Copy manifest
@@ -334,12 +335,12 @@ func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
tgtRCFile := filepath.Join(outputDir, basename+".rc")
if !b.fs.FileExists(tgtRCFile) {
srcRCfile := filepath.Join(b.getPackageFileBaseDir(), "wails.rc")
rcfilebytes, err := ioutil.ReadFile(srcRCfile)
rcfilebytes, err := os.ReadFile(srcRCfile)
if err != nil {
return err
}
rcfiledata := strings.Replace(string(rcfilebytes), "$NAME$", basename, -1)
err = ioutil.WriteFile(tgtRCFile, []byte(rcfiledata), 0755)
err = os.WriteFile(tgtRCFile, []byte(rcfiledata), 0755)
if err != nil {
return err
}
@@ -387,11 +388,11 @@ func (b *PackageHelper) copyIcon() (string, error) {
// Install default icon
iconfile := filepath.Join(b.getPackageFileBaseDir(), "icon.png")
iconData, err := ioutil.ReadFile(iconfile)
iconData, err := os.ReadFile(iconfile)
if err != nil {
return "", err
}
err = ioutil.WriteFile(srcIcon, iconData, 0644)
err = os.WriteFile(srcIcon, iconData, 0644)
if err != nil {
return "", err
}

View File

@@ -3,7 +3,6 @@ package cmd
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"runtime"
@@ -310,14 +309,14 @@ func (po *ProjectOptions) WriteProjectConfig() error {
return err
}
return ioutil.WriteFile(targetFile, filedata, 0600)
return os.WriteFile(targetFile, filedata, 0600)
}
// LoadConfig loads the project configuration file from the
// given directory
func (po *ProjectOptions) LoadConfig(projectDir string) error {
targetFile := filepath.Join(projectDir, "project.json")
rawBytes, err := ioutil.ReadFile(targetFile)
rawBytes, err := os.ReadFile(targetFile)
if err != nil {
return err
}

View File

@@ -3,7 +3,6 @@ package cmd
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
@@ -124,7 +123,7 @@ func (s *SystemHelper) setup() error {
if err != nil {
return err
}
err = ioutil.WriteFile(s.wailsSystemConfig, configData, 0755)
err = os.WriteFile(s.wailsSystemConfig, configData, 0755)
if err != nil {
return err
}
@@ -207,11 +206,11 @@ func (sc *SystemConfig) Save(filename string) error {
}
// Write it out to the config file
return ioutil.WriteFile(filename, theJSON, 0644)
return os.WriteFile(filename, theJSON, 0644)
}
func (sc *SystemConfig) load(filename string) error {
configData, err := ioutil.ReadFile(filename)
configData, err := os.ReadFile(filename)
if err != nil {
return err
}

View File

@@ -4,8 +4,8 @@ import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"runtime"
"strings"
@@ -125,7 +125,7 @@ func (t *TemplateHelper) LoadMetadata(dir string) (*TemplateMetadata, error) {
if !t.fs.FileExists(templateFile) {
return nil, nil
}
rawJSON, err := ioutil.ReadFile(templateFile)
rawJSON, err := os.ReadFile(templateFile)
if err != nil {
return nil, err
}

View File

@@ -1,4 +1,4 @@
package cmd
// Version - Wails version
const Version = "v1.16.8"
const Version = "v1.16.9"

View File

@@ -3,7 +3,6 @@ package main
import (
"bufio"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
@@ -305,7 +304,7 @@ func updateWailsVersion(currentVersion, latestVersion *semver.Version) error {
new := fmt.Sprintf("%s v%s", wailsModule, latestVersion)
goMod = strings.Replace(goMod, old, new, -1)
err := ioutil.WriteFile(goModFile, []byte(goMod), 0600)
err := os.WriteFile(goModFile, []byte(goMod), 0600)
if err != nil {
checkSpinner.Error()
return err
@@ -343,7 +342,7 @@ func patchMainJS() error {
newStartLine := `Wails.Init`
mainJSContents = strings.Replace(mainJSContents, oldStartLine, newStartLine, -1)
err := ioutil.WriteFile(mainJSFile, []byte(mainJSContents), 0600)
err := os.WriteFile(mainJSFile, []byte(mainJSContents), 0600)
if err != nil {
checkSpinner.Error()
return err

View File

@@ -2,7 +2,7 @@ package main
import (
"fmt"
"io/ioutil"
"io"
"net/http"
"net/url"
"os"
@@ -112,7 +112,7 @@ To help you in this process, we will ask for some information, add Go/Wails deta
os.Exit(1)
}
defer resp.Body.Close()
template, _ := ioutil.ReadAll(resp.Body)
template, _ := io.ReadAll(resp.Body)
body := string(template)
body = "**Description**\n" + (strings.Split(body, "**Description**")[1])
fullURL := "https://github.com/wailsapp/wails/issues/new?"

2
go.mod
View File

@@ -8,7 +8,6 @@ require (
github.com/gorilla/websocket v1.4.1
github.com/jackmordaunt/icns v1.0.0
github.com/kennygrant/sanitize v1.2.4
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/leaanthony/slicer v1.4.0
github.com/leaanthony/spinner v0.5.3
github.com/mattn/go-colorable v0.1.1 // indirect
@@ -17,7 +16,6 @@ require (
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4
github.com/pkg/errors v0.8.1 // indirect
github.com/sirupsen/logrus v1.8.1
github.com/stretchr/objx v0.1.1 // indirect
github.com/stretchr/testify v1.3.0 // indirect
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba
golang.org/x/image v0.0.0-20200430140353-33d19683fad8

9
go.sum
View File

@@ -21,9 +21,6 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kennygrant/sanitize v1.2.4 h1:gN25/otpP5vAsO2djbMhF/LQX6R7+O1TB4yv8NzpJ3o=
github.com/kennygrant/sanitize v1.2.4/go.mod h1:LGsjYYtgxbetdg5owWB2mpgUL6e2nfw2eObZ0u0qvak=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/leaanthony/slicer v1.4.0 h1:Q9u4w+UBU4WHjXnEDdz+eRLMKF/rnyosRBiqULnc1J8=
@@ -52,12 +49,9 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
@@ -73,15 +67,12 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c h1:UIcGWL6/wpCfyGuJnRFJRurA+yj8RrW7Q6x2YMCXt6c=
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359 h1:2B5p2L5IfGiD7+b9BOoRMC6DgObAVZV+Fsp050NqXik=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=

View File

@@ -2,7 +2,6 @@ package binding
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"reflect"
@@ -144,7 +143,7 @@ export {};`
dir := filepath.Dir(typescriptDefinitionFilename)
os.MkdirAll(dir, 0755)
return ioutil.WriteFile(typescriptDefinitionFilename, []byte(output.String()), 0755)
return os.WriteFile(typescriptDefinitionFilename, []byte(output.String()), 0755)
}
// bind the given struct method

View File

@@ -55,20 +55,20 @@ func (e *Manager) addEventListener(eventName string, callback func(...interface{
return fmt.Errorf("nil callback bassed to addEventListener")
}
// Check event has been registered before
if e.listeners[eventName] == nil {
e.listeners[eventName] = []*eventListener{}
}
// Create the callback
listener := &eventListener{
callback: callback,
counter: counter,
}
e.mu.Lock()
// Check event has been registered before
if e.listeners[eventName] == nil {
e.listeners[eventName] = []*eventListener{}
}
// Register listener
e.listeners[eventName] = append(e.listeners[eventName], listener)
e.mu.Unlock()
// All good mate
return nil
}

BIN
sponsors/silver sponsor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -15,8 +15,6 @@ The build command processes the Wails project and generates an application binar
| -ldflags "custom ld flags" | Use given ldflags | |
| -o path/to/binary | Compile to given path/filename | |
| -k | Keep generated assets | |
| -package | Create a platform specific package | |
| -production | Compile in production mode: -ldflags="-w -s" + "-h windows" on Windows | |
| -tags | Build tags to pass to Go compiler (quoted and space separated) | |
| -upx | Compress final binary with UPX (if installed) | |
| -upxflags "custom flags" | Flags to pass to upx | |
@@ -36,13 +34,13 @@ The build process is as follows:
- The frontend is then built. This command is read from the project file `wails.json` under the key `frontend:install` and executed in the `frontend` directory. If this is not defined, it is ignored.
- The project directory is checked to see if the `build` directory exists. If not, it is created and default project assets are copied to it.
- An asset bundle is then created by reading the `html` key from `wails.json` and loading the referenced file. This is then parsed, looking for local Javascript and CSS references. Those files are in turn loaded into memory, converted to C data and saved into the asset bundle located at `build/assets.h`, which also includes the original HTML.
- The application icon is then processed: if there is no `build/appicon.png`, a default icon is copied. On Windows, an `app.ico` file is generated from this png. On Mac, `icons.icns` is generated.
- If there are icons in the `build/tray` directory, these are processed, converted to C data and saved as `build/trayicons.h`, ready for the compilation step.
- If there are icons in the `build/dialog` directory, these are processed, converted to C data and saved as `build/userdialogicons.h`, ready for the compilation step.
- If the `-package` flag is given for a Windows target, the Windows assets in the `build/windows` directory are processed: manifest + icons compiled to a `.syso` file (deleted after compilation).
- If we are building a universal binary for Mac, the application is compiled for both `arm64` and `amd64`. The `lipo` tool is then executed to create the universal binary.
- The application icon is then processed: if there is no `build/appicon.png`, a default icon is copied. On Windows,
an `app.ico` file is generated from this png. On Mac, `icons.icns` is generated.
- The platform assets in the `build/<platform>` directory are processed: manifest + icons compiled to a `.syso` file (
deleted after compilation), `info.plist` copied to `.app` on Mac.
- If we are building a universal binary for Mac, the application is compiled for both `arm64` and `amd64`. The `lipo`
tool is then executed to create the universal binary.
- If we are not building a universal binary for Mac, the application is built using `go build`, using build tags to indicate type of application and build mode (debug/production).
- If the `-upx` flag was provided, `upx` is invoked to compress the binary. Custom flags may be provided using the `-upxflags` flag.
- If the `package` flag is given for a non Windows target, the application is bundled for the platform. On Mac, this creates a `.app` with the processed icons, the `Info.plist` in `build/darwin` and the compiled binary.

View File

@@ -2,6 +2,7 @@ package build
import (
"fmt"
"github.com/wailsapp/wails/v2/internal/colour"
"io"
"os"
"os/exec"
@@ -38,6 +39,9 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
compilerCommand := "go"
command.StringFlag("compiler", "Use a different go compiler to build, eg go1.15beta1", &compilerCommand)
skipModTidy := false
command.BoolFlag("m", "Skip mod tidy before compile", &skipModTidy)
compress := false
command.BoolFlag("upx", "Compress final binary with UPX (if installed)", &compress)
@@ -76,6 +80,12 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
forceBuild := false
command.BoolFlag("f", "Force build application", &forceBuild)
updateGoMod := false
command.BoolFlag("u", "Updates go.mod to use the same Wails version as the CLI", &updateGoMod)
debug := false
command.BoolFlag("debug", "Retains debug data in the compiled application", &debug)
command.Action(func() error {
quiet := verbosity == 0
@@ -99,11 +109,12 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
"darwin/amd64",
"darwin/arm64",
"darwin/universal",
//"linux",
"linux",
//"linux/amd64",
//"linux/arm-7",
"windows",
"windows/amd64",
"windows/arm64",
})
if !validPlatformArch.Contains(platform) {
return fmt.Errorf("platform %s is not supported. Platforms supported: %s", platform, validPlatformArch.Join(","))
@@ -156,16 +167,24 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
}
}
mode := build.Production
modeString := "Production"
if debug {
mode = build.Debug
modeString = "Debug"
}
// Create BuildOptions
buildOptions := &build.Options{
Logger: logger,
OutputType: outputType,
OutputFile: outputFilename,
CleanBuildDirectory: cleanBuildDirectory,
Mode: build.Production,
Mode: mode,
Pack: !noPackage,
LDFlags: ldflags,
Compiler: compilerCommand,
SkipModTidy: skipModTidy,
Verbosity: verbosity,
ForceBuild: forceBuild,
IgnoreFrontend: skipFrontend,
@@ -197,6 +216,7 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
fmt.Fprintf(w, "Platform: \t%s\n", buildOptions.Platform)
fmt.Fprintf(w, "Arch: \t%s\n", buildOptions.Arch)
fmt.Fprintf(w, "Compiler: \t%s\n", compilerPath)
fmt.Fprintf(w, "Build Mode: \t%s\n", modeString)
fmt.Fprintf(w, "Skip Frontend: \t%t\n", skipFrontend)
fmt.Fprintf(w, "Compress: \t%t\n", buildOptions.Compress)
fmt.Fprintf(w, "Package: \t%t\n", buildOptions.Pack)
@@ -209,7 +229,7 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
fmt.Fprintf(w, "\n")
w.Flush()
err = checkGoModVersion(logger)
err = checkGoModVersion(logger, updateGoMod)
if err != nil {
return err
}
@@ -238,7 +258,7 @@ func doBuild(buildOptions *build.Options) error {
return nil
}
func checkGoModVersion(logger *clilogger.CLILogger) error {
func checkGoModVersion(logger *clilogger.CLILogger, updateGoMod bool) error {
cwd, err := os.Getwd()
if err != nil {
return err
@@ -260,6 +280,36 @@ func checkGoModVersion(logger *clilogger.CLILogger) error {
return err
}
logger.Println("Warning: go.mod is using Wails '%s' but the CLI is '%s'. Consider updating it.\n", gomodversion.String(), internal.Version)
if updateGoMod {
return syncGoModVersion(cwd)
}
logger.Println("Warning: go.mod is using Wails '%s' but the CLI is '%s'. Consider updating your project's `go.mod` file.\n", gomodversion.String(), internal.Version)
return nil
}
func LogGreen(message string, args ...interface{}) {
text := fmt.Sprintf(message, args...)
println(colour.Green(text))
}
func syncGoModVersion(cwd string) error {
gomodFilename := filepath.Join(cwd, "go.mod")
gomodData, err := os.ReadFile(gomodFilename)
if err != nil {
return err
}
outOfSync, err := gomod.GoModOutOfSync(gomodData, internal.Version)
if err != nil {
return err
}
if !outOfSync {
return nil
}
LogGreen("Updating go.mod to use Wails '%s'", internal.Version)
newGoData, err := gomod.UpdateGoModVersion(gomodData, internal.Version)
if err != nil {
return err
}
return os.WriteFile(gomodFilename, newGoData, 0755)
}

View File

@@ -63,6 +63,7 @@ type devFlags struct {
compilerCommand string
assetDir string
extensions string
reloadDirs string
openBrowser bool
noReload bool
wailsjsdir string
@@ -83,8 +84,9 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
flags := defaultDevFlags()
command.StringFlag("ldflags", "optional ldflags", &flags.ldflags)
command.StringFlag("compiler", "Use a different go compiler to build, eg go1.15beta1", &flags.compilerCommand)
command.StringFlag("assetdir", "Serve assets from the given directory", &flags.assetDir)
command.StringFlag("assetdir", "Serve assets from the given directory instead of using the provided asset FS", &flags.assetDir)
command.StringFlag("e", "Extensions to trigger rebuilds (comma separated) eg go", &flags.extensions)
command.StringFlag("reloaddirs", "Additional directories to trigger reloads (comma separated)", &flags.reloadDirs)
command.BoolFlag("browser", "Open application in browser", &flags.openBrowser)
command.BoolFlag("noreload", "Disable reload on asset change", &flags.noReload)
command.StringFlag("wailsjsdir", "Directory to generate the Wails JS modules", &flags.wailsjsdir)
@@ -278,7 +280,7 @@ func generateBuildOptions(flags devFlags) *build.Options {
OutputType: "dev",
Mode: build.Dev,
Arch: runtime.GOARCH,
Pack: false,
Pack: true,
Platform: runtime.GOOS,
LDFlags: flags.ldflags,
Compiler: flags.compilerCommand,
@@ -287,10 +289,7 @@ func generateBuildOptions(flags devFlags) *build.Options {
Verbosity: flags.verbosity,
WailsJSDir: flags.wailsjsdir,
}
switch runtime.GOOS {
case "darwin":
result.Pack = false
}
return result
}
@@ -304,21 +303,29 @@ func loadAndMergeProjectConfig(cwd string, flags *devFlags) (*project.Project, e
var shouldSaveConfig bool
if projectConfig.AssetDirectory == "" && flags.assetDir == "" {
return nil, fmt.Errorf("No asset directory provided. Please use -assetdir to indicate which directory contains your built assets.")
}
if flags.assetDir == "" && projectConfig.AssetDirectory != "" {
flags.assetDir = projectConfig.AssetDirectory
}
if flags.assetDir != projectConfig.AssetDirectory {
projectConfig.AssetDirectory = filepath.ToSlash(flags.assetDir)
shouldSaveConfig = true
}
flags.assetDir, err = filepath.Abs(flags.assetDir)
if err != nil {
return nil, err
if flags.assetDir != "" {
flags.assetDir, err = filepath.Abs(flags.assetDir)
if err != nil {
return nil, err
}
}
if flags.reloadDirs == "" && projectConfig.ReloadDirectories != "" {
flags.reloadDirs = projectConfig.ReloadDirectories
}
if flags.reloadDirs != projectConfig.ReloadDirectories {
projectConfig.ReloadDirectories = filepath.ToSlash(flags.reloadDirs)
shouldSaveConfig = true
}
if flags.devServerURL == defaultDevServerURL && projectConfig.DevServerURL != defaultDevServerURL && projectConfig.DevServerURL != "" {
@@ -506,11 +513,26 @@ func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Proc
newBinaryProcess *process.Process
)
var extensionsThatTriggerARebuild = sliceToMap(strings.Split(flags.extensions, ","))
var dirsThatTriggerAReload []string
for _, dir := range strings.Split(flags.reloadDirs, ",") {
if dir == "" {
continue
}
path, err := filepath.Abs(dir)
if err != nil {
LogRed("Unable to expand reloadDir '%s': %s", dir, err)
continue
}
dirsThatTriggerAReload = append(dirsThatTriggerAReload, path)
}
quit := false
interval := time.Duration(flags.debounceMS) * time.Millisecond
timer := time.NewTimer(interval)
rebuild := false
reload := false
assetDir := ""
changedPaths := map[string]struct{}{}
for quit == false {
//reload := false
select {
@@ -522,12 +544,13 @@ func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Proc
// Check for file writes
if item.Op&fsnotify.Write == fsnotify.Write {
// Ignore directories
if fs.DirExists(item.Name) {
itemName := item.Name
if fs.DirExists(itemName) {
continue
}
// Iterate all file patterns
ext := filepath.Ext(item.Name)
ext := filepath.Ext(itemName)
if ext != "" {
ext = ext[1:]
if _, exists := extensionsThatTriggerARebuild[ext]; exists {
@@ -537,9 +560,17 @@ func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Proc
}
}
if strings.HasPrefix(item.Name, flags.assetDir) {
reload = true
for _, reloadDir := range dirsThatTriggerAReload {
if strings.HasPrefix(itemName, reloadDir) {
reload = true
break
}
}
if !reload {
changedPaths[filepath.Dir(itemName)] = struct{}{}
}
timer.Reset(interval)
}
// Check for new directories
@@ -571,6 +602,35 @@ func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Proc
debugBinaryProcess = newBinaryProcess
}
}
if len(changedPaths) != 0 {
if assetDir == "" {
resp, err := http.Get("http://localhost:34115/wails/assetdir")
if err != nil {
LogRed("Error during retrieving assetdir: %s", err.Error())
} else {
content, err := io.ReadAll(resp.Body)
if err != nil {
LogRed("Error reading assetdir from devserver: %s", err.Error())
} else {
assetDir = string(content)
}
resp.Body.Close()
}
}
if assetDir != "" {
for path := range changedPaths {
if strings.HasPrefix(path, assetDir) {
reload = true
break
}
}
} else if len(dirsThatTriggerAReload) == 0 {
LogRed("Reloading couldn't be triggered: Please specify -assetdir or -reloaddirs")
}
changedPaths = map[string]struct{}{}
}
if reload {
reload = false
_, err = http.Get("http://localhost:34115/wails/reload")

View File

@@ -1,9 +1,8 @@
package generate
import (
"io"
"github.com/wailsapp/wails/v2/cmd/wails/internal/commands/generate/template"
"io"
"github.com/leaanthony/clir"
)
@@ -17,6 +16,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
if err != nil {
return err
}
template.AddSubCommand(app, command, w)
return nil

View File

@@ -10,7 +10,6 @@ The next steps to complete the template are:
- It is really important to ensure `helpurl` is valid as this is where users of the template will be directed for help.
2. Update `README.md`.
3. Edit `wails.json` and ensure all fields are correct, especially:
- `assetdir` - path to your assets
- `wailsjsdir` - path to generate wailsjs modules
- `frontend:install` - The command to install your frontend dependencies
- `frontend:build` - The command to build your frontend

View File

@@ -4,13 +4,12 @@
About your template
## Building
To build this project in debug mode, use `wails build`. For production, use `wails build -production`.
To generate a platform native package, add the `-package` flag.
## Live Development
To run in live development mode, run `wails dev` in the project directory. In another terminal, go into the `frontend`
directory and run `npm run dev`. The frontend dev server will run on http://localhost:34115. Connect to this
in your browser and connect to your application.
To run in live development mode, run `wails dev` in the project directory. In another terminal, go into the `frontend`
directory and run `npm run dev`. The frontend dev server will run on http://localhost:34115. Connect to this in your
browser and connect to your application.
## Building
To build a redistributable, production mode package, use `wails build`.

View File

@@ -22,7 +22,6 @@ github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
github.com/leaanthony/go-webview2 v0.0.0-20210914103035-f00aa774a934 // indirect
github.com/leaanthony/slicer v1.5.0 // indirect
github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
github.com/leaanthony/webview2runtime v1.1.0 // indirect
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
github.com/pkg/errors v0.9.1 // indirect

View File

@@ -90,8 +90,6 @@ github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0H
github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
github.com/leaanthony/typescriptify-golang-structs v0.1.7 h1:yoznzWzyxkO/iWdlpq+aPcuJ5Y/hpjq/lmgMFmpjwl0=
github.com/leaanthony/typescriptify-golang-structs v0.1.7/go.mod h1:cWtOkiVhMF77e6phAXUcfNwYmMwCJ67Sij24lfvi9Js=
github.com/leaanthony/webview2runtime v1.1.0 h1:N0pv55ift8XtqozIp4PNOtRCJ/Qdd/qzx80lUpalS4c=
github.com/leaanthony/webview2runtime v1.1.0/go.mod h1:hH9GnWCve3DYzNaPOcPbhHQ7fodXR1QJNsnwixid4Tk=
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 h1:5iOd93PZbpH4Iir8QkC4coFD+zEQEZSIRcjwjTFZkr0=
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18/go.mod h1:KEbMsKoznsebyGHwLk5LqkFOxL5uXSRdvpP4+avmAMs=
github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU=

View File

@@ -33,10 +33,10 @@ func main() {
HideWindowOnClose: false,
RGBA: &options.RGBA{255, 255, 255, 255},
Assets: assets,
LogLevel: logger.DEBUG,
OnStartup: app.startup,
OnDomReady: app.domReady,
OnShutdown: app.shutdown,
LogLevel: logger.DEBUG,
OnStartup: app.startup,
OnDomReady: app.domReady,
OnShutdown: app.shutdown,
Bind: []interface{}{
app,
},

View File

@@ -0,0 +1,16 @@
{
"name": "{{.ProjectName}}",
"author": "",
"private": true,
"scripts": {
"install": "go install github.com/wailsapp/wails/v2/cmd/wails@latest",
"build": "wails build --clean",
"build:macos": "npm run build -- --platform darwin/universal",
"build:macos-arm": "npm run build -- --platform darwin/arm64",
"build:macos-intel": "npm run build -- --platform darwin",
"build:windows": "npm run build -- --platform windows/amd64"
},
"workspaces": [
"frontend"
]
}

View File

@@ -1,7 +1,6 @@
{
"name": "{{.ProjectName}}",
"outputfilename": "{{.BinaryName}}",
"assetdir": "frontend/dist",
"frontend:install": "npm install",
"frontend:build": "npm run build",
"author": {

View File

@@ -158,18 +158,17 @@ func processPackageJSON(frontendDir string) error {
return nil
}
data, err := os.ReadFile(packageJSON)
json, err := os.ReadFile(packageJSON)
if err != nil {
return err
}
json := string(data)
// We will ignore these errors - it's not critical
println("Updating package.json data...")
json, _ = sjson.Set(json, "name", "{{.ProjectName}}")
json, _ = sjson.Set(json, "author", "{{.AuthorName}}")
json, _ = sjson.SetBytes(json, "name", "{{.ProjectName}}")
json, _ = sjson.SetBytes(json, "author", "{{.AuthorName}}")
err = os.WriteFile(packageJSON, []byte(json), 0644)
err = os.WriteFile(packageJSON, json, 0644)
if err != nil {
return err
}

View File

@@ -36,7 +36,6 @@
<working_directory value="$PROJECT_DIR$"/>
<go_parameters value="-gcflags &quot;all=-N -l&quot; -tags dev -o {{.PathToDesktopBinary}}"/>
<useCustomBuildTags value="true"/>
<parameters value="-assetdir {{.AssetDir}}"/>
<envs>
<env name="CGO_ENABLED" value="&quot;{{.CGOEnabled}}&quot;"/>
</envs>

View File

@@ -9,11 +9,7 @@
"program": "${workspaceFolder}/{{.PathToDesktopBinary}}",
"preLaunchTask": "build",
"cwd": "${workspaceFolder}",
"env": {},
"args": [
"-assetdir",
"{{.AssetDir}}"
]
"env": {}
}
]
}

View File

@@ -4,15 +4,14 @@ import (
"embed"
"encoding/json"
"fmt"
"github.com/go-git/go-git/v5"
gofs "io/fs"
"io/ioutil"
"log"
"os"
"path/filepath"
"runtime"
"strings"
"github.com/go-git/go-git/v5"
"github.com/pkg/errors"
"github.com/leaanthony/debme"
@@ -43,7 +42,6 @@ type Data struct {
AuthorNameAndEmail string
WailsDirectory string
GoSDKPath string
AssetDir string
WindowsFlags string
CGOEnabled string
OutputFile string
@@ -61,7 +59,6 @@ type Options struct {
InitGit bool
AuthorName string
AuthorEmail string
AssetDir string
IDE string
ProjectNameFilename string // The project name but as a valid filename
WailsVersion string
@@ -262,7 +259,6 @@ func Install(options *Options) (bool, *Template, error) {
AuthorName: options.AuthorName,
WailsVersion: options.WailsVersion,
GoSDKPath: options.GoSDKPath,
AssetDir: options.AssetDir,
}
// Create a formatted name and email combo.
@@ -295,7 +291,7 @@ func Install(options *Options) (bool, *Template, error) {
// Clones the given uri and returns the temporary cloned directory
func gitclone(options *Options) (string, error) {
// Create temporary directory
dirname, err := ioutil.TempDir("", "wails-template-*")
dirname, err := os.MkdirTemp("", "wails-template-*")
if err != nil {
return "", err
}
@@ -409,22 +405,6 @@ func installIDEFiles(o ideOptions) error {
binaryName += ".exe"
}
// Parse wails.json for assetdir
wailsJSONBytes, err := os.ReadFile(filepath.Join(o.options.TargetDir, "wails.json"))
if err != nil {
return err
}
var wailsJSON map[string]interface{}
err = json.Unmarshal(wailsJSONBytes, &wailsJSON)
if err != nil {
return err
}
assetDir := wailsJSON["assetdir"]
if assetDir == "" {
return fmt.Errorf("Unable to find 'assetdir' in 'wails.json' ")
}
o.options.AssetDir = assetDir.(string)
o.options.PathToDesktopBinary = filepath.ToSlash(filepath.Join("build", "bin", binaryName))
o.options.WindowsFlags = ""

View File

@@ -22,7 +22,6 @@ github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
github.com/leaanthony/go-webview2 v0.0.0-20210914103035-f00aa774a934 // indirect
github.com/leaanthony/slicer v1.5.0 // indirect
github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
github.com/leaanthony/webview2runtime v1.1.0 // indirect
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
github.com/pkg/errors v0.9.1 // indirect

View File

@@ -91,8 +91,6 @@ github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0H
github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
github.com/leaanthony/typescriptify-golang-structs v0.1.7 h1:yoznzWzyxkO/iWdlpq+aPcuJ5Y/hpjq/lmgMFmpjwl0=
github.com/leaanthony/typescriptify-golang-structs v0.1.7/go.mod h1:cWtOkiVhMF77e6phAXUcfNwYmMwCJ67Sij24lfvi9Js=
github.com/leaanthony/webview2runtime v1.1.0 h1:N0pv55ift8XtqozIp4PNOtRCJ/Qdd/qzx80lUpalS4c=
github.com/leaanthony/webview2runtime v1.1.0/go.mod h1:hH9GnWCve3DYzNaPOcPbhHQ7fodXR1QJNsnwixid4Tk=
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 h1:5iOd93PZbpH4Iir8QkC4coFD+zEQEZSIRcjwjTFZkr0=
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18/go.mod h1:KEbMsKoznsebyGHwLk5LqkFOxL5uXSRdvpP4+avmAMs=
github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU=

View File

@@ -1,9 +1,9 @@
{
"name": "{{.ProjectName}}",
"outputfilename": "{{.BinaryName}}",
"assetdir": "frontend/dist",
"frontend:install": "npm install",
"frontend:build": "npm run build",
"wailsjsdir": "./frontend",
"author": {
"name": "{{.AuthorName}}",
"email": "{{.AuthorEmail}}"

View File

@@ -22,7 +22,6 @@ github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
github.com/leaanthony/go-webview2 v0.0.0-20210914103035-f00aa774a934 // indirect
github.com/leaanthony/slicer v1.5.0 // indirect
github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
github.com/leaanthony/webview2runtime v1.1.0 // indirect
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
github.com/pkg/errors v0.9.1 // indirect

View File

@@ -91,8 +91,6 @@ github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0H
github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
github.com/leaanthony/typescriptify-golang-structs v0.1.7 h1:yoznzWzyxkO/iWdlpq+aPcuJ5Y/hpjq/lmgMFmpjwl0=
github.com/leaanthony/typescriptify-golang-structs v0.1.7/go.mod h1:cWtOkiVhMF77e6phAXUcfNwYmMwCJ67Sij24lfvi9Js=
github.com/leaanthony/webview2runtime v1.1.0 h1:N0pv55ift8XtqozIp4PNOtRCJ/Qdd/qzx80lUpalS4c=
github.com/leaanthony/webview2runtime v1.1.0/go.mod h1:hH9GnWCve3DYzNaPOcPbhHQ7fodXR1QJNsnwixid4Tk=
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 h1:5iOd93PZbpH4Iir8QkC4coFD+zEQEZSIRcjwjTFZkr0=
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18/go.mod h1:KEbMsKoznsebyGHwLk5LqkFOxL5uXSRdvpP4+avmAMs=
github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU=

View File

@@ -1,7 +1,7 @@
{
"name": "{{.ProjectName}}",
"outputfilename": "{{.BinaryName}}",
"assetdir": "frontend/src",
"wailsjsdir": "./frontend",
"author": {
"name": "{{.AuthorName}}",
"email": "{{.AuthorEmail}}"

View File

@@ -1,3 +1,3 @@
package internal
var Version = "v2.0.0-beta.19"
var Version = "v2.0.0-beta.27"

View File

@@ -22,13 +22,12 @@ require (
github.com/leaanthony/debme v1.2.1
github.com/leaanthony/go-ansi-parser v1.0.1
github.com/leaanthony/go-common-file-dialog v1.0.3
github.com/leaanthony/go-webview2 v0.0.0-20211022194343-1e4c8d4226f3
github.com/leaanthony/go-webview2 v1.0.2
github.com/leaanthony/gosod v1.0.3
github.com/leaanthony/idgen v1.0.0
github.com/leaanthony/slicer v1.5.0
github.com/leaanthony/typescriptify-golang-structs v0.1.7
github.com/leaanthony/webview2runtime v1.1.0
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18
github.com/leaanthony/winc v0.0.0-20211202091710-9931d43181ff
github.com/leaanthony/winicon v1.0.0
github.com/matryer/is v1.4.0
github.com/olekukonko/tablewriter v0.0.4
@@ -40,11 +39,10 @@ require (
github.com/tdewolff/test v1.0.6 // indirect
github.com/tidwall/sjson v1.1.7
github.com/wzshiming/ctc v1.2.3
github.com/xyproto/xpm v1.2.1
github.com/ztrue/tracerr v0.3.0
golang.org/x/mod v0.4.1
golang.org/x/net v0.0.0-20210510120150-4163338589ed
golang.org/x/sys v0.0.0-20211020174200-9d6173849985
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e
golang.org/x/tools v0.1.0
nhooyr.io/websocket v1.8.6
)
@@ -55,7 +53,7 @@ require (
github.com/emirpasic/gods v1.12.0 // indirect
github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab // indirect
github.com/go-git/gcfg v1.5.0 // indirect
github.com/go-ole/go-ole v1.2.5 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/google/go-cmp v0.5.5 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect

View File

@@ -45,8 +45,8 @@ github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod
github.com/go-git/go-git/v5 v5.3.0 h1:8WKMtJR2j8RntEXR/uvTKagfEt4GYlwQ7mntE4+0GWc=
github.com/go-git/go-git/v5 v5.3.0/go.mod h1:xdX4bWJ48aOrdhnl2XqHYstHbbp6+LFS4r4X+lNVprw=
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
@@ -118,8 +118,8 @@ github.com/leaanthony/go-ansi-parser v1.0.1 h1:97v6c5kYppVsbScf4r/VZdXyQ21KQIfeQ
github.com/leaanthony/go-ansi-parser v1.0.1/go.mod h1:7arTzgVI47srICYhvgUV4CGd063sGEeoSlych5yeSPM=
github.com/leaanthony/go-common-file-dialog v1.0.3 h1:O0uGjKnWtdEADGrkg+TyAAbZylykMwwx/MNEXn9fp+Y=
github.com/leaanthony/go-common-file-dialog v1.0.3/go.mod h1:TGhEc9eSJgRsupZ+iH1ZgAOnEo9zp05cRH2j08RPrF0=
github.com/leaanthony/go-webview2 v0.0.0-20211022194343-1e4c8d4226f3 h1:qhgrg3MhFRAIvtaqoqI+SrT+0wDYpxDMp9e3cvcxMpI=
github.com/leaanthony/go-webview2 v0.0.0-20211022194343-1e4c8d4226f3/go.mod h1:lS5ds4bruPk9d7lzdF/OH31Z0YCerI6MmHNFGsWoUnM=
github.com/leaanthony/go-webview2 v1.0.2 h1:IjTbpAXUig33G3LUqf+8EClZutg2Z/C1cbxqhHKPxbU=
github.com/leaanthony/go-webview2 v1.0.2/go.mod h1:iX54IaVk1FnDqMuHJ47VYLPQOcVqQiOe9SJACt9CAbU=
github.com/leaanthony/gosod v1.0.3 h1:Fnt+/B6NjQOVuCWOKYRREZnjGyvg+mEhd1nkkA04aTQ=
github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4=
github.com/leaanthony/idgen v1.0.0 h1:IZreR+JGEzFV4yeVuBZA25gM0keUoFy+RDUldncQ+Jw=
@@ -128,10 +128,8 @@ github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0H
github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
github.com/leaanthony/typescriptify-golang-structs v0.1.7 h1:yoznzWzyxkO/iWdlpq+aPcuJ5Y/hpjq/lmgMFmpjwl0=
github.com/leaanthony/typescriptify-golang-structs v0.1.7/go.mod h1:cWtOkiVhMF77e6phAXUcfNwYmMwCJ67Sij24lfvi9Js=
github.com/leaanthony/webview2runtime v1.1.0 h1:N0pv55ift8XtqozIp4PNOtRCJ/Qdd/qzx80lUpalS4c=
github.com/leaanthony/webview2runtime v1.1.0/go.mod h1:hH9GnWCve3DYzNaPOcPbhHQ7fodXR1QJNsnwixid4Tk=
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 h1:5iOd93PZbpH4Iir8QkC4coFD+zEQEZSIRcjwjTFZkr0=
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18/go.mod h1:KEbMsKoznsebyGHwLk5LqkFOxL5uXSRdvpP4+avmAMs=
github.com/leaanthony/winc v0.0.0-20211202091710-9931d43181ff h1:FwGObElCr/T/xy8S9IKDjWsNcfJHGxgjRl/GIbcseoQ=
github.com/leaanthony/winc v0.0.0-20211202091710-9931d43181ff/go.mod h1:KEbMsKoznsebyGHwLk5LqkFOxL5uXSRdvpP4+avmAMs=
github.com/leaanthony/winicon v1.0.0 h1:ZNt5U5dY71oEoKZ97UVwJRT4e+5xo5o/ieKuHuk8NqQ=
github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
@@ -213,8 +211,6 @@ github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae h1:tpXvBXC3hpQBDC
github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae/go.mod h1:VTAq37rkGeV+WOybvZwjXiJOicICdpLCN8ifpISjK20=
github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI=
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
github.com/xyproto/xpm v1.2.1 h1:trdvGjjWBsOOKzBBUPT6JvaIQM3acJEEYfbxN7M96wg=
github.com/xyproto/xpm v1.2.1/go.mod h1:cMnesLsD0PBXLgjDfTDEaKr8XyTFsnP1QycSqRw7BiY=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/ztrue/tracerr v0.3.0 h1:lDi6EgEYhPYPnKcjsYzmWw4EkFEoA/gfe+I9Y5f+h6Y=
github.com/ztrue/tracerr v0.3.0/go.mod h1:qEalzze4VN9O8tnhBXScfCrmoJo10o8TN5ciKjm6Mww=
@@ -252,18 +248,17 @@ golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210218145245-beda7e5e158e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210611083646-a4fc73990273/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211020174200-9d6173849985 h1:LOlKVhfDyahgmqa97awczplwkjzNaELFg3zRIJ13RYo=
golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@@ -1,3 +1,4 @@
//go:build !windows
// +build !windows
package wails

View File

@@ -1,3 +1,4 @@
//go:build !desktop && !hybrid && !server && !dev
// +build !desktop,!hybrid,!server,!dev
package app

View File

@@ -1,3 +1,4 @@
//go:build !server && !desktop && hybrid
// +build !server,!desktop,hybrid
package app

View File

@@ -1,4 +1,5 @@
//+build !windows
//go:build !windows
// +build !windows
package app

View File

@@ -1,4 +1,5 @@
//+build windows
//go:build windows
// +build windows
package app

View File

@@ -61,6 +61,9 @@ func generateBindings(bindings *binding.Bindings) error {
return err
}
if projectConfig.WailsJSDir == "" {
projectConfig.WailsJSDir = filepath.Join(cwd, "frontend")
}
wrapperDir := filepath.Join(projectConfig.WailsJSDir, "wailsjs", "runtime")
_ = os.RemoveAll(wrapperDir)
extractor := gosod.New(wrapper.RuntimeWrapper)
@@ -100,6 +103,12 @@ func generateBindings(bindings *binding.Bindings) error {
return err
}
bindingsTypes := filepath.Join(targetDir, "bindings.d.ts")
err = bindings.GenerateBackendTS(bindingsTypes)
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,32 @@
//go:build !dev && !production && !bindings && linux
package appng
import (
"fmt"
"github.com/wailsapp/wails/v2/pkg/options"
)
// App defines a Wails application structure
type App struct{}
func (a *App) Run() error {
return nil
}
// CreateApp creates the app!
func CreateApp(_ *options.App) (*App, error) {
// result := w32.MessageBox(0,
// `Wails applications will not build without the correct build tags.
//Please use "wails build" or press "OK" to open the documentation on how to use "go build"`,
// "Error",
// w32.MB_ICONERROR|w32.MB_OKCANCEL)
// if result == 1 {
// exec.Command("rundll32", "url.dll,FileProtocolHandler", "https://wails.io").Start()
// }
err := fmt.Errorf(`Wails applications will not build without the correct build tags.`)
return nil, err
}

View File

@@ -5,6 +5,10 @@ package appng
import (
"context"
"embed"
"flag"
"fmt"
iofs "io/fs"
"os"
"path/filepath"
@@ -58,17 +62,62 @@ func CreateApp(appoptions *options.App) (*App, error) {
myLogger.SetLogLevel(appoptions.LogLevel)
// Check for CLI Flags
var assetdirFlag *string
var devServerURLFlag *string
var loglevelFlag *string
assetdir := os.Getenv("assetdir")
if assetdir == "" {
assetdirFlag = flag.String("assetdir", "", "Directory to serve assets")
}
devServerURL := os.Getenv("devserverurl")
if devServerURL == "" {
devServerURLFlag = flag.String("devserverurl", "", "URL of development server")
}
loglevel := os.Getenv("loglevel")
if loglevel == "" {
loglevelFlag = flag.String("loglevel", "debug", "Loglevel to use - Trace, Debug, Info, Warning, Error")
}
// If we weren't given the assetdir in the environment variables
if assetdir == "" {
flag.Parse()
if assetdirFlag != nil {
assetdir = *assetdirFlag
}
if devServerURLFlag != nil {
devServerURL = *devServerURLFlag
}
if loglevelFlag != nil {
loglevel = *loglevelFlag
}
}
if assetdir == "" {
// If no assetdir has been defined, let's try to infer it from the project root and the asset FS.
assetdir, err = tryInferAssetDirFromFS(appoptions.Assets)
if err != nil {
return nil, err
}
}
if assetdir != "" {
// Let's override the assets to serve from on disk, if needed
absdir, err := filepath.Abs(assetdir)
if err != nil {
return nil, err
}
myLogger.Info("Serving assets from disk: %s", absdir)
appoptions.Assets = os.DirFS(absdir)
ctx = context.WithValue(ctx, "assetdir", assetdir)
}
if devServerURL != "" {
ctx = context.WithValue(ctx, "devserverurl", devServerURL)
}
if assetdir != "" {
ctx = context.WithValue(ctx, "assetdir", assetdir)
}
if loglevel != "" {
level, err := pkglogger.StringToLogLevel(loglevel)
@@ -165,6 +214,42 @@ func generateBindings(bindings *binding.Bindings) error {
if err != nil {
return err
}
bindingsTypes := filepath.Join(targetDir, "bindings.d.ts")
err = bindings.GenerateBackendTS(bindingsTypes)
if err != nil {
return err
}
return nil
}
func tryInferAssetDirFromFS(assets iofs.FS) (string, error) {
if _, isEmbedFs := assets.(embed.FS); !isEmbedFs {
// We only infer the assetdir for embed.FS assets
return "", nil
}
path, err := fs.FindPathToFile(assets, "index.html")
if err != nil {
return "", err
}
path, err = filepath.Abs(path)
if err != nil {
return "", err
}
if _, err := os.Stat(filepath.Join(path, "index.html")); err != nil {
if os.IsNotExist(err) {
err = fmt.Errorf(
"inferred assetdir '%s' does not exist or does not contain an 'index.html' file, "+
"please specify it with -assetdir or set it in wails.json",
path)
}
return "", err
}
return path, nil
}

View File

@@ -0,0 +1,15 @@
//go:build linux && !bindings
package appng
import (
"github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/pkg/options"
)
func PreflightChecks(options *options.App, logger *logger.Logger) error {
_ = options
return nil
}

View File

@@ -35,6 +35,9 @@ type App struct {
func (a *App) Run() error {
err := a.frontend.Run(a.ctx)
if a.shutdownCallback != nil {
a.shutdownCallback(a.ctx)
}
return err
}
@@ -78,6 +81,9 @@ func CreateApp(appoptions *options.App) (*App, error) {
appFrontend := desktop.NewFrontend(ctx, appoptions, myLogger, appBindings, messageDispatcher)
eventHandler.AddFrontend(appFrontend)
// Attach logger to context
ctx = context.WithValue(ctx, "logger", myLogger)
result := &App{
ctx: ctx,
frontend: appFrontend,

View File

@@ -15,9 +15,9 @@ func PreflightChecks(options *options.App, logger *logger.Logger) error {
// Process the webview2 runtime situation. We can pass a strategy in via the `webview2` flag for `wails build`.
// This will determine how wv2runtime.Process will handle a lack of valid runtime.
installedVersion, err := wv2runtime.Process()
if installedVersion != nil {
logger.Debug("WebView2 Runtime installed: Name: '%s' Version:'%s' Location:'%s'. Minimum version required: %s.",
installedVersion.Name, installedVersion.Version, installedVersion.Location, wv2runtime.MinimumRuntimeVersion)
if installedVersion != "" {
logger.Debug("WebView2 Runtime Version '%s' installed. Minimum version required: %s.",
installedVersion, wv2runtime.MinimumRuntimeVersion)
}
if err != nil {
return err

View File

@@ -1,4 +1,6 @@
//go:build !desktop
// +build !desktop
package assetdb
import (

View File

@@ -122,6 +122,83 @@ export default go;`)
return os.WriteFile(targetfile, output.Bytes(), 0755)
}
// GenerateBackendTS generates typescript bindings for
// the bound methods.
func (b *Bindings) GenerateBackendTS(targetfile string) error {
store := b.db.store
var output bytes.Buffer
output.WriteString("interface go {\n")
var sortedPackageNames slicer.StringSlicer
for packageName := range store {
sortedPackageNames.Add(packageName)
}
sortedPackageNames.Sort()
sortedPackageNames.Each(func(packageName string) {
packages := store[packageName]
output.WriteString(fmt.Sprintf(" \"%s\": {", packageName))
output.WriteString("\n")
var sortedStructNames slicer.StringSlicer
for structName := range packages {
sortedStructNames.Add(structName)
}
sortedStructNames.Sort()
sortedStructNames.Each(func(structName string) {
structs := packages[structName]
output.WriteString(fmt.Sprintf(" \"%s\": {", structName))
output.WriteString("\n")
var sortedMethodNames slicer.StringSlicer
for methodName := range structs {
sortedMethodNames.Add(methodName)
}
sortedMethodNames.Sort()
sortedMethodNames.Each(func(methodName string) {
methodDetails := structs[methodName]
output.WriteString(fmt.Sprintf("\t\t%s(", methodName))
var args slicer.StringSlicer
for count, input := range methodDetails.Inputs {
arg := fmt.Sprintf("arg%d", count+1)
args.Add(arg + ":" + goTypeToTypescriptType(input.TypeName))
}
output.WriteString(args.Join(",") + "):")
returnType := "Promise"
if methodDetails.OutputCount() > 0 {
firstType := goTypeToTypescriptType(methodDetails.Outputs[0].TypeName)
returnType += "<" + firstType
if methodDetails.OutputCount() == 2 {
secondType := goTypeToTypescriptType(methodDetails.Outputs[1].TypeName)
returnType += "|" + secondType
}
returnType += ">"
} else {
returnType = "Promise<void>"
}
output.WriteString(returnType + "\n")
})
output.WriteString(" },\n")
})
output.WriteString(" }\n\n")
})
output.WriteString("}\n")
globals := `
declare global {
interface Window {
go: go;
}
}
`
output.WriteString(globals)
return os.WriteFile(targetfile, output.Bytes(), 0755)
}
func goTypeToJSDocType(input string) string {
switch true {
case input == "string":
@@ -139,7 +216,7 @@ func goTypeToJSDocType(input string) string {
return "string"
case strings.HasPrefix(input, "[]"):
arrayType := goTypeToJSDocType(input[2:])
return "Array.<" + arrayType + ">"
return "Array<" + arrayType + ">"
default:
if strings.ContainsRune(input, '.') {
return strings.Split(input, ".")[1]
@@ -147,3 +224,11 @@ func goTypeToJSDocType(input string) string {
return "any"
}
}
func goTypeToTypescriptType(input string) string {
if strings.HasPrefix(input, "[]") {
arrayType := goTypeToJSDocType(input[2:])
return "Array<" + arrayType + ">"
}
return goTypeToJSDocType(input)
}

View File

@@ -78,10 +78,16 @@ func (b *Bindings) getMethods(value interface{}) ([]*BoundMethod, error) {
input := methodType.In(inputIndex)
thisParam := newParameter("", input)
thisInput := input
if thisInput.Kind() == reflect.Slice {
thisInput = thisInput.Elem()
}
// Process struct pointer params
if input.Kind() == reflect.Ptr {
if input.Elem().Kind() == reflect.Struct {
typ := input.Elem()
if thisInput.Kind() == reflect.Ptr {
if thisInput.Elem().Kind() == reflect.Struct {
typ := thisInput.Elem()
a := reflect.New(typ)
s := reflect.Indirect(a).Interface()
b.converter.Add(s)
@@ -89,8 +95,8 @@ func (b *Bindings) getMethods(value interface{}) ([]*BoundMethod, error) {
}
// Process struct params
if input.Kind() == reflect.Struct {
a := reflect.New(input)
if thisInput.Kind() == reflect.Struct {
a := reflect.New(thisInput)
s := reflect.Indirect(a).Interface()
b.converter.Add(s)
}
@@ -108,6 +114,30 @@ func (b *Bindings) getMethods(value interface{}) ([]*BoundMethod, error) {
for outputIndex := 0; outputIndex < outputParamCount; outputIndex++ {
output := methodType.Out(outputIndex)
thisParam := newParameter("", output)
thisOutput := output
if thisOutput.Kind() == reflect.Slice {
thisOutput = thisOutput.Elem()
}
// Process struct pointer params
if thisOutput.Kind() == reflect.Ptr {
if thisOutput.Elem().Kind() == reflect.Struct {
typ := thisOutput.Elem()
a := reflect.New(typ)
s := reflect.Indirect(a).Interface()
b.converter.Add(s)
}
}
// Process struct params
if thisOutput.Kind() == reflect.Struct {
a := reflect.New(thisOutput)
s := reflect.Indirect(a).Interface()
b.converter.Add(s)
}
outputs = append(outputs, thisParam)
}
boundMethod.Outputs = outputs

View File

@@ -1,3 +1,4 @@
//go:build !windows
// +build !windows
package ffenestri

View File

@@ -1,3 +1,4 @@
//go:build windows
// +build windows
package ffenestri

View File

@@ -1,10 +1,11 @@
//go:build wv2runtime.browser
// +build wv2runtime.browser
package wv2runtime
import (
"fmt"
"github.com/leaanthony/webview2runtime"
"github.com/wailsapp/wails/v2/internal/webview2runtime"
)
func doInstallationStrategy(installStatus installationStatus) error {

View File

@@ -1,12 +1,11 @@
// +build !wv2runtime.error
// +build !wv2runtime.browser
// +build !wv2runtime.embed
//go:build !wv2runtime.error && !wv2runtime.browser && !wv2runtime.embed
// +build !wv2runtime.error,!wv2runtime.browser,!wv2runtime.embed
package wv2runtime
import (
"fmt"
"github.com/leaanthony/webview2runtime"
"github.com/wailsapp/wails/v2/internal/webview2runtime"
)
func doInstallationStrategy(installStatus installationStatus) error {

View File

@@ -1,10 +1,11 @@
//go:build wv2runtime.embed
// +build wv2runtime.embed
package wv2runtime
import (
"fmt"
"github.com/leaanthony/webview2runtime"
"github.com/wailsapp/wails/v2/internal/webview2runtime"
)
func doInstallationStrategy(installStatus installationStatus) error {

View File

@@ -1,10 +1,11 @@
//go:build wv2runtime.error
// +build wv2runtime.error
package wv2runtime
import (
"fmt"
"github.com/leaanthony/webview2runtime"
"github.com/wailsapp/wails/v2/internal/webview2runtime"
)
func doInstallationStrategy(installStatus installationStatus) error {

View File

@@ -2,7 +2,6 @@ package wv2runtime
import (
"github.com/leaanthony/go-webview2/webviewloader"
"github.com/leaanthony/webview2runtime"
)
const MinimumRuntimeVersion string = "91.0.992.28"
@@ -15,14 +14,17 @@ const (
installed
)
func Process() (*webview2runtime.Info, error) {
func Process() (string, error) {
installStatus := needsInstalling
installedVersion := webview2runtime.GetInstalledVersion()
if installedVersion != nil {
installedVersion, err := webviewloader.GetInstalledVersion()
if err != nil {
return "", err
}
if installedVersion != "" {
installStatus = installed
compareResult, err := webviewloader.CompareBrowserVersions(installedVersion.Version, MinimumRuntimeVersion)
compareResult, err := webviewloader.CompareBrowserVersions(installedVersion, MinimumRuntimeVersion)
if err != nil {
return nil, err
return "", err
}
updateRequired := compareResult == -1
// Installed and does not require updating

View File

@@ -1,14 +1,16 @@
//+build windows
//go:build windows
// +build windows
package ffenestri
import (
"fmt"
"github.com/leaanthony/slicer"
"github.com/wailsapp/wails/v2/internal/menumanager"
"os"
"sync"
"text/tabwriter"
"github.com/leaanthony/slicer"
"github.com/wailsapp/wails/v2/internal/menumanager"
)
/* ---------------------------------------------------------------------------------

View File

@@ -1,4 +1,5 @@
//+build windows,debug
//go:build windows && debug
// +build windows,debug
package ffenestri

View File

@@ -1,3 +1,4 @@
//go:build windows && !debug
// +build windows,!debug
package ffenestri

View File

@@ -1,4 +1,5 @@
//+build windows
//go:build windows
// +build windows
package ffenestri

View File

@@ -1,4 +1,5 @@
//+build windows
//go:build windows
// +build windows
package ffenestri

View File

@@ -1,4 +1,5 @@
//+build windows
//go:build windows
// +build windows
package ffenestri

View File

@@ -1,4 +1,5 @@
//+build windows
//go:build windows
// +build windows
package ffenestri

View File

@@ -5,11 +5,13 @@ package assetserver
import (
"bytes"
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
"github.com/wailsapp/wails/v2/pkg/options"
"golang.org/x/net/html"
"path/filepath"
"context"
"io/fs"
"strings"
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
"github.com/wailsapp/wails/v2/internal/logger"
"golang.org/x/net/html"
)
/*
@@ -19,35 +21,41 @@ It injects a websocket based IPC script into `index.html`.
*/
import (
"os"
)
type BrowserAssetServer struct {
runtimeJS []byte
assetdir string
appOptions *options.App
assets fs.FS
runtimeJS []byte
logger *logger.Logger
}
func NewBrowserAssetServer(assetdir string, bindingsJSON string, appOptions *options.App) (*BrowserAssetServer, error) {
result := &BrowserAssetServer{
assetdir: assetdir,
appOptions: appOptions,
func NewBrowserAssetServer(ctx context.Context, assets fs.FS, bindingsJSON string) (*BrowserAssetServer, error) {
result := &BrowserAssetServer{}
_logger := ctx.Value("logger")
if _logger != nil {
result.logger = _logger.(*logger.Logger)
}
var err error
result.assets, err = prepareAssetsForServing(assets)
if err != nil {
return nil, err
}
var buffer bytes.Buffer
buffer.WriteString(`window.wailsbindings='` + bindingsJSON + `';` + "\n")
buffer.Write(runtime.RuntimeDesktopJS)
result.runtimeJS = buffer.Bytes()
return result, nil
}
func (a *BrowserAssetServer) loadFileFromDisk(filename string) ([]byte, error) {
return os.ReadFile(filepath.Join(a.assetdir, filename))
func (d *BrowserAssetServer) LogDebug(message string, args ...interface{}) {
if d.logger != nil {
d.logger.Debug("[BrowserAssetServer] "+message, args...)
}
}
func (a *BrowserAssetServer) processIndexHTML() ([]byte, error) {
indexHTML, err := a.loadFileFromDisk("index.html")
indexHTML, err := fs.ReadFile(a.assets, "index.html")
if err != nil {
return nil, err
}
@@ -97,15 +105,9 @@ func (a *BrowserAssetServer) Load(filename string) ([]byte, string, error) {
case "/wails/ipc.js":
content = runtime.WebsocketIPC
default:
content, err = a.loadFileFromDisk(filename)
if strings.HasSuffix(filename, ".js") {
var buffer bytes.Buffer
buffer.WriteString("window.awaitIPC('" + filename + "', ()=>{")
buffer.Write(content)
buffer.WriteString(`
});`)
content = buffer.Bytes()
}
filename = strings.TrimPrefix(filename, "/")
a.LogDebug("Loading file: %s", filename)
content, err = fs.ReadFile(a.assets, filename)
}
if err != nil {
return nil, "", err

View File

@@ -0,0 +1,25 @@
package assetserver
import (
iofs "io/fs"
"path"
"github.com/wailsapp/wails/v2/internal/fs"
)
func prepareAssetsForServing(assets iofs.FS) (iofs.FS, error) {
if _, err := assets.Open("."); err != nil {
return nil, err
}
subDir, err := fs.FindPathToFile(assets, "index.html")
if err != nil {
return nil, err
}
assets, err = iofs.Sub(assets, path.Clean(subDir))
if err != nil {
return nil, err
}
return assets, nil
}

View File

@@ -3,26 +3,21 @@ package assetserver
import (
"bytes"
"context"
"embed"
"fmt"
"github.com/leaanthony/debme"
"github.com/leaanthony/slicer"
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
"github.com/wailsapp/wails/v2/internal/logger"
"io/fs"
"log"
"path/filepath"
"strings"
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
"github.com/wailsapp/wails/v2/internal/logger"
)
type DesktopAssetServer struct {
assets debme.Debme
assets fs.FS
runtimeJS []byte
assetdir string
logger *logger.Logger
}
func NewDesktopAssetServer(ctx context.Context, assets embed.FS, bindingsJSON string) (*DesktopAssetServer, error) {
func NewDesktopAssetServer(ctx context.Context, assets fs.FS, bindingsJSON string) (*DesktopAssetServer, error) {
result := &DesktopAssetServer{}
_logger := ctx.Value("logger")
@@ -30,22 +25,18 @@ func NewDesktopAssetServer(ctx context.Context, assets embed.FS, bindingsJSON st
result.logger = _logger.(*logger.Logger)
}
_assetdir := ctx.Value("assetdir")
if _assetdir != nil {
result.assetdir = _assetdir.(string)
absdir, err := filepath.Abs(result.assetdir)
if err != nil {
return nil, err
}
result.LogDebug("Loading assets from: %s", absdir)
var err error
result.assets, err = prepareAssetsForServing(assets)
if err != nil {
return nil, err
}
var buffer bytes.Buffer
buffer.WriteString(`window.wailsbindings='` + bindingsJSON + `';` + "\n")
buffer.Write(runtime.RuntimeDesktopJS)
result.runtimeJS = buffer.Bytes()
err := result.init(assets)
return result, err
return result, nil
}
func (d *DesktopAssetServer) LogDebug(message string, args ...interface{}) {
@@ -54,63 +45,8 @@ func (d *DesktopAssetServer) LogDebug(message string, args ...interface{}) {
}
}
func (d *DesktopAssetServer) SetAssetDir(assetdir string) {
d.assetdir = assetdir
}
func PathToIndexHTML(assets embed.FS) (string, error) {
stat, err := fs.Stat(assets, "index.html")
if stat != nil {
return ".", nil
}
var indexFiles slicer.StringSlicer
err = fs.WalkDir(assets, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if strings.HasSuffix(path, "index.html") {
indexFiles.Add(path)
}
return nil
})
if err != nil {
return "", err
}
if indexFiles.Length() > 1 {
return "", fmt.Errorf("multiple 'index.html' files found in assets")
}
path, _ := filepath.Split(indexFiles.AsSlice()[0])
return path, nil
}
func processAssets(assets embed.FS) (debme.Debme, error) {
result, err := debme.FS(assets, ".")
if err != nil {
return result, err
}
// Find index.html
path, err := PathToIndexHTML(assets)
if err != nil {
return debme.Debme{}, err
}
return debme.FS(assets, path)
}
func (a *DesktopAssetServer) init(assets embed.FS) error {
var err error
a.assets, err = processAssets(assets)
if err != nil {
return err
}
return nil
}
func (a *DesktopAssetServer) processIndexHTML() ([]byte, error) {
indexHTML, err := a.ReadFile("index.html")
indexHTML, err := fs.ReadFile(a.assets, "index.html")
if err != nil {
return nil, err
}
@@ -146,7 +82,9 @@ func (a *DesktopAssetServer) Load(filename string) ([]byte, string, error) {
case "/wails/ipc.js":
content = runtime.DesktopIPC
default:
content, err = a.ReadFile(filename)
filename = strings.TrimPrefix(filename, "/")
a.LogDebug("Loading file: %s", filename)
content, err = fs.ReadFile(a.assets, filename)
}
if err != nil {
return nil, "", err

View File

@@ -1,13 +0,0 @@
//go:build dev
package assetserver
import (
"os"
"path/filepath"
)
func (a *DesktopAssetServer) ReadFile(filename string) ([]byte, error) {
a.LogDebug("Loading file from disk: %s", filename)
return os.ReadFile(filepath.Join(a.assetdir, filename))
}

View File

@@ -1,7 +0,0 @@
//go:build production
package assetserver
func (a *DesktopAssetServer) ReadFile(filename string) ([]byte, error) {
return a.assets.ReadFile(filename)
}

View File

@@ -0,0 +1,20 @@
package common
import "net/url"
func TranslateUriToFile(uri string, expectedScheme string, expectedHost string) (file string, match bool, err error) {
url, err := url.Parse(uri)
if err != nil {
return "", false, err
}
if url.Scheme != expectedScheme || url.Host != expectedHost {
return "", false, nil
}
filePath := url.Path
if filePath == "" {
filePath = "/"
}
return filePath, true, nil
}

View File

@@ -14,6 +14,8 @@
@interface AppDelegate : NSResponder <NSTouchBarProvider>
@property bool alwaysOnTop;
@property bool startHidden;
@property bool startFullscreen;
@property (retain) WailsWindow* mainWindow;
@end

View File

@@ -16,14 +16,26 @@
}
- (void)applicationWillFinishLaunching:(NSNotification *)aNotification {
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
[self.mainWindow makeKeyAndOrderFront:self];
if (self.alwaysOnTop) {
[self.mainWindow setLevel:NSStatusWindowLevel];
}
if ( !self.startHidden ) {
[self.mainWindow makeKeyAndOrderFront:self];
}
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
[NSApp activateIgnoringOtherApps:YES];
if ( self.startFullscreen ) {
NSWindowCollectionBehavior behaviour = [self.mainWindow collectionBehavior];
behaviour |= NSWindowCollectionBehaviorFullScreenPrimary;
[self.mainWindow setCollectionBehavior:behaviour];
[self.mainWindow toggleFullScreen:nil];
}
}
- (void)dealloc {
[super dealloc];
}
@synthesize touchBar;

View File

@@ -12,7 +12,12 @@
#import <Cocoa/Cocoa.h>
#import "WailsContext.h"
WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int debug);
#define WindowStartsNormal 0
#define WindowStartsMaximised 1
#define WindowStartsMinimised 2
#define WindowStartsFullscreen 3
WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int debug, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight);
void Run(void*);
void SetTitle(void* ctx, const char *title);
@@ -36,7 +41,7 @@ void Quit(void*);
const char* GetSize(void *ctx);
const char* GetPos(void *ctx);
void ProcessURLResponse(void *inctx, const char *url, const char *contentType, void* data, int datalength);
void ProcessURLResponse(void *inctx, const char *url, int statusCode, const char *contentType, void* data, int datalength);
/* Dialogs */

View File

@@ -12,7 +12,7 @@
#import "WailsMenu.h"
#import "WailsMenuItem.h"
WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int debug) {
WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int debug, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight) {
[NSApplication sharedApplication];
@@ -20,23 +20,46 @@ WailsContext* Create(const char* title, int width, int height, int frameless, in
result.debug = debug;
[result CreateWindow:width :height :frameless :resizable :fullscreen :fullSizeContent :hideTitleBar :titlebarAppearsTransparent :hideTitle :useToolbar :hideToolbarSeparator :webviewIsTransparent :hideWindowOnClose :safeInit(appearance) :windowIsTranslucent];
if ( windowStartState == WindowStartsFullscreen ) {
fullscreen = 1;
}
[result CreateWindow:width :height :frameless :resizable :fullscreen :fullSizeContent :hideTitleBar :titlebarAppearsTransparent :hideTitle :useToolbar :hideToolbarSeparator :webviewIsTransparent :hideWindowOnClose :safeInit(appearance) :windowIsTranslucent :minWidth :minHeight :maxWidth :maxHeight];
[result SetTitle:safeInit(title)];
[result Center];
switch( windowStartState ) {
case WindowStartsMaximised:
[result.mainWindow zoom:nil];
break;
case WindowStartsMinimised:
//TODO: Can you start a mac app minimised?
break;
}
if ( startsHidden == 1 ) {
result.startHidden = true;
}
if ( fullscreen == 1 ) {
result.startFullscreen = true;
}
result.alwaysOnTop = alwaysOnTop;
result.hideOnClose = hideWindowOnClose;
return result;
}
void ProcessURLResponse(void *inctx, const char *url, const char *contentType, void* data, int datalength) {
void ProcessURLResponse(void *inctx, const char *url, int statusCode, const char *contentType, void* data, int datalength) {
WailsContext *ctx = (__bridge WailsContext*) inctx;
NSString *nsurl = safeInit(url);
NSString *nsContentType = safeInit(contentType);
NSData *nsdata = [NSData dataWithBytes:data length:datalength];
[ctx processURLResponse:nsurl :nsContentType :nsdata];
[ctx processURLResponse:nsurl :statusCode :nsContentType :nsdata];
[nsdata release];
}
void ExecJS(void* inctx, const char *script) {
@@ -306,6 +329,8 @@ void Run(void *inctx) {
ctx.appdelegate = delegate;
delegate.mainWindow = ctx.mainWindow;
delegate.alwaysOnTop = ctx.alwaysOnTop;
delegate.startHidden = ctx.startHidden;
delegate.startFullscreen = ctx.startFullscreen;
[ctx loadRequest:@"wails://wails/"];
[app setMainMenu:ctx.applicationMenu];

View File

@@ -11,11 +11,22 @@
#import <Cocoa/Cocoa.h>
#import <WebKit/WebKit.h>
#if __has_include(<UniformTypeIdentifiers/UTType.h>)
#define USE_NEW_FILTERS
#import <UniformTypeIdentifiers/UTType.h>
#endif
#define ON_MAIN_THREAD(str) dispatch_async(dispatch_get_main_queue(), ^{ str; });
#define unicode(input) [NSString stringWithFormat:@"%C", input]
@interface WailsWindow : NSWindow
- (BOOL)canBecomeKeyWindow;
@property NSSize userMinSize;
@property NSSize userMaxSize;
- (BOOL) canBecomeKeyWindow;
- (void) applyWindowConstraints;
- (void) disableWindowConstraints;
@end
@interface WailsContext : NSObject <WKURLSchemeHandler,WKScriptMessageHandler,WKNavigationDelegate>
@@ -26,9 +37,8 @@
@property bool hideOnClose;
@property bool shuttingDown;
@property NSSize maxSize;
@property NSSize minSize;
@property bool startHidden;
@property bool startFullscreen;
@property (retain) NSEvent* mouseEvent;
@@ -45,7 +55,7 @@
@property (retain) NSString* aboutTitle;
@property (retain) NSString* aboutDescription;
- (void) CreateWindow:(int)width :(int)height :(bool)frameless :(bool)resizable :(bool)fullscreen :(bool)fullSizeContent :(bool)hideTitleBar :(bool)titlebarAppearsTransparent :(bool)hideTitle :(bool)useToolbar :(bool)hideToolbarSeparator :(bool)webviewIsTransparent :(bool)hideWindowOnClose :(NSString *)appearance :(bool)windowIsTranslucent;
- (void) CreateWindow:(int)width :(int)height :(bool)frameless :(bool)resizable :(bool)fullscreen :(bool)fullSizeContent :(bool)hideTitleBar :(bool)titlebarAppearsTransparent :(bool)hideTitle :(bool)useToolbar :(bool)hideToolbarSeparator :(bool)webviewIsTransparent :(bool)hideWindowOnClose :(NSString *)appearance :(bool)windowIsTranslucent :(int)minWidth :(int)minHeight :(int)maxWidth :(int)maxHeight;
- (void) SetSize:(int)width :(int)height;
- (void) SetPosition:(int)x :(int) y;
- (void) SetMinSize:(int)minWidth :(int)minHeight;
@@ -70,11 +80,12 @@
- (void) SaveFileDialog :(NSString*)title :(NSString*)defaultFilename :(NSString*)defaultDirectory :(bool)canCreateDirectories :(bool)treatPackagesAsDirectories :(bool)showHiddenFiles :(NSString*)filters;
- (void) loadRequest:(NSString*)url;
- (void) processURLResponse:(NSString *)url :(NSString *)contentType :(NSData*)data;
- (void) processURLResponse:(NSString *)url :(int)statusCode :(NSString *)contentType :(NSData*)data;
- (void) ExecJS:(NSString*)script;
- (NSScreen*) getCurrentScreen;
- (void) SetAbout :(NSString*)title :(NSString*)description :(void*)imagedata :(int)datalen;
- (void) dealloc;
@end

View File

@@ -21,6 +21,16 @@
return YES;
}
- (void) applyWindowConstraints {
[self setMinSize:self.userMinSize];
[self setMaxSize:self.userMaxSize];
}
- (void) disableWindowConstraints {
[self setMinSize:NSMakeSize(0, 0)];
[self setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
}
@end
@implementation WailsContext
@@ -33,7 +43,7 @@
frame.origin.y += frame.size.height - height;
frame.size.width = width;
frame.size.height = height;
ON_MAIN_THREAD([self.mainWindow setFrame:frame display:TRUE animate:FALSE];);
[self.mainWindow setFrame:frame display:TRUE animate:FALSE];
}
- (void) SetPosition:(int)x :(int)y {
@@ -45,8 +55,8 @@
NSRect screenFrame = [screen frame];
windowFrame.origin.x = screenFrame.origin.x + (float)x;
windowFrame.origin.y = (screenFrame.origin.y + screenFrame.size.height) - windowFrame.size.height - (float)y;
ON_MAIN_THREAD([self.mainWindow setFrame:windowFrame display:TRUE animate:FALSE]; );
[self.mainWindow setFrame:windowFrame display:TRUE animate:FALSE];
}
- (void) SetMinSize:(int)minWidth :(int)minHeight {
@@ -54,13 +64,9 @@
if (self.shuttingDown) return;
NSSize size = { minWidth, minHeight };
self.minSize = size;
ON_MAIN_THREAD(
[self.mainWindow setMinSize:size];
[self adjustWindowSize];
);
self.mainWindow.userMinSize = size;
[self.mainWindow setMinSize:size];
[self adjustWindowSize];
}
@@ -73,12 +79,9 @@
size.width = maxWidth > 0 ? maxWidth : FLT_MAX;
size.height = maxHeight > 0 ? maxHeight : FLT_MAX;
self.maxSize = size;
ON_MAIN_THREAD(
[self.mainWindow setMaxSize:size];
[self adjustWindowSize];
);
self.mainWindow.userMaxSize = size;
[self.mainWindow setMaxSize:size];
[self adjustWindowSize];
}
@@ -88,23 +91,23 @@
NSRect currentFrame = [self.mainWindow frame];
if ( currentFrame.size.width > self.maxSize.width ) currentFrame.size.width = self.maxSize.width;
if ( currentFrame.size.width < self.minSize.width ) currentFrame.size.width = self.minSize.width;
if ( currentFrame.size.height > self.maxSize.height ) currentFrame.size.height = self.maxSize.height;
if ( currentFrame.size.height < self.minSize.height ) currentFrame.size.height = self.minSize.height;
if ( currentFrame.size.width > self.mainWindow.userMaxSize.width ) currentFrame.size.width = self.mainWindow.userMaxSize.width;
if ( currentFrame.size.width < self.mainWindow.userMinSize.width ) currentFrame.size.width = self.mainWindow.userMinSize.width;
if ( currentFrame.size.height > self.mainWindow.userMaxSize.height ) currentFrame.size.height = self.mainWindow.userMaxSize.height;
if ( currentFrame.size.height < self.mainWindow.userMinSize.height ) currentFrame.size.height = self.mainWindow.userMinSize.height;
[self.mainWindow setFrame:currentFrame display:YES animate:FALSE];
}
- (void) dealloc {
[super dealloc];
[self.appdelegate release];
[self.mainWindow release];
[self.mouseEvent release];
[self.userContentController release];
[self.urlRequests release];
[self.applicationMenu release];
[super dealloc];
}
- (NSScreen*) getCurrentScreen {
@@ -116,11 +119,11 @@
}
- (void) SetTitle:(NSString*)title {
ON_MAIN_THREAD([self.mainWindow setTitle:title];)
[self.mainWindow setTitle:title];
}
- (void) Center {
ON_MAIN_THREAD( [self.mainWindow center]; );
[self.mainWindow center];
}
- (BOOL) isFullscreen {
@@ -131,37 +134,29 @@
return NO;
}
- (void) CreateWindow:(int)width :(int)height :(bool)frameless :(bool)resizable :(bool)fullscreen :(bool)fullSizeContent :(bool)hideTitleBar :(bool)titlebarAppearsTransparent :(bool)hideTitle :(bool)useToolbar :(bool)hideToolbarSeparator :(bool)webviewIsTransparent :(bool)hideWindowOnClose :(NSString*)appearance :(bool)windowIsTranslucent {
- (void) CreateWindow:(int)width :(int)height :(bool)frameless :(bool)resizable :(bool)fullscreen :(bool)fullSizeContent :(bool)hideTitleBar :(bool)titlebarAppearsTransparent :(bool)hideTitle :(bool)useToolbar :(bool)hideToolbarSeparator :(bool)webviewIsTransparent :(bool)hideWindowOnClose :(NSString*)appearance :(bool)windowIsTranslucent :(int)minWidth :(int)minHeight :(int)maxWidth :(int)maxHeight {
self.urlRequests = [NSMutableDictionary new];
NSWindowStyleMask styleMask = NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable;
NSWindowStyleMask styleMask = 0;
if (frameless) {
styleMask = NSWindowStyleMaskBorderless;
titlebarAppearsTransparent = true;
hideTitle = true;
} else {
if( !frameless ) {
if (!hideTitleBar) {
styleMask |= NSWindowStyleMaskTitled;
}
if (fullscreen) {
styleMask |= NSWindowStyleMaskFullScreen;
}
if( fullSizeContent || frameless || titlebarAppearsTransparent ) {
styleMask |= NSWindowStyleMaskFullSizeContentView;
}
styleMask |= NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable;
}
if( fullSizeContent || frameless || titlebarAppearsTransparent ) {
styleMask |= NSWindowStyleMaskFullSizeContentView;
}
if (resizable) {
styleMask |= NSWindowStyleMaskResizable;
}
self.mainWindow = [[[WailsWindow alloc] initWithContentRect:NSMakeRect(0, 0, width, height)
styleMask:styleMask backing:NSBackingStoreBuffered defer:NO]
autorelease];
self.mainWindow = [[WailsWindow alloc] initWithContentRect:NSMakeRect(0, 0, width, height)
styleMask:styleMask backing:NSBackingStoreBuffered defer:NO];
if (!frameless && useToolbar) {
id toolbar = [[NSToolbar alloc] initWithIdentifier:@"wails.toolbar"];
@@ -192,15 +187,25 @@
[self.mainWindow setAppearance:nsAppearance];
}
// Set up min/max
NSSize maxSize = { FLT_MAX, FLT_MAX };
self.maxSize = maxSize;
NSSize minSize = { 0, 0 };
self.minSize = minSize;
[self adjustWindowSize];
NSSize minSize = { minWidth, minHeight };
NSSize maxSize = { maxWidth, maxHeight };
if (maxSize.width == 0) {
maxSize.width = FLT_MAX;
}
if (maxSize.height == 0) {
maxSize.height = FLT_MAX;
}
self.mainWindow.userMaxSize = maxSize;
self.mainWindow.userMinSize = minSize;
if( !fullscreen ) {
[self.mainWindow applyWindowConstraints];
}
WindowDelegate *windowDelegate = [WindowDelegate new];
windowDelegate.hideOnClose = hideWindowOnClose;
windowDelegate.ctx = self;
[self.mainWindow setDelegate:windowDelegate];
// Webview stuff here!
@@ -278,7 +283,7 @@
}
- (NSMenu*) newMenu :(NSString*)title {
WailsMenu *result = [[[WailsMenu new] initWithTitle:title] autorelease];
WailsMenu *result = [[WailsMenu new] initWithTitle:title];
[result setAutoenablesItems:NO];
return result;
}
@@ -294,14 +299,14 @@
}
- (void) SetRGBA:(int)r :(int)g :(int)b :(int)a {
float red = r/255;
float green = g/255;
float blue = b/255;
float alpha = a/255;
float red = r/255.0;
float green = g/255.0;
float blue = b/255.0;
float alpha = a/255.0;
id colour = [NSColor colorWithCalibratedRed:red green:green blue:blue alpha:alpha ];
ON_MAIN_THREAD([self.mainWindow setBackgroundColor:colour];);
[self.mainWindow setBackgroundColor:colour];
}
- (void) HideMouse {
@@ -325,66 +330,66 @@
// Fullscreen sets the main window to be fullscreen
- (void) Fullscreen {
if( ! [self isFullScreen] ) {
ON_MAIN_THREAD([self.mainWindow toggleFullScreen:nil];)
[self.mainWindow disableWindowConstraints];
[self.mainWindow toggleFullScreen:nil];
}
}
// UnFullscreen resets the main window after a fullscreen
- (void) UnFullscreen {
if( [self isFullScreen] ) {
ON_MAIN_THREAD([self.mainWindow toggleFullScreen:nil];)
[self.mainWindow applyWindowConstraints];
[self.mainWindow toggleFullScreen:nil];
}
}
- (void) Minimise {
ON_MAIN_THREAD([self.mainWindow miniaturize:nil];)
[self.mainWindow miniaturize:nil];
}
- (void) UnMinimise {
ON_MAIN_THREAD([self.mainWindow deminiaturize:nil];)
[self.mainWindow deminiaturize:nil];
}
- (void) Hide {
ON_MAIN_THREAD([self.mainWindow orderOut:nil];)
[self.mainWindow orderOut:nil];
}
- (void) Show {
ON_MAIN_THREAD(
[self.mainWindow makeKeyAndOrderFront:nil];
[NSApp activateIgnoringOtherApps:YES];
)
[self.mainWindow makeKeyAndOrderFront:nil];
[NSApp activateIgnoringOtherApps:YES];
}
- (void) Maximise {
if (![self.mainWindow isZoomed]) {
ON_MAIN_THREAD([self.mainWindow zoom:nil];)
[self.mainWindow zoom:nil];
}
}
- (void) UnMaximise {
if ([self.mainWindow isZoomed]) {
ON_MAIN_THREAD([self.mainWindow zoom:nil];)
[self.mainWindow zoom:nil];
}
}
- (void) ExecJS:(NSString*)script {
ON_MAIN_THREAD(
[self.webview evaluateJavaScript:script completionHandler:nil];
)
[self.webview evaluateJavaScript:script completionHandler:nil];
}
- (void) processURLResponse:(NSString *)url :(NSString *)contentType :(NSData *)data {
- (void) processURLResponse:(NSString *)url :(int)statusCode :(NSString *)contentType :(NSData *)data {
id<WKURLSchemeTask> urlSchemeTask = self.urlRequests[url];
NSURL *nsurl = [NSURL URLWithString:url];
NSHTTPURLResponse *response = [NSHTTPURLResponse new];
NSMutableDictionary *headerFields = [NSMutableDictionary new];
headerFields[@"content-type"] = contentType;
[response initWithURL:nsurl statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:headerFields];
if ( ![contentType isEqualToString:@""] ) {
headerFields[@"content-type"] = contentType;
}
NSHTTPURLResponse *response = [[NSHTTPURLResponse new] initWithURL:nsurl statusCode:statusCode HTTPVersion:@"HTTP/1.1" headerFields:headerFields];
[urlSchemeTask didReceiveResponse:response];
[urlSchemeTask didReceiveData:data];
[urlSchemeTask didFinish];
[self.urlRequests removeObjectForKey:url];
[response release];
[headerFields release];
}
- (void)webView:(nonnull WKWebView *)webView startURLSchemeTask:(nonnull id<WKURLSchemeTask>)urlSchemeTask {
@@ -406,15 +411,13 @@
// Check for drag
if ( [m isEqualToString:@"drag"] ) {
if( ! [self isFullScreen] ) {
if( self.mouseEvent != nil ) {
[self HideMouse];
ON_MAIN_THREAD(
[self.mainWindow performWindowDragWithEvent:self.mouseEvent];
);
}
if( [self isFullScreen] ) {
return;
}
if( self.mouseEvent != nil ) {
[self.mainWindow performWindowDragWithEvent:self.mouseEvent];
}
return;
}
const char *_m = [m UTF8String];
@@ -455,28 +458,26 @@
NSData *imageData = [NSData dataWithBytes:iconData length:iconDataLength];
icon = [[NSImage alloc] initWithData:imageData];
}
ON_MAIN_THREAD(
if( icon != nil) {
[alert setIcon:icon];
}
[alert.window setLevel:NSFloatingWindowLevel];
if( icon != nil) {
[alert setIcon:icon];
}
[alert.window setLevel:NSFloatingWindowLevel];
long response = [alert runModal];
int result;
if( response == NSAlertFirstButtonReturn ) {
result = 0;
}
else if( response == NSAlertSecondButtonReturn ) {
result = 1;
}
else if( response == NSAlertThirdButtonReturn ) {
result = 2;
} else {
result = 3;
}
processMessageDialogResponse(result);
)
long response = [alert runModal];
int result;
if( response == NSAlertFirstButtonReturn ) {
result = 0;
}
else if( response == NSAlertSecondButtonReturn ) {
result = 1;
}
else if( response == NSAlertThirdButtonReturn ) {
result = 2;
} else {
result = 3;
}
processMessageDialogResponse(result);
}
-(void) OpenFileDialog :(NSString*)title :(NSString*)defaultFilename :(NSString*)defaultDirectory :(bool)allowDirectories :(bool)allowFiles :(bool)canCreateDirectories :(bool)treatPackagesAsDirectories :(bool)resolveAliases :(bool)showHiddenFiles :(bool)allowMultipleSelection :(NSString*)filters {
@@ -492,11 +493,24 @@
// Filters - semicolon delimited list of file extensions
if( allowFiles ) {
if( filters != nil ) {
if( filters != nil && [filters length] > 0) {
filters = [filters stringByReplacingOccurrencesOfString:@"*." withString:@""];
filters = [filters stringByReplacingOccurrencesOfString:@" " withString:@""];
NSArray *filterList = [filters componentsSeparatedByString:@";"];
[dialog setAllowedFileTypes:filterList];
#ifdef USE_NEW_FILTERS
NSMutableArray *contentTypes = [[NSMutableArray new] autorelease];
for (NSString *filter in filterList) {
if (@available(macOS 11.0, *)) {
UTType *t = [UTType typeWithFilenameExtension:filter];
[contentTypes addObject:t];
}
}
if (@available(macOS 11.0, *)) {
[dialog setAllowedContentTypes:contentTypes];
}
#else
[dialog setAllowedFileTypes:filterList];
#endif
} else {
[dialog setAllowsOtherFileTypes:true];
}
@@ -526,6 +540,10 @@
// Setup callback handler
[dialog beginSheetModalForWindow:self.mainWindow completionHandler:^(NSModalResponse returnCode) {
if ( returnCode != NSModalResponseOK) {
processOpenFileDialogResponse("[]");
return;
}
NSMutableArray *arr = [NSMutableArray new];
for (NSURL *url in [dialog URLs]) {
[arr addObject:[url path]];
@@ -533,10 +551,10 @@
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:arr options:0 error:nil];
NSString *nsjson = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
processOpenFileDialogResponse([nsjson UTF8String]);
[nsjson release];
[arr release];
}];
ON_MAIN_THREAD([dialog runModal];)
}
@@ -544,7 +562,7 @@
// Create the dialog
NSSavePanel *dialog = [NSOpenPanel savePanel];
NSSavePanel *dialog = [NSSavePanel savePanel];
// Valid but appears to do nothing.... :/
if( title != nil ) {
@@ -552,7 +570,7 @@
}
// Filters - semicolon delimited list of file extensions
if( filters != nil ) {
if( filters != nil && [filters length] > 0) {
filters = [filters stringByReplacingOccurrencesOfString:@"*." withString:@""];
filters = [filters stringByReplacingOccurrencesOfString:@" " withString:@""];
NSArray *filterList = [filters componentsSeparatedByString:@";"];
@@ -578,12 +596,16 @@
// Setup callback handler
[dialog beginSheetModalForWindow:self.mainWindow completionHandler:^(NSModalResponse returnCode) {
NSURL *url = [dialog URL];
processSaveFileDialogResponse([url.path UTF8String]);
if ( returnCode == NSModalResponseOK ) {
NSURL *url = [dialog URL];
if ( url != nil ) {
processSaveFileDialogResponse([url.path UTF8String]);
return;
}
}
processSaveFileDialogResponse("");
}];
ON_MAIN_THREAD([dialog runModal];)
}
- (void) SetAbout :(NSString*)title :(NSString*)description :(void*)imagedata :(int)datalen {
@@ -611,8 +633,7 @@
[alert setIcon:self.aboutImage];
}
ON_MAIN_THREAD([alert runModal];)
[alert runModal];
}
@end

View File

@@ -19,7 +19,7 @@
}
- (NSMenuItem*) newMenuItemWithContext :(WailsContext*)ctx :(NSString*)title :(SEL)selector :(NSString*)key :(NSEventModifierFlags)flags {
NSMenuItem *result = [[NSMenuItem new] autorelease];
NSMenuItem *result = [NSMenuItem new];
if ( title != nil ) {
[result setTitle:title];
}
@@ -43,6 +43,8 @@
- (WailsMenu*) initWithNSTitle:(NSString *)title {
if( title != nil ) {
[super initWithTitle:title];
} else {
[self init];
}
[self setAutoenablesItems:NO];
return self;
@@ -50,7 +52,7 @@
- (void) appendSubmenu :(WailsMenu*)child {
NSMenuItem *childMenuItem = [[NSMenuItem new] autorelease];
[childMenuItem setTitle:[child title]];
[childMenuItem setTitle:child.title];
[self addItem:childMenuItem];
[childMenuItem setSubmenu:child];
}
@@ -64,7 +66,7 @@
if( appName == nil ) {
appName = [[NSProcessInfo processInfo] processName];
}
WailsMenu *appMenu = [[WailsMenu new] initWithNSTitle:appName];
WailsMenu *appMenu = [[[WailsMenu new] initWithNSTitle:appName] autorelease];
id quitTitle = [@"Quit " stringByAppendingString:appName];
NSMenuItem* quitMenuItem = [self newMenuItem:quitTitle :@selector(Quit) :@"q" :NSEventModifierFlagCommand];
quitMenuItem.target = ctx;
@@ -77,7 +79,7 @@
}
case EditMenu:
{
WailsMenu *editMenu = [[WailsMenu new] initWithNSTitle:@"Edit"];
WailsMenu *editMenu = [[[WailsMenu new] initWithNSTitle:@"Edit"] autorelease];
[editMenu addItem:[self newMenuItem:@"Undo" :@selector(undoActionName) :@"z" :NSEventModifierFlagCommand]];
[editMenu addItem:[self newMenuItem:@"Redo" :@selector(redoActionName) :@"z" :(NSEventModifierFlagShift | NSEventModifierFlagCommand)]];
[editMenu addItem:[NSMenuItem separatorItem]];
@@ -91,7 +93,7 @@
// NSMenuItem *speechMenuItem = [[NSMenuItem new] autorelease];
// [speechMenuItem setTitle:@"Speech"];
// [editMenu addItem:speechMenuItem];
WailsMenu *speechMenu = [[WailsMenu new] initWithNSTitle:@"Speech"];
WailsMenu *speechMenu = [[[WailsMenu new] initWithNSTitle:@"Speech"] autorelease];
[speechMenu addItem:[self newMenuItem:@"Start Speaking" :@selector(startSpeaking:) :@""]];
[speechMenu addItem:[self newMenuItem:@"Stop Speaking" :@selector(stopSpeaking:) :@""]];
[editMenu appendSubmenu:speechMenu];

View File

@@ -8,10 +8,17 @@
#ifndef WindowDelegate_h
#define WindowDelegate_h
#import "WailsContext.h"
@interface WindowDelegate : NSObject <NSWindowDelegate>
@property bool hideOnClose;
@property (assign) WailsContext* ctx;
- (void)windowDidExitFullScreen:(NSNotification *)notification;
@end

View File

@@ -12,13 +12,26 @@
#import "WailsContext.h"
@implementation WindowDelegate
- (BOOL)windowShouldClose:(WailsWindow *)sender {
[sender orderOut:nil];
if( self.hideOnClose == false ) {
processMessage("Q");
if( self.hideOnClose ) {
[NSApp hide:nil];
return false;
}
return !self.hideOnClose;
processMessage("Q");
return false;
}
- (void)windowDidExitFullScreen:(NSNotification *)notification {
[self.ctx.mainWindow applyWindowConstraints];
}
- (void)windowWillEnterFullScreen:(NSNotification *)notification {
[self.ctx.mainWindow disableWindowConstraints];
}
- (NSApplicationPresentationOptions)window:(WailsWindow *)window willUseFullScreenPresentationOptions:(NSApplicationPresentationOptions)proposedOptions {
return NSApplicationPresentationAutoHideToolbar | NSApplicationPresentationAutoHideMenuBar | NSApplicationPresentationFullScreen;
}
@end

View File

@@ -84,7 +84,7 @@ func (f *Frontend) openDialog(options *frontend.OpenDialogOptions, multiple bool
// OpenFileDialog prompts the user to select a file
func (f *Frontend) OpenFileDialog(options frontend.OpenDialogOptions) (string, error) {
results, err := f.openDialog(&options, false, options.AllowFiles, options.AllowDirectories)
results, err := f.openDialog(&options, false, true, false)
if err != nil {
return "", err
}
@@ -97,7 +97,7 @@ func (f *Frontend) OpenFileDialog(options frontend.OpenDialogOptions) (string, e
// OpenMultipleFilesDialog prompts the user to select a file
func (f *Frontend) OpenMultipleFilesDialog(options frontend.OpenDialogOptions) ([]string, error) {
return f.openDialog(&options, true, options.AllowFiles, options.AllowDirectories)
return f.openDialog(&options, true, true, false)
}
// SaveFileDialog prompts the user to select a file

View File

@@ -16,15 +16,17 @@ import "C"
import (
"context"
"encoding/json"
"fmt"
"html/template"
"log"
"os"
"strconv"
"strings"
"unsafe"
"github.com/wailsapp/wails/v2/internal/binding"
"github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/internal/frontend/assetserver"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/common"
"github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/pkg/options"
)
@@ -51,11 +53,10 @@ type Frontend struct {
assets *assetserver.DesktopAssetServer
// main window handle
mainWindow *Window
minWidth, minHeight, maxWidth, maxHeight int
bindings *binding.Bindings
dispatcher frontend.Dispatcher
servingFromDisk bool
mainWindow *Window
bindings *binding.Bindings
dispatcher frontend.Dispatcher
servingFromDisk bool
}
func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher) *Frontend {
@@ -163,15 +164,11 @@ func (f *Frontend) WindowSetTitle(title string) {
}
func (f *Frontend) WindowFullscreen() {
f.mainWindow.SetMaxSize(0, 0)
f.mainWindow.SetMinSize(0, 0)
f.mainWindow.Fullscreen()
}
func (f *Frontend) WindowUnFullscreen() {
f.mainWindow.UnFullscreen()
f.mainWindow.SetMaxSize(f.maxWidth, f.maxHeight)
f.mainWindow.SetMinSize(f.minWidth, f.minHeight)
}
func (f *Frontend) WindowShow() {
@@ -195,13 +192,9 @@ func (f *Frontend) WindowUnminimise() {
}
func (f *Frontend) WindowSetMinSize(width int, height int) {
f.minWidth = width
f.minHeight = height
f.mainWindow.SetMinSize(width, height)
}
func (f *Frontend) WindowSetMaxSize(width int, height int) {
f.maxWidth = width
f.maxHeight = height
f.mainWindow.SetMaxSize(width, height)
}
@@ -213,10 +206,10 @@ func (f *Frontend) WindowSetRGBA(col *options.RGBA) {
}
func (f *Frontend) Quit() {
f.mainWindow.Quit()
if f.frontendOptions.OnShutdown != nil {
f.frontendOptions.OnShutdown(f.ctx)
if f.frontendOptions.OnBeforeClose != nil && f.frontendOptions.OnBeforeClose(f.ctx) {
return
}
f.mainWindow.Quit()
}
type EventNotify struct {
@@ -246,23 +239,31 @@ func (f *Frontend) processMessage(message string) {
return
}
result, err := f.dispatcher.ProcessMessage(message, f)
if err != nil {
f.logger.Error(err.Error())
f.Callback(result)
return
}
if result == "" {
return
}
//if strings.HasPrefix(message, "systemevent:") {
// f.processSystemEvent(message)
// return
//}
go func() {
result, err := f.dispatcher.ProcessMessage(message, f)
if err != nil {
f.logger.Error(err.Error())
f.Callback(result)
return
}
if result == "" {
return
}
switch result[0] {
case 'c':
// Callback from a method call
f.Callback(result[1:])
default:
f.logger.Info("Unknown message returned from dispatcher: %+v", result)
}
}()
switch result[0] {
case 'c':
// Callback from a method call
f.Callback(result[1:])
default:
f.logger.Info("Unknown message returned from dispatcher: %+v", result)
}
}
func (f *Frontend) Callback(message string) {
@@ -274,17 +275,34 @@ func (f *Frontend) ExecJS(js string) {
}
func (f *Frontend) processRequest(r *request) {
url := C.GoString(r.url)
url = strings.TrimPrefix(url, "wails://wails")
if !strings.HasPrefix(url, "/") {
return
uri := C.GoString(r.url)
var _contents []byte
var _mimetype string
// Translate URI to file
file, match, err := common.TranslateUriToFile(uri, "wails", "wails")
if err == nil {
if !match {
// This should never happen on darwin, because we get only called for wails://
panic("Unexpected host for request on wails:// scheme")
}
// Load file from asset store
_contents, _mimetype, err = f.assets.Load(file)
}
_contents, _mimetype, err := f.assets.Load(url)
statusCode := 200
if err != nil {
f.logger.Error(err.Error())
//TODO: Handle errors
return
if os.IsNotExist(err) {
statusCode = 404
} else {
err = fmt.Errorf("Error processing request %s: %w", uri, err)
f.logger.Error(err.Error())
statusCode = 500
}
}
var data unsafe.Pointer
if _contents != nil {
data = unsafe.Pointer(&_contents[0])
@@ -292,9 +310,25 @@ func (f *Frontend) processRequest(r *request) {
mimetype := C.CString(_mimetype)
defer C.free(unsafe.Pointer(mimetype))
C.ProcessURLResponse(r.ctx, r.url, mimetype, data, C.int(len(_contents)))
C.ProcessURLResponse(r.ctx, r.url, C.int(statusCode), mimetype, data, C.int(len(_contents)))
}
//func (f *Frontend) processSystemEvent(message string) {
// sl := strings.Split(message, ":")
// if len(sl) != 2 {
// f.logger.Error("Invalid system message: %s", message)
// return
// }
// switch sl[1] {
// case "fullscreen":
// f.mainWindow.DisableSizeConstraints()
// case "unfullscreen":
// f.mainWindow.EnableSizeConstraints()
// default:
// f.logger.Error("Unknown system message: %s", message)
// }
//}
//export processMessage
func processMessage(message *C.char) {
goMessage := C.GoString(message)

View File

@@ -32,7 +32,8 @@ void processCallback(int callbackID) {
void processURLRequest(void *ctx, const char* url) {
NSLog(@"processURLRequest called");
const char myByteArray[] = { 0x3c,0x68,0x31,0x3e,0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f,0x72,0x6c,0x64,0x21,0x3c,0x2f,0x68,0x31,0x3e };
ProcessURLResponse(ctx, url, "text/html", (void*)myByteArray, 21);
// void *inctx, const char *url, int statusCode, const char *contentType, void* data, int datalength
ProcessURLResponse(ctx, url, 200, "text/html", (void*)myByteArray, 21);
}
unsigned char _Users_username_Pictures_SaltBae_png[] = {
@@ -200,9 +201,9 @@ unsigned int _Users_username_Pictures_SaltBae_png_len = 1863;
int main(int argc, const char * argv[]) {
// insert code here...
int frameless = 1;
int resizable = 0;
int fullscreen = 0;
int frameless = 0;
int resizable = 1;
int fullscreen = 1;
int fullSizeContent = 1;
int hideTitleBar = 0;
int titlebarAppearsTransparent = 0;
@@ -215,7 +216,10 @@ int main(int argc, const char * argv[]) {
const char* appearance = "NSAppearanceNameDarkAqua";
int windowIsTranslucent = 1;
int debug = 1;
WailsContext *result = Create("OI OI!",400,400, frameless, resizable, fullscreen, fullSizeContent, hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent, alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, debug);
int windowStartState = 0;
int startsHidden = 0;
WailsContext *result = Create("OI OI!",400,400, frameless, resizable, fullscreen, fullSizeContent, hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent, alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, debug, windowStartState,
startsHidden, 400, 400, 600, 600);
SetRGBA(result, 255, 0, 0, 255);
void *m = NewMenu("");
SetAbout(result, "Fake title", "I am a description", _Users_username_Pictures_SaltBae_png, _Users_username_Pictures_SaltBae_png_len);
@@ -228,7 +232,7 @@ int main(int argc, const char * argv[]) {
AppendSubmenu(m, submenu);
UpdateMenuItem(menuITem, 1);
SetAsApplicationMenu(result, m);
SetPosition(result, 100, 100);
// SetPosition(result, 100, 100);

View File

@@ -1,3 +1,6 @@
//go:build darwin
// +build darwin
package darwin
/*
@@ -47,6 +50,7 @@ func NewWindow(frontendOptions *options.App, debugMode bool) *Window {
fullscreen := bool2Cint(frontendOptions.Fullscreen)
alwaysOnTop := bool2Cint(frontendOptions.AlwaysOnTop)
hideWindowOnClose := bool2Cint(frontendOptions.HideWindowOnClose)
startsHidden := bool2Cint(frontendOptions.StartHidden)
debug := bool2Cint(debugMode)
var fullSizeContent, hideTitleBar, hideTitle, useToolbar, webviewIsTransparent C.int
@@ -55,6 +59,11 @@ func NewWindow(frontendOptions *options.App, debugMode bool) *Window {
width := C.int(frontendOptions.Width)
height := C.int(frontendOptions.Height)
minWidth := C.int(frontendOptions.MinWidth)
minHeight := C.int(frontendOptions.MinHeight)
maxWidth := C.int(frontendOptions.MaxWidth)
maxHeight := C.int(frontendOptions.MaxHeight)
windowStartState := C.int(int(frontendOptions.WindowStartState))
title = c.String(frontendOptions.Title)
@@ -75,7 +84,8 @@ func NewWindow(frontendOptions *options.App, debugMode bool) *Window {
}
var context *C.WailsContext = C.Create(title, width, height, frameless, resizable, fullscreen, fullSizeContent,
hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent,
alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, debug)
alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, debug, windowStartState, startsHidden,
minWidth, minHeight, maxWidth, maxHeight)
// Create menu
result := &Window{
@@ -102,9 +112,6 @@ func NewWindow(frontendOptions *options.App, debugMode bool) *Window {
result.SetApplicationMenu(frontendOptions.Menu)
}
result.SetMinSize(frontendOptions.MinWidth, frontendOptions.MinHeight)
result.SetMaxSize(frontendOptions.MaxWidth, frontendOptions.MaxHeight)
return result
}
@@ -161,16 +168,10 @@ func (w *Window) UnMinimise() {
}
func (w *Window) SetMinSize(width int, height int) {
if width == 0 && height == 0 {
return
}
C.SetMinSize(w.context, C.int(width), C.int(height))
}
func (w *Window) SetMaxSize(width int, height int) {
if width == 0 && height == 0 {
return
}
C.SetMaxSize(w.context, C.int(width), C.int(height))
}

View File

@@ -0,0 +1,17 @@
//go:build linux
// +build linux
package desktop
import (
"context"
"github.com/wailsapp/wails/v2/internal/binding"
"github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/linux"
"github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/pkg/options"
)
func NewFrontend(ctx context.Context, appoptions *options.App, logger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher) frontend.Frontend {
return linux.NewFrontend(ctx, appoptions, logger, appBindings, dispatcher)
}

View File

@@ -0,0 +1,12 @@
//go:build linux
// +build linux
package linux
import "github.com/pkg/browser"
// BrowserOpenURL Use the default browser to open the url
func (f *Frontend) BrowserOpenURL(url string) {
// Specific method implementation
_ = browser.OpenURL(url)
}

View File

@@ -0,0 +1,32 @@
package linux
/*
#include <stdlib.h>
*/
import "C"
import "unsafe"
// Calloc handles alloc/dealloc of C data
type Calloc struct {
pool []unsafe.Pointer
}
// NewCalloc creates a new allocator
func NewCalloc() Calloc {
return Calloc{}
}
// String creates a new C string and retains a reference to it
func (c Calloc) String(in string) *C.char {
result := C.CString(in)
c.pool = append(c.pool, unsafe.Pointer(result))
return result
}
// Free frees all allocated C memory
func (c Calloc) Free() {
for _, str := range c.pool {
C.free(str)
}
c.pool = []unsafe.Pointer{}
}

View File

@@ -0,0 +1,45 @@
//go:build linux
// +build linux
package linux
import (
"github.com/wailsapp/wails/v2/internal/frontend"
)
import "C"
var openFileResults = make(chan string)
func (f *Frontend) OpenFileDialog(dialogOptions frontend.OpenDialogOptions) (result string, err error) {
f.dispatch(func() {
println("Before OpenFileDialog")
f.mainWindow.OpenFileDialog(dialogOptions)
println("After OpenFileDialog")
})
println("Waiting for result")
result = <-openFileResults
println("Got result")
return
}
func (f *Frontend) OpenMultipleFilesDialog(dialogOptions frontend.OpenDialogOptions) ([]string, error) {
panic("implement me")
}
func (f *Frontend) OpenDirectoryDialog(dialogOptions frontend.OpenDialogOptions) (string, error) {
panic("implement me")
}
func (f *Frontend) SaveFileDialog(dialogOptions frontend.SaveDialogOptions) (string, error) {
panic("implement me")
}
func (f *Frontend) MessageDialog(dialogOptions frontend.MessageDialogOptions) (string, error) {
panic("implement me")
}
//export processOpenFileResult
func processOpenFileResult(result *C.char) {
openFileResults <- C.GoString(result)
}

View File

@@ -0,0 +1,374 @@
//go:build linux
// +build linux
package linux
/*
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0
#include "gtk/gtk.h"
#include "webkit2/webkit2.h"
extern void callDispatchedMethod(int id);
static inline void processDispatchID(gpointer id) {
callDispatchedMethod(GPOINTER_TO_INT(id));
}
static void gtkDispatch(int id) {
gdk_threads_add_idle((GSourceFunc)processDispatchID, GINT_TO_POINTER(id));
}
*/
import "C"
import (
"context"
"encoding/json"
"fmt"
"log"
"os"
"strconv"
"sync"
"text/template"
"unsafe"
"github.com/wailsapp/wails/v2/internal/binding"
"github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/internal/frontend/assetserver"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/common"
"github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/pkg/options"
)
type Frontend struct {
// Context
ctx context.Context
frontendOptions *options.App
logger *logger.Logger
debug bool
// Assets
assets *assetserver.DesktopAssetServer
startURL string
// main window handle
mainWindow *Window
// minWidth, minHeight, maxWidth, maxHeight int
bindings *binding.Bindings
dispatcher frontend.Dispatcher
servingFromDisk bool
}
func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher) *Frontend {
println("[NewFrontend] PID:", os.Getpid())
// Set GDK_BACKEND=x11 to prevent warnings
os.Setenv("GDK_BACKEND", "x11")
result := &Frontend{
frontendOptions: appoptions,
logger: myLogger,
bindings: appBindings,
dispatcher: dispatcher,
ctx: ctx,
startURL: "file://wails/",
}
bindingsJSON, err := appBindings.ToJSON()
if err != nil {
log.Fatal(err)
}
_devServerURL := ctx.Value("devserverurl")
if _devServerURL != nil {
devServerURL := _devServerURL.(string)
if len(devServerURL) > 0 && devServerURL != "http://localhost:34115" {
result.startURL = devServerURL
return result
}
}
// Check if we have been given a directory to serve assets from.
// If so, this means we are in dev mode and are serving assets off disk.
// We indicate this through the `servingFromDisk` flag to ensure requests
// aren't cached by webkit.
_assetdir := ctx.Value("assetdir")
if _assetdir != nil {
result.servingFromDisk = true
}
assets, err := assetserver.NewDesktopAssetServer(ctx, appoptions.Assets, bindingsJSON)
if err != nil {
log.Fatal(err)
}
result.assets = assets
go result.startMessageProcessor()
go result.startRequestProcessor()
C.gtk_init(nil, nil)
var _debug = ctx.Value("debug")
if _debug != nil {
result.debug = _debug.(bool)
}
result.mainWindow = NewWindow(appoptions, result.debug)
return result
}
func (f *Frontend) startMessageProcessor() {
for message := range messageBuffer {
f.processMessage(message)
}
}
func (f *Frontend) WindowReload() {
f.ExecJS("runtime.WindowReload();")
}
func (f *Frontend) Run(ctx context.Context) error {
f.ctx = context.WithValue(ctx, "frontend", f)
go func() {
if f.frontendOptions.OnStartup != nil {
f.frontendOptions.OnStartup(f.ctx)
}
}()
f.mainWindow.Run()
return nil
}
func (f *Frontend) WindowCenter() {
f.mainWindow.Center()
}
func (f *Frontend) WindowSetPos(x, y int) {
f.mainWindow.SetPos(x, y)
}
func (f *Frontend) WindowGetPos() (int, int) {
return f.mainWindow.Pos()
}
func (f *Frontend) WindowSetSize(width, height int) {
f.mainWindow.SetSize(width, height)
}
func (f *Frontend) WindowGetSize() (int, int) {
return f.mainWindow.Size()
}
func (f *Frontend) WindowSetTitle(title string) {
f.mainWindow.SetTitle(title)
}
func (f *Frontend) WindowFullscreen() {
f.mainWindow.Fullscreen()
}
func (f *Frontend) WindowUnFullscreen() {
f.mainWindow.UnFullscreen()
}
func (f *Frontend) WindowShow() {
f.mainWindow.Show()
}
func (f *Frontend) WindowHide() {
f.mainWindow.Hide()
}
func (f *Frontend) WindowMaximise() {
f.mainWindow.Maximise()
}
func (f *Frontend) WindowUnmaximise() {
f.mainWindow.UnMaximise()
}
func (f *Frontend) WindowMinimise() {
f.mainWindow.Minimise()
}
func (f *Frontend) WindowUnminimise() {
f.mainWindow.UnMinimise()
}
func (f *Frontend) WindowSetMinSize(width int, height int) {
f.mainWindow.SetMinSize(width, height)
}
func (f *Frontend) WindowSetMaxSize(width int, height int) {
f.mainWindow.SetMaxSize(width, height)
}
func (f *Frontend) WindowSetRGBA(col *options.RGBA) {
if col == nil {
return
}
}
func (f *Frontend) Quit() {
if f.frontendOptions.OnBeforeClose != nil && f.frontendOptions.OnBeforeClose(f.ctx) {
return
}
f.mainWindow.Quit()
}
type EventNotify struct {
Name string `json:"name"`
Data []interface{} `json:"data"`
}
func (f *Frontend) Notify(name string, data ...interface{}) {
notification := EventNotify{
Name: name,
Data: data,
}
payload, err := json.Marshal(notification)
if err != nil {
f.logger.Error(err.Error())
return
}
f.ExecJS(`window.wails.EventsNotify('` + template.JSEscapeString(string(payload)) + `');`)
}
func (f *Frontend) processMessage(message string) {
if message == "drag" {
// if !f.mainWindow.IsFullScreen() {
f.startDrag()
// }
return
}
go func() {
result, err := f.dispatcher.ProcessMessage(message, f)
if err != nil {
f.logger.Error(err.Error())
f.Callback(result)
return
}
if result == "" {
return
}
switch result[0] {
case 'c':
// Callback from a method call
f.Callback(result[1:])
default:
f.logger.Info("Unknown message returned from dispatcher: %+v", result)
}
}()
}
func (f *Frontend) Callback(message string) {
f.ExecJS(`window.wails.Callback(` + strconv.Quote(message) + `);`)
}
func (f *Frontend) startDrag() {
f.dispatch(func() {
f.mainWindow.StartDrag()
})
}
func (f *Frontend) ExecJS(js string) {
f.dispatch(func() {
f.mainWindow.ExecJS(js)
})
}
func (f *Frontend) dispatch(fn func()) {
dispatchCallbackLock.Lock()
id := 0
for fn := dispatchCallbacks[id]; fn != nil; id++ {
}
dispatchCallbacks[id] = fn
dispatchCallbackLock.Unlock()
C.gtkDispatch(C.int(id))
}
var messageBuffer = make(chan string, 100)
//export processMessage
func processMessage(message *C.char) {
goMessage := C.GoString(message)
messageBuffer <- goMessage
}
// Map of functions passed to dispatch()
var dispatchCallbacks = make(map[int]func())
var dispatchCallbackLock sync.Mutex
//export callDispatchedMethod
func callDispatchedMethod(cid C.int) {
println("[callDispatchedMethod] PID:", os.Getpid())
id := int(cid)
fn := dispatchCallbacks[id]
if fn != nil {
fn()
dispatchCallbackLock.Lock()
delete(dispatchCallbacks, id)
dispatchCallbackLock.Unlock()
} else {
println("Error: No dispatch method with id", id, cid)
}
}
var requestBuffer = make(chan unsafe.Pointer, 100)
func (f *Frontend) startRequestProcessor() {
for request := range requestBuffer {
f.processRequest(request)
}
}
//export processURLRequest
func processURLRequest(request unsafe.Pointer) {
requestBuffer <- request
}
func (f *Frontend) processRequest(request unsafe.Pointer) {
req := (*C.WebKitURISchemeRequest)(request)
uri := C.webkit_uri_scheme_request_get_uri(req)
goURI := C.GoString(uri)
file, match, err := common.TranslateUriToFile(goURI, "wails", "")
if err != nil {
// TODO Handle errors
return
} else if !match {
// This should never happen on linux, because we get only called for wails://
panic("Unexpected host for request on wails:// scheme")
}
// Load file from asset store
content, mimeType, err := f.assets.Load(file)
// TODO How to return 404/500 errors to webkit?
if err != nil {
if os.IsNotExist(err) {
f.dispatch(func() {
message := C.CString("not found")
defer C.free(unsafe.Pointer(message))
C.webkit_uri_scheme_request_finish_error(req, C.g_error_new_literal(C.G_FILE_ERROR_NOENT, C.int(404), message))
})
} else {
err = fmt.Errorf("Error processing request %s: %w", uri, err)
f.logger.Error(err.Error())
message := C.CString("internal server error")
defer C.free(unsafe.Pointer(message))
C.webkit_uri_scheme_request_finish_error(req, C.g_error_new_literal(C.G_FILE_ERROR_NOENT, C.int(500), message))
}
return
}
cContent := C.CString(string(content))
defer C.free(unsafe.Pointer(cContent))
cMimeType := C.CString(mimeType)
defer C.free(unsafe.Pointer(cMimeType))
cLen := C.long(len(content))
stream := C.g_memory_input_stream_new_from_data(unsafe.Pointer(cContent), cLen, nil)
C.webkit_uri_scheme_request_finish(req, stream, cLen, cMimeType)
}

View File

@@ -0,0 +1,14 @@
//go:build linux
// +build linux
package linux
import "github.com/wailsapp/wails/v2/pkg/menu"
func (f *Frontend) MenuSetApplicationMenu(menu *menu.Menu) {
panic("implement me")
}
func (f *Frontend) MenuUpdateApplicationMenu() {
panic("implement me")
}

View File

@@ -0,0 +1,452 @@
//go:build linux
// +build linux
package linux
/*
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 x11
#include "gtk/gtk.h"
#include "webkit2/webkit2.h"
#include <X11/Xlib.h>
#include <stdio.h>
#include <limits.h>
static GtkWidget* GTKWIDGET(void *pointer) {
return GTK_WIDGET(pointer);
}
static GtkWindow* GTKWINDOW(void *pointer) {
return GTK_WINDOW(pointer);
}
static void SetMinSize(GtkWindow* window, int width, int height) {
GdkGeometry size;
size.min_height = height;
size.min_width = width;
gtk_window_set_geometry_hints(window, NULL, &size, GDK_HINT_MIN_SIZE);
}
static void SetMaxSize(GtkWindow* window, int width, int height) {
GdkGeometry size;
if( width == 0 ) {
width = INT_MAX;
}
if( height == 0 ) {
height = INT_MAX;
}
size.max_height = height;
size.max_width = width;
gtk_window_set_geometry_hints(window, NULL, &size, GDK_HINT_MAX_SIZE);
}
GdkRectangle getCurrentMonitorGeometry(GtkWindow *window) {
// Get the monitor that the window is currently on
GdkDisplay *display = gtk_widget_get_display(GTK_WIDGET(window));
GdkWindow *gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
GdkMonitor *monitor = gdk_display_get_monitor_at_window (display, gdk_window);
// Get the geometry of the monitor
GdkRectangle result;
gdk_monitor_get_geometry (monitor,&result);
return result;
}
void SetPosition(GtkWindow *window, int x, int y) {
GdkRectangle monitorDimensions = getCurrentMonitorGeometry(window);
gtk_window_move(window, monitorDimensions.x + x, monitorDimensions.y + y);
}
void Center(GtkWindow *window)
{
// Get the geometry of the monitor
GdkRectangle m = getCurrentMonitorGeometry(window);
// Get the window width/height
int windowWidth, windowHeight;
gtk_window_get_size(window, &windowWidth, &windowHeight);
int newX = ((m.width - windowWidth) / 2) + m.x;
int newY = ((m.height - windowHeight) / 2) + m.y;
// Place the window at the center of the monitor
gtk_window_move(window, newX, newY);
}
int IsFullscreen(GtkWidget *widget) {
GdkWindow *gdkwindow = gtk_widget_get_window(widget);
GdkWindowState state = gdk_window_get_state(GDK_WINDOW(gdkwindow));
return state & GDK_WINDOW_STATE_FULLSCREEN == GDK_WINDOW_STATE_FULLSCREEN;
}
extern void processMessage(char*);
static void sendMessageToBackend(WebKitUserContentManager *contentManager,
WebKitJavascriptResult *result,
void* data)
{
#if WEBKIT_MAJOR_VERSION >= 2 && WEBKIT_MINOR_VERSION >= 22
JSCValue *value = webkit_javascript_result_get_js_value(result);
char *message = jsc_value_to_string(value);
#else
JSGlobalContextRef context = webkit_javascript_result_get_global_context(result);
JSValueRef value = webkit_javascript_result_get_value(result);
JSStringRef js = JSValueToStringCopy(context, value, NULL);
size_t messageSize = JSStringGetMaximumUTF8CStringSize(js);
char *message = g_new(char, messageSize);
JSStringGetUTF8CString(js, message, messageSize);
JSStringRelease(js);
#endif
processMessage(message);
g_free(message);
}
ulong setupInvokeSignal(void* contentManager) {
return g_signal_connect((WebKitUserContentManager*)contentManager, "script-message-received::external", G_CALLBACK(sendMessageToBackend), NULL);
}
void initThreads() {
printf("init threads\n");
XInitThreads();
}
// These are the x,y & time of the last mouse down event
// It's used for window dragging
float xroot = 0.0f;
float yroot = 0.0f;
int dragTime = -1;
gboolean buttonPress(GtkWidget *widget, GdkEventButton *event, void* dummy)
{
if( event == NULL ) {
xroot = yroot = 0.0f;
dragTime = -1;
return FALSE;
}
if (event->type == GDK_BUTTON_PRESS && event->button == 1)
{
xroot = event->x_root;
yroot = event->y_root;
dragTime = event->time;
}
return FALSE;
}
gboolean buttonRelease(GtkWidget *widget, GdkEventButton *event, void* dummy)
{
if (event == NULL || (event->type == GDK_BUTTON_RELEASE && event->button == 1))
{
xroot = yroot = 0.0f;
dragTime = -1;
}
return FALSE;
}
void connectButtons(void* webview) {
g_signal_connect(WEBKIT_WEB_VIEW(webview), "button-press-event", G_CALLBACK(buttonPress), NULL);
g_signal_connect(WEBKIT_WEB_VIEW(webview), "button-release-event", G_CALLBACK(buttonRelease), NULL);
}
extern void processURLRequest(WebKitURISchemeRequest *request);
// This is called when the close button on the window is pressed
gboolean close_button_pressed(GtkWidget *widget, GdkEvent *event, void* data)
{
processMessage("Q");
return FALSE;
}
GtkWidget* setupWebview(void* contentManager, GtkWindow* window, int hideWindowOnClose) {
GtkWidget* webview = webkit_web_view_new_with_user_content_manager((WebKitUserContentManager*)contentManager);
gtk_container_add(GTK_CONTAINER(window), webview);
WebKitWebContext *context = webkit_web_context_get_default();
webkit_web_context_register_uri_scheme(context, "wails", (WebKitURISchemeRequestCallback)processURLRequest, NULL, NULL);
//g_signal_connect(G_OBJECT(webview), "load-changed", G_CALLBACK(webview_load_changed_cb), NULL);
if (hideWindowOnClose) {
g_signal_connect(GTK_WIDGET(window), "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL);
} else {
g_signal_connect(GTK_WIDGET(window), "delete-event", G_CALLBACK(close_button_pressed), NULL);
}
return webview;
}
void devtoolsEnabled(void* webview, int enabled) {
WebKitSettings *settings = webkit_web_view_get_settings(WEBKIT_WEB_VIEW(webview));
gboolean genabled = enabled == 1 ? true : false;
webkit_settings_set_enable_developer_extras(settings, genabled);
}
void loadIndex(void* webview) {
webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview), "wails:///");
}
static void startDrag(void *webview, GtkWindow* mainwindow)
{
// Ignore non-toplevel widgets
GtkWidget *window = gtk_widget_get_toplevel(GTK_WIDGET(webview));
if (!GTK_IS_WINDOW(window)) return;
gtk_window_begin_move_drag(mainwindow, 1, xroot, yroot, dragTime);
}
void extern processOpenFileResult(char*);
static void OpenDialog(GtkWindow* window, char *title) {
printf("Here\n");
GtkWidget *dlg = gtk_file_chooser_dialog_new(title, window, GTK_FILE_CHOOSER_ACTION_OPEN,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Open", GTK_RESPONSE_ACCEPT,
NULL);
printf("Here3\n");
gint response = gtk_dialog_run(GTK_DIALOG(dlg));
printf("Here 4\n");
if (response == GTK_RESPONSE_ACCEPT)
{
printf("Here 5\n");
gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dlg));
processOpenFileResult(filename);
g_free(filename);
}
gtk_widget_destroy(dlg);
}
*/
import "C"
import (
"github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/pkg/options"
"os"
"unsafe"
)
func gtkBool(input bool) C.gboolean {
if input {
return C.gboolean(1)
}
return C.gboolean(0)
}
type Window struct {
appoptions *options.App
debug bool
gtkWindow unsafe.Pointer
contentManager unsafe.Pointer
webview unsafe.Pointer
}
func bool2Cint(value bool) C.int {
if value {
return C.int(1)
}
return C.int(0)
}
func NewWindow(appoptions *options.App, debug bool) *Window {
result := &Window{
appoptions: appoptions,
debug: debug,
}
gtkWindow := C.gtk_window_new(C.GTK_WINDOW_TOPLEVEL)
C.g_object_ref_sink(C.gpointer(gtkWindow))
result.gtkWindow = unsafe.Pointer(gtkWindow)
result.contentManager = unsafe.Pointer(C.webkit_user_content_manager_new())
external := C.CString("external")
defer C.free(unsafe.Pointer(external))
C.webkit_user_content_manager_register_script_message_handler(result.cWebKitUserContentManager(), external)
C.setupInvokeSignal(result.contentManager)
webview := C.setupWebview(result.contentManager, result.asGTKWindow(), bool2Cint(appoptions.HideWindowOnClose))
result.webview = unsafe.Pointer(webview)
buttonPressedName := C.CString("button-press-event")
defer C.free(unsafe.Pointer(buttonPressedName))
C.connectButtons(unsafe.Pointer(webview))
if debug {
C.devtoolsEnabled(unsafe.Pointer(webview), C.int(1))
}
// Setup window
result.SetKeepAbove(appoptions.AlwaysOnTop)
result.SetResizable(!appoptions.DisableResize)
result.SetSize(appoptions.Width, appoptions.Height)
result.SetDecorated(!appoptions.Frameless)
result.SetTitle(appoptions.Title)
result.SetMinSize(appoptions.MinWidth, appoptions.MinHeight)
result.SetMaxSize(appoptions.MaxWidth, appoptions.MaxHeight)
return result
}
func (w *Window) asGTKWidget() *C.GtkWidget {
return C.GTKWIDGET(w.gtkWindow)
}
func (w *Window) asGTKWindow() *C.GtkWindow {
return C.GTKWINDOW(w.gtkWindow)
}
func (w *Window) cWebKitUserContentManager() *C.WebKitUserContentManager {
return (*C.WebKitUserContentManager)(w.contentManager)
}
func (w *Window) Fullscreen() {
C.gtk_window_fullscreen(w.asGTKWindow())
}
func (w *Window) UnFullscreen() {
C.gtk_window_unfullscreen(w.asGTKWindow())
}
func (w *Window) Destroy() {
C.g_object_unref(C.gpointer(w.gtkWindow))
C.gtk_widget_destroy(w.asGTKWidget())
}
func (w *Window) Close() {
C.gtk_window_close(w.asGTKWindow())
}
func (w *Window) Center() {
C.Center(w.asGTKWindow())
}
func (w *Window) SetPos(x int, y int) {
cX := C.int(x)
cY := C.int(y)
C.gtk_window_move(w.asGTKWindow(), cX, cY)
}
func (w *Window) Size() (int, int) {
var width, height C.int
C.gtk_window_get_size(w.asGTKWindow(), &width, &height)
return int(width), int(height)
}
func (w *Window) Pos() (int, int) {
var width, height C.int
C.gtk_window_get_position(w.asGTKWindow(), &width, &height)
return int(width), int(height)
}
func (w *Window) SetMaxSize(maxWidth int, maxHeight int) {
C.SetMaxSize(w.asGTKWindow(), C.int(maxWidth), C.int(maxHeight))
}
func (w *Window) SetMinSize(minWidth int, minHeight int) {
C.SetMinSize(w.asGTKWindow(), C.int(minWidth), C.int(minHeight))
}
func (w *Window) Show() {
C.gtk_widget_show(w.asGTKWidget())
}
func (w *Window) Hide() {
C.gtk_widget_hide(w.asGTKWidget())
}
func (w *Window) Maximise() {
C.gtk_window_maximize(w.asGTKWindow())
}
func (w *Window) UnMaximise() {
C.gtk_window_unmaximize(w.asGTKWindow())
}
func (w *Window) Minimise() {
C.gtk_window_iconify(w.asGTKWindow())
}
func (w *Window) UnMinimise() {
C.gtk_window_present(w.asGTKWindow())
}
func (w *Window) IsFullScreen() bool {
result := C.IsFullscreen(w.asGTKWidget())
if result == 1 {
return true
}
return false
}
func (w *Window) SetRGBA(r uint8, g uint8, b uint8, a uint8) {
//C.SetRGBA(w.context, C.int(r), C.int(g), C.int(b), C.int(a))
}
//func (w *Window) SetApplicationMenu(inMenu *menu.Menu) {
// //mainMenu := NewNSMenu(w.context, "")
// //processMenu(mainMenu, inMenu)
// //C.SetAsApplicationMenu(w.context, mainMenu.nsmenu)
//}
func (w *Window) UpdateApplicationMenu() {
//C.UpdateApplicationMenu(w.context)
}
func (w *Window) Run() {
C.loadIndex(w.webview)
C.gtk_widget_show_all(w.asGTKWidget())
w.Center()
switch w.appoptions.WindowStartState {
case options.Fullscreen:
w.Fullscreen()
case options.Minimised:
w.Minimise()
case options.Maximised:
w.Maximise()
}
C.initThreads()
C.gtk_main()
w.Destroy()
}
func (w *Window) SetKeepAbove(top bool) {
C.gtk_window_set_keep_above(w.asGTKWindow(), gtkBool(top))
}
func (w *Window) SetResizable(resizable bool) {
C.gtk_window_set_resizable(w.asGTKWindow(), gtkBool(resizable))
}
func (w *Window) SetSize(width int, height int) {
C.gtk_window_resize(w.asGTKWindow(), C.gint(width), C.gint(height))
}
func (w *Window) SetDecorated(frameless bool) {
C.gtk_window_set_decorated(w.asGTKWindow(), gtkBool(frameless))
}
func (w *Window) SetTitle(title string) {
cTitle := C.CString(title)
defer C.free(unsafe.Pointer(cTitle))
C.gtk_window_set_title(w.asGTKWindow(), cTitle)
}
func (w *Window) ExecJS(js string) {
script := C.CString(js)
defer C.free(unsafe.Pointer(script))
C.webkit_web_view_run_javascript((*C.WebKitWebView)(w.webview), script, nil, nil, nil)
}
func (w *Window) StartDrag() {
C.startDrag(w.webview, w.asGTKWindow())
}
func (w *Window) Quit() {
C.gtk_main_quit()
}
func (w *Window) OpenFileDialog(dialogOptions frontend.OpenDialogOptions) {
println("OpenFileDialog PID:", os.Getpid())
mem := NewCalloc()
title := mem.String(dialogOptions.Title)
C.OpenDialog(w.asGTKWindow(), title)
mem.Free()
}

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