Compare commits
139 Commits
930_-_defa
...
v1.16.9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81b3ecb056 | ||
|
|
b4d14644ee | ||
|
|
69fd584c32 | ||
|
|
3444ec50a7 | ||
|
|
02d4c65e01 | ||
|
|
efdcfe9985 | ||
|
|
5884b7a87c | ||
|
|
7229446ce7 | ||
|
|
c355d63768 | ||
|
|
eb0030adeb | ||
|
|
fe224d9ecd | ||
|
|
a98d55db58 | ||
|
|
f034163da5 | ||
|
|
d8fe011509 | ||
|
|
e7bb3b3e83 | ||
|
|
3201206d4f | ||
|
|
69c14d2a5d | ||
|
|
778cbe04d9 | ||
|
|
131a8f421d | ||
|
|
6fcd4b7bd4 | ||
|
|
f3b2f6ab76 | ||
|
|
b556e860c4 | ||
|
|
eb01a005dc | ||
|
|
6dcee51940 | ||
|
|
4c7a53b72b | ||
|
|
73c9fba731 | ||
|
|
0726ae9e83 | ||
|
|
9ba4ca10ca | ||
|
|
38caa645e5 | ||
|
|
41507e966a | ||
|
|
3092f04bcf | ||
|
|
ffc0765a2f | ||
|
|
ac803aa426 | ||
|
|
92b63d9fad | ||
|
|
fda3323386 | ||
|
|
b7a4aba5f3 | ||
|
|
7848a028e3 | ||
|
|
d827aafe89 | ||
|
|
db8094cd68 | ||
|
|
59d29dc12f | ||
|
|
7aad934dae | ||
|
|
0b1e33748a | ||
|
|
97be694d2a | ||
|
|
576e574399 | ||
|
|
6d9a195830 | ||
|
|
8107a8bd1e | ||
|
|
47d783291d | ||
|
|
0295f8dee2 | ||
|
|
d915f73c6c | ||
|
|
187bf3085c | ||
|
|
a353a653d1 | ||
|
|
155f1fde49 | ||
|
|
ec1a535acb | ||
|
|
fb5bcdc364 | ||
|
|
e6f42247e7 | ||
|
|
4bc0b30231 | ||
|
|
1cd2645b87 | ||
|
|
7904d0aadc | ||
|
|
06fa6850a1 | ||
|
|
485f5831ac | ||
|
|
587bcd8e21 | ||
|
|
d43b7b1882 | ||
|
|
ca147143ad | ||
|
|
3371967dad | ||
|
|
b09825ab0f | ||
|
|
5edf45468c | ||
|
|
507e8d5222 | ||
|
|
b9283009df | ||
|
|
60ddaf449d | ||
|
|
5bad81e182 | ||
|
|
2e15f22621 | ||
|
|
6a3a822640 | ||
|
|
e5057e1627 | ||
|
|
0a8f720586 | ||
|
|
5dbfb447b1 | ||
|
|
1f21dfbcfd | ||
|
|
53481830a9 | ||
|
|
7eb8e6456e | ||
|
|
5f0352404b | ||
|
|
b036b8c547 | ||
|
|
39ca977b18 | ||
|
|
abc078fb1b | ||
|
|
166490845c | ||
|
|
c2399e3620 | ||
|
|
a2890b6d0d | ||
|
|
a1dee989c7 | ||
|
|
6ff1dac925 | ||
|
|
0b011929bf | ||
|
|
be3d1ff9e1 | ||
|
|
9c73b7285f | ||
|
|
810793aba7 | ||
|
|
ef8d7d2fd7 | ||
|
|
ae341be638 | ||
|
|
dcef8679d2 | ||
|
|
0bb09a53ea | ||
|
|
deb1156916 | ||
|
|
1d87a81f63 | ||
|
|
8ef8b2528b | ||
|
|
f05109232e | ||
|
|
cf1001bffc | ||
|
|
7bf2218c36 | ||
|
|
48c9879bc4 | ||
|
|
2fe5e5ed01 | ||
|
|
38fd09bd9a | ||
|
|
4c5a81782b | ||
|
|
ace3122e07 | ||
|
|
f5c35487d9 | ||
|
|
06df0e1ee4 | ||
|
|
9735bd1b01 | ||
|
|
cd8bad58cd | ||
|
|
53a3cd9422 | ||
|
|
5e2f25af9b | ||
|
|
865d118651 | ||
|
|
6ea6bfeed0 | ||
|
|
48527eb90a | ||
|
|
33d8f98da9 | ||
|
|
658a30d16a | ||
|
|
0189d1cb55 | ||
|
|
8df94fa02b | ||
|
|
f5f89c31eb | ||
|
|
46cb34f2ec | ||
|
|
f6f13540c8 | ||
|
|
21ce7709ab | ||
|
|
d569e37b81 | ||
|
|
c9c6edeb84 | ||
|
|
9525667ebd | ||
|
|
28a3d86348 | ||
|
|
fc8aa58e62 | ||
|
|
cb2bbacae8 | ||
|
|
c3c6261a2d | ||
|
|
8bfec24108 | ||
|
|
9ad2665ad8 | ||
|
|
28894868e3 | ||
|
|
a8fcd994c9 | ||
|
|
3a93c08813 | ||
|
|
ab1469638f | ||
|
|
9073caf287 | ||
|
|
1bed8234c9 | ||
|
|
621c70253d |
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -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!
|
Please use the `wails issue` command!
|
||||||
If you do not do this then the issue may be closed automatically.
|
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.
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
**System Details**
|
**System Details**
|
||||||
Please provide your platform, GO version and variables, etc
|
V2 users: Please add the output of `wails doctor`.
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
Add any other context about the problem here.
|
Add any other context about the problem here.
|
||||||
|
|||||||
74
README.md
@@ -1,17 +1,35 @@
|
|||||||
<p align="center" style="text-align: center">
|
<p align="center" style="text-align: center">
|
||||||
<img src="logo.png" width="55%"><br/>
|
<img src="logo.png" width="55%"><br/>
|
||||||
</p>
|
</p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
Build desktop applications using Go & Web Technologies.<br/><br/>
|
Build desktop applications using Go & Web Technologies.<br/><br/>
|
||||||
<a href="https://github.com/wailsapp/wails/blob/master/LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg"></a>
|
<a href="https://github.com/wailsapp/wails/blob/master/LICENSE">
|
||||||
<a href="https://goreportcard.com/report/github.com/wailsapp/wails"><img src="https://goreportcard.com/badge/github.com/wailsapp/wails"/></a>
|
<img src="https://img.shields.io/badge/License-MIT-blue.svg">
|
||||||
<a href="http://godoc.org/github.com/wailsapp/wails"><img src="https://img.shields.io/badge/godoc-reference-blue.svg"/></a>
|
</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://goreportcard.com/report/github.com/wailsapp/wails">
|
||||||
<a href="https://github.com/wailsapp/wails/issues"><img src="https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat" alt="CodeFactor" /></a>
|
<img src="https://goreportcard.com/badge/github.com/wailsapp/wails"/>
|
||||||
<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>
|
||||||
<a href="https://houndci.com"><img src="https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg"/></a>
|
<a href="http://godoc.org/github.com/wailsapp/wails">
|
||||||
<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>
|
<img src="https://img.shields.io/badge/godoc-reference-blue.svg"/>
|
||||||
<a href="https://github.com/wailsapp/wails/workflows/release/badge.svg?branch=master" rel="nofollow"><img src="https://github.com/wailsapp/wails/workflows/release/badge.svg?branch=master" alt="Release Pipelines"></a>
|
</a>
|
||||||
|
<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>
|
</p>
|
||||||
|
|
||||||
<span id="nav-1"></span>
|
<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:
|
This project is supported by these kind people / companies:
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://www.easywebadv.it/" style="width:100px;">
|
||||||
|
<img src="website/static/img/easyweb.png" width="100"/>
|
||||||
|
</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;">
|
<a href="https://github.com/sponsors/leaanthony" style="width:100px;">
|
||||||
<img src="sponsors/bronze%20sponsor.png" width="100"/>
|
<img src="sponsors/bronze%20sponsor.png" width="100"/>
|
||||||
</a>
|
</a>
|
||||||
@@ -106,7 +139,7 @@ This project is supported by these kind people / companies:
|
|||||||
<img src="https://github.com/matryer.png" width="100"/>
|
<img src="https://github.com/matryer.png" width="100"/>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://www.jetbrains.com?from=Wails" style="width:100px">
|
<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>
|
||||||
<a href="https://github.com/tc-hib" style="width:55px">
|
<a href="https://github.com/tc-hib" style="width:55px">
|
||||||
<img src="https://github.com/tc-hib.png?size=55" width="55"/>
|
<img src="https://github.com/tc-hib.png?size=55" width="55"/>
|
||||||
@@ -159,6 +192,9 @@ This project is supported by these kind people / companies:
|
|||||||
<a href="https://github.com/DonTomato" style="width:45px">
|
<a href="https://github.com/DonTomato" style="width:45px">
|
||||||
<img src="https://github.com/DonTomato.png?size=45" width="45"/>
|
<img src="https://github.com/DonTomato.png?size=45" width="45"/>
|
||||||
</a>
|
</a>
|
||||||
|
<a href="https://github.com/taigrr" style="width:45px">
|
||||||
|
<img src="https://github.com/taigrr.png?size=45" width="45"/>
|
||||||
|
</a>
|
||||||
|
|
||||||
<span id="nav-6"></span>
|
<span id="nav-6"></span>
|
||||||
|
|
||||||
@@ -322,11 +358,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/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/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/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/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>
|
<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>
|
<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>
|
<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></a>
|
<a href="https://github.com/s12chung"><img src="https://github.com/s12chung.png?size=40" width="40"/></a>
|
||||||
|
|
||||||
<span id="nav-10"></span>
|
<span id="nav-10"></span>
|
||||||
|
|
||||||
@@ -362,7 +398,7 @@ This project was mainly coded to the following albums:
|
|||||||
## Special Thanks
|
## Special Thanks
|
||||||
|
|
||||||
<p align="center" style="text-align: center">
|
<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/>
|
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/>
|
If you are looking for a Project Management tool that's powerful but quick and easy to use, check them out!<br/><br/>
|
||||||
</p>
|
</p>
|
||||||
@@ -370,5 +406,5 @@ This project was mainly coded to the following albums:
|
|||||||
<p align="center" style="text-align: center">
|
<p align="center" style="text-align: center">
|
||||||
A special thank you to JetBrains for donating licenses to us!<br/><br/>
|
A special thank you to JetBrains for donating licenses to us!<br/><br/>
|
||||||
Please click the logo to let them know your appreciation!<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>
|
</p>
|
||||||
|
|||||||
@@ -2,16 +2,34 @@
|
|||||||
<img src="logo.png" width="55%"><br/>
|
<img src="logo.png" width="55%"><br/>
|
||||||
</p>
|
</p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
使用 Go 和 Web 技术构建桌面应用程序。<br/><br/>
|
使用 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://github.com/wailsapp/wails/blob/master/LICENSE">
|
||||||
<a href="https://goreportcard.com/report/github.com/wailsapp/wails"><img src="https://goreportcard.com/badge/github.com/wailsapp/wails"/></a>
|
<img src="https://img.shields.io/badge/License-MIT-blue.svg">
|
||||||
<a href="http://godoc.org/github.com/wailsapp/wails"><img src="https://img.shields.io/badge/godoc-reference-blue.svg"/></a>
|
</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://goreportcard.com/report/github.com/wailsapp/wails">
|
||||||
<a href="https://github.com/wailsapp/wails/issues"><img src="https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat" alt="CodeFactor" /></a>
|
<img src="https://goreportcard.com/badge/github.com/wailsapp/wails"/>
|
||||||
<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>
|
||||||
<a href="https://houndci.com"><img src="https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg"/></a>
|
<a href="http://godoc.org/github.com/wailsapp/wails">
|
||||||
<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>
|
<img src="https://img.shields.io/badge/godoc-reference-blue.svg"/>
|
||||||
<a href="https://github.com/wailsapp/wails/workflows/release/badge.svg?branch=master" rel="nofollow"><img src="https://github.com/wailsapp/wails/workflows/release/badge.svg?branch=master" alt="Release Pipelines"></a>
|
</a>
|
||||||
|
<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>
|
</p>
|
||||||
|
|
||||||
<span id="nav-1"></span>
|
<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="100"/>
|
||||||
|
</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;">
|
<a href="https://github.com/sponsors/leaanthony" style="width:100px;">
|
||||||
<img src="sponsors/bronze%20sponsor.png" width="100"/>
|
<img src="sponsors/bronze%20sponsor.png" width="100"/>
|
||||||
</a>
|
</a>
|
||||||
@@ -109,7 +142,7 @@
|
|||||||
<img src="https://github.com/matryer.png" width="100"/>
|
<img src="https://github.com/matryer.png" width="100"/>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://www.jetbrains.com?from=Wails" style="width:100px">
|
<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>
|
||||||
<a href="https://github.com/tc-hib" style="width:55px">
|
<a href="https://github.com/tc-hib" style="width:55px">
|
||||||
<img src="https://github.com/tc-hib.png?size=55" width="55"/>
|
<img src="https://github.com/tc-hib.png?size=55" width="55"/>
|
||||||
@@ -162,6 +195,9 @@
|
|||||||
<a href="https://github.com/DonTomato" style="width:45px">
|
<a href="https://github.com/DonTomato" style="width:45px">
|
||||||
<img src="https://github.com/DonTomato.png?size=45" width="45"/>
|
<img src="https://github.com/DonTomato.png?size=45" width="45"/>
|
||||||
</a>
|
</a>
|
||||||
|
<a href="https://github.com/taigrr" style="width:45px">
|
||||||
|
<img src="https://github.com/taigrr.png?size=45" width="45"/>
|
||||||
|
</a>
|
||||||
|
|
||||||
<span id="nav-6"></span>
|
<span id="nav-6"></span>
|
||||||
|
|
||||||
@@ -318,11 +354,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/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/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/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/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>
|
<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>
|
<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>
|
<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></a>
|
<a href="https://github.com/s12chung"><img src="https://github.com/s12chung.png?size=40" width="40"/></a>
|
||||||
|
|
||||||
<span id="nav-10"></span>
|
<span id="nav-10"></span>
|
||||||
|
|
||||||
@@ -355,7 +391,7 @@ go get -u github.com/wailsapp/wails/cmd/wails
|
|||||||
## 特别感谢
|
## 特别感谢
|
||||||
|
|
||||||
<p align="center" style="text-align: center">
|
<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/>
|
<i>非常</i> 感谢<a href="https://pace.dev">Pace</a>对项目的赞助,并帮助将 Wails 移植到 Apple Silicon !<br/><br/>
|
||||||
如果您正在寻找一个强大并且快速和易于使用的项目管理工具,可以看看他们!<br/><br/>
|
如果您正在寻找一个强大并且快速和易于使用的项目管理工具,可以看看他们!<br/><br/>
|
||||||
</p>
|
</p>
|
||||||
@@ -363,5 +399,5 @@ go get -u github.com/wailsapp/wails/cmd/wails
|
|||||||
<p align="center" style="text-align: center">
|
<p align="center" style="text-align: center">
|
||||||
特别感谢 JetBrains 向我们捐赠许可!<br/><br/>
|
特别感谢 JetBrains 向我们捐赠许可!<br/><br/>
|
||||||
请点击 logo 让他们知道你的感激之情!<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>
|
</p>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 103 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
13
cmd/fs.go
@@ -6,7 +6,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
@@ -50,7 +49,7 @@ func (fs *FSHelper) FileExists(path string) bool {
|
|||||||
|
|
||||||
// FindFile returns the first occurrence of match inside path.
|
// FindFile returns the first occurrence of match inside path.
|
||||||
func (fs *FSHelper) FindFile(path, match string) (string, error) {
|
func (fs *FSHelper) FindFile(path, match string) (string, error) {
|
||||||
files, err := ioutil.ReadDir(path)
|
files, err := os.ReadDir(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -69,7 +68,7 @@ func (fs *FSHelper) FindFile(path, match string) (string, error) {
|
|||||||
func (fs *FSHelper) CreateFile(filename string, data []byte) error {
|
func (fs *FSHelper) CreateFile(filename string, data []byte) error {
|
||||||
// Ensure directory exists
|
// Ensure directory exists
|
||||||
fs.MkDirs(filepath.Dir(filename))
|
fs.MkDirs(filepath.Dir(filename))
|
||||||
return ioutil.WriteFile(filename, data, 0644)
|
return os.WriteFile(filename, data, 0644)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MkDirs creates the given nested directories.
|
// MkDirs creates the given nested directories.
|
||||||
@@ -156,14 +155,14 @@ func (fs *FSHelper) LoadRelativeFile(relativePath string) ([]byte, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return ioutil.ReadFile(fullPath)
|
return os.ReadFile(fullPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSubdirs will return a list of FQPs to subdirectories in the given directory
|
// GetSubdirs will return a list of FQPs to subdirectories in the given directory
|
||||||
func (d *Dir) GetSubdirs() (map[string]string, error) {
|
func (d *Dir) GetSubdirs() (map[string]string, error) {
|
||||||
|
|
||||||
// Read in the directory information
|
// Read in the directory information
|
||||||
fileInfo, err := ioutil.ReadDir(d.fullPath)
|
fileInfo, err := os.ReadDir(d.fullPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -215,7 +214,7 @@ func (fs *FSHelper) SaveAsJSON(data interface{}, filename string) error {
|
|||||||
e.SetIndent("", " ")
|
e.SetIndent("", " ")
|
||||||
e.Encode(data)
|
e.Encode(data)
|
||||||
|
|
||||||
err := ioutil.WriteFile(filename, buf.Bytes(), 0755)
|
err := os.WriteFile(filename, buf.Bytes(), 0755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -231,7 +230,7 @@ func (fs *FSHelper) LoadAsString(filename string) (string, error) {
|
|||||||
|
|
||||||
// LoadAsBytes returns the contents of the file as a byte slice
|
// LoadAsBytes returns the contents of the file as a byte slice
|
||||||
func (fs *FSHelper) LoadAsBytes(filename string) ([]byte, error) {
|
func (fs *FSHelper) LoadAsBytes(filename string) ([]byte, error) {
|
||||||
return ioutil.ReadFile(filename)
|
return os.ReadFile(filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileMD5 returns the md5sum of the given file
|
// FileMD5 returns the md5sum of the given file
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
)
|
)
|
||||||
@@ -28,7 +28,7 @@ func (g *GitHubHelper) GetVersionTags() ([]*SemanticVersion, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
@@ -75,7 +74,6 @@ const (
|
|||||||
NixOS
|
NixOS
|
||||||
// Artix linux distribution
|
// Artix linux distribution
|
||||||
ArtixLinux
|
ArtixLinux
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// DistroInfo contains all the information relating to a linux distribution
|
// DistroInfo contains all the information relating to a linux distribution
|
||||||
@@ -96,7 +94,7 @@ func GetLinuxDistroInfo() *DistroInfo {
|
|||||||
}
|
}
|
||||||
_, err := os.Stat("/etc/os-release")
|
_, err := os.Stat("/etc/os-release")
|
||||||
if !os.IsNotExist(err) {
|
if !os.IsNotExist(err) {
|
||||||
osRelease, _ := ioutil.ReadFile("/etc/os-release")
|
osRelease, _ := os.ReadFile("/etc/os-release")
|
||||||
result = parseOsRelease(string(osRelease))
|
result = parseOsRelease(string(osRelease))
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"image/png"
|
"image/png"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -244,7 +243,7 @@ func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
|
|||||||
// No - create a new plist from our defaults
|
// No - create a new plist from our defaults
|
||||||
tmpl := template.New("infoPlist")
|
tmpl := template.New("infoPlist")
|
||||||
plistFile := filepath.Join(b.getPackageFileBaseDir(), "info.plist")
|
plistFile := filepath.Join(b.getPackageFileBaseDir(), "info.plist")
|
||||||
infoPlist, err := ioutil.ReadFile(plistFile)
|
infoPlist, err := os.ReadFile(plistFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -258,13 +257,13 @@ func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save to the package
|
// Save to the package
|
||||||
err = ioutil.WriteFile(plistFilename, tpl.Bytes(), 0644)
|
err = os.WriteFile(plistFilename, tpl.Bytes(), 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also write to project directory for customisation
|
// Also write to project directory for customisation
|
||||||
err = ioutil.WriteFile(customPlist, tpl.Bytes(), 0644)
|
err = os.WriteFile(customPlist, tpl.Bytes(), 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -314,10 +313,12 @@ func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate icon from PNG
|
// Generate icon from PNG if it doesn't exist
|
||||||
err = generateWindowsIcon(icon, basename+".ico")
|
if !fs.FileExists(basename + ".ico") {
|
||||||
if err != nil {
|
err = generateWindowsIcon(icon, basename+".ico")
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy manifest
|
// Copy manifest
|
||||||
@@ -334,12 +335,12 @@ func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
|
|||||||
tgtRCFile := filepath.Join(outputDir, basename+".rc")
|
tgtRCFile := filepath.Join(outputDir, basename+".rc")
|
||||||
if !b.fs.FileExists(tgtRCFile) {
|
if !b.fs.FileExists(tgtRCFile) {
|
||||||
srcRCfile := filepath.Join(b.getPackageFileBaseDir(), "wails.rc")
|
srcRCfile := filepath.Join(b.getPackageFileBaseDir(), "wails.rc")
|
||||||
rcfilebytes, err := ioutil.ReadFile(srcRCfile)
|
rcfilebytes, err := os.ReadFile(srcRCfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
rcfiledata := strings.Replace(string(rcfilebytes), "$NAME$", basename, -1)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -387,11 +388,11 @@ func (b *PackageHelper) copyIcon() (string, error) {
|
|||||||
|
|
||||||
// Install default icon
|
// Install default icon
|
||||||
iconfile := filepath.Join(b.getPackageFileBaseDir(), "icon.png")
|
iconfile := filepath.Join(b.getPackageFileBaseDir(), "icon.png")
|
||||||
iconData, err := ioutil.ReadFile(iconfile)
|
iconData, err := os.ReadFile(iconfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
err = ioutil.WriteFile(srcIcon, iconData, 0644)
|
err = os.WriteFile(srcIcon, iconData, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
@@ -310,14 +309,14 @@ func (po *ProjectOptions) WriteProjectConfig() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ioutil.WriteFile(targetFile, filedata, 0600)
|
return os.WriteFile(targetFile, filedata, 0600)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadConfig loads the project configuration file from the
|
// LoadConfig loads the project configuration file from the
|
||||||
// given directory
|
// given directory
|
||||||
func (po *ProjectOptions) LoadConfig(projectDir string) error {
|
func (po *ProjectOptions) LoadConfig(projectDir string) error {
|
||||||
targetFile := filepath.Join(projectDir, "project.json")
|
targetFile := filepath.Join(projectDir, "project.json")
|
||||||
rawBytes, err := ioutil.ReadFile(targetFile)
|
rawBytes, err := os.ReadFile(targetFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -124,7 +123,7 @@ func (s *SystemHelper) setup() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = ioutil.WriteFile(s.wailsSystemConfig, configData, 0755)
|
err = os.WriteFile(s.wailsSystemConfig, configData, 0755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -207,11 +206,11 @@ func (sc *SystemConfig) Save(filename string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write it out to the config file
|
// 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 {
|
func (sc *SystemConfig) load(filename string) error {
|
||||||
configData, err := ioutil.ReadFile(filename)
|
configData, err := os.ReadFile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -125,7 +125,7 @@ func (t *TemplateHelper) LoadMetadata(dir string) (*TemplateMetadata, error) {
|
|||||||
if !t.fs.FileExists(templateFile) {
|
if !t.fs.FileExists(templateFile) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
rawJSON, err := ioutil.ReadFile(templateFile)
|
rawJSON, err := os.ReadFile(templateFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
// Version - Wails version
|
// Version - Wails version
|
||||||
const Version = "v1.16.8"
|
const Version = "v1.16.9"
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -305,7 +304,7 @@ func updateWailsVersion(currentVersion, latestVersion *semver.Version) error {
|
|||||||
new := fmt.Sprintf("%s v%s", wailsModule, latestVersion)
|
new := fmt.Sprintf("%s v%s", wailsModule, latestVersion)
|
||||||
|
|
||||||
goMod = strings.Replace(goMod, old, new, -1)
|
goMod = strings.Replace(goMod, old, new, -1)
|
||||||
err := ioutil.WriteFile(goModFile, []byte(goMod), 0600)
|
err := os.WriteFile(goModFile, []byte(goMod), 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
checkSpinner.Error()
|
checkSpinner.Error()
|
||||||
return err
|
return err
|
||||||
@@ -343,7 +342,7 @@ func patchMainJS() error {
|
|||||||
newStartLine := `Wails.Init`
|
newStartLine := `Wails.Init`
|
||||||
mainJSContents = strings.Replace(mainJSContents, oldStartLine, newStartLine, -1)
|
mainJSContents = strings.Replace(mainJSContents, oldStartLine, newStartLine, -1)
|
||||||
|
|
||||||
err := ioutil.WriteFile(mainJSFile, []byte(mainJSContents), 0600)
|
err := os.WriteFile(mainJSFile, []byte(mainJSContents), 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
checkSpinner.Error()
|
checkSpinner.Error()
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
@@ -112,7 +112,7 @@ To help you in this process, we will ask for some information, add Go/Wails deta
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
template, _ := ioutil.ReadAll(resp.Body)
|
template, _ := io.ReadAll(resp.Body)
|
||||||
body := string(template)
|
body := string(template)
|
||||||
body = "**Description**\n" + (strings.Split(body, "**Description**")[1])
|
body = "**Description**\n" + (strings.Split(body, "**Description**")[1])
|
||||||
fullURL := "https://github.com/wailsapp/wails/issues/new?"
|
fullURL := "https://github.com/wailsapp/wails/issues/new?"
|
||||||
|
|||||||
2
go.mod
@@ -8,7 +8,6 @@ require (
|
|||||||
github.com/gorilla/websocket v1.4.1
|
github.com/gorilla/websocket v1.4.1
|
||||||
github.com/jackmordaunt/icns v1.0.0
|
github.com/jackmordaunt/icns v1.0.0
|
||||||
github.com/kennygrant/sanitize v1.2.4
|
github.com/kennygrant/sanitize v1.2.4
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
|
|
||||||
github.com/leaanthony/slicer v1.4.0
|
github.com/leaanthony/slicer v1.4.0
|
||||||
github.com/leaanthony/spinner v0.5.3
|
github.com/leaanthony/spinner v0.5.3
|
||||||
github.com/mattn/go-colorable v0.1.1 // indirect
|
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/browser v0.0.0-20180916011732-0a3d74bf9ce4
|
||||||
github.com/pkg/errors v0.8.1 // indirect
|
github.com/pkg/errors v0.8.1 // indirect
|
||||||
github.com/sirupsen/logrus v1.8.1
|
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/stretchr/testify v1.3.0 // indirect
|
||||||
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba
|
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba
|
||||||
golang.org/x/image v0.0.0-20200430140353-33d19683fad8
|
golang.org/x/image v0.0.0-20200430140353-33d19683fad8
|
||||||
|
|||||||
9
go.sum
@@ -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/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||||
github.com/kennygrant/sanitize v1.2.4 h1:gN25/otpP5vAsO2djbMhF/LQX6R7+O1TB4yv8NzpJ3o=
|
github.com/kennygrant/sanitize v1.2.4 h1:gN25/otpP5vAsO2djbMhF/LQX6R7+O1TB4yv8NzpJ3o=
|
||||||
github.com/kennygrant/sanitize v1.2.4/go.mod h1:LGsjYYtgxbetdg5owWB2mpgUL6e2nfw2eObZ0u0qvak=
|
github.com/kennygrant/sanitize v1.2.4/go.mod h1:LGsjYYtgxbetdg5owWB2mpgUL6e2nfw2eObZ0u0qvak=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/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 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/leaanthony/slicer v1.4.0 h1:Q9u4w+UBU4WHjXnEDdz+eRLMKF/rnyosRBiqULnc1J8=
|
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/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
|
|
||||||
github.com/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 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
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.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.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
@@ -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 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
|
||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
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-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-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/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-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 h1:2B5p2L5IfGiD7+b9BOoRMC6DgObAVZV+Fsp050NqXik=
|
||||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package binding
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
@@ -144,7 +143,7 @@ export {};`
|
|||||||
|
|
||||||
dir := filepath.Dir(typescriptDefinitionFilename)
|
dir := filepath.Dir(typescriptDefinitionFilename)
|
||||||
os.MkdirAll(dir, 0755)
|
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
|
// bind the given struct method
|
||||||
|
|||||||
@@ -55,20 +55,20 @@ func (e *Manager) addEventListener(eventName string, callback func(...interface{
|
|||||||
return fmt.Errorf("nil callback bassed to addEventListener")
|
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
|
// Create the callback
|
||||||
listener := &eventListener{
|
listener := &eventListener{
|
||||||
callback: callback,
|
callback: callback,
|
||||||
counter: counter,
|
counter: counter,
|
||||||
}
|
}
|
||||||
|
e.mu.Lock()
|
||||||
|
// Check event has been registered before
|
||||||
|
if e.listeners[eventName] == nil {
|
||||||
|
e.listeners[eventName] = []*eventListener{}
|
||||||
|
}
|
||||||
|
|
||||||
// Register listener
|
// Register listener
|
||||||
e.listeners[eventName] = append(e.listeners[eventName], listener)
|
e.listeners[eventName] = append(e.listeners[eventName], listener)
|
||||||
|
e.mu.Unlock()
|
||||||
// All good mate
|
// All good mate
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
sponsors/silver sponsor.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
@@ -99,11 +99,12 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
|||||||
"darwin/amd64",
|
"darwin/amd64",
|
||||||
"darwin/arm64",
|
"darwin/arm64",
|
||||||
"darwin/universal",
|
"darwin/universal",
|
||||||
//"linux",
|
"linux",
|
||||||
//"linux/amd64",
|
//"linux/amd64",
|
||||||
//"linux/arm-7",
|
//"linux/arm-7",
|
||||||
"windows",
|
"windows",
|
||||||
"windows/amd64",
|
"windows/amd64",
|
||||||
|
"windows/arm64",
|
||||||
})
|
})
|
||||||
if !validPlatformArch.Contains(platform) {
|
if !validPlatformArch.Contains(platform) {
|
||||||
return fmt.Errorf("platform %s is not supported. Platforms supported: %s", platform, validPlatformArch.Join(","))
|
return fmt.Errorf("platform %s is not supported. Platforms supported: %s", platform, validPlatformArch.Join(","))
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ type devFlags struct {
|
|||||||
compilerCommand string
|
compilerCommand string
|
||||||
assetDir string
|
assetDir string
|
||||||
extensions string
|
extensions string
|
||||||
|
reloadDirs string
|
||||||
openBrowser bool
|
openBrowser bool
|
||||||
noReload bool
|
noReload bool
|
||||||
wailsjsdir string
|
wailsjsdir string
|
||||||
@@ -83,8 +84,9 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
|||||||
flags := defaultDevFlags()
|
flags := defaultDevFlags()
|
||||||
command.StringFlag("ldflags", "optional ldflags", &flags.ldflags)
|
command.StringFlag("ldflags", "optional ldflags", &flags.ldflags)
|
||||||
command.StringFlag("compiler", "Use a different go compiler to build, eg go1.15beta1", &flags.compilerCommand)
|
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("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("browser", "Open application in browser", &flags.openBrowser)
|
||||||
command.BoolFlag("noreload", "Disable reload on asset change", &flags.noReload)
|
command.BoolFlag("noreload", "Disable reload on asset change", &flags.noReload)
|
||||||
command.StringFlag("wailsjsdir", "Directory to generate the Wails JS modules", &flags.wailsjsdir)
|
command.StringFlag("wailsjsdir", "Directory to generate the Wails JS modules", &flags.wailsjsdir)
|
||||||
@@ -278,7 +280,7 @@ func generateBuildOptions(flags devFlags) *build.Options {
|
|||||||
OutputType: "dev",
|
OutputType: "dev",
|
||||||
Mode: build.Dev,
|
Mode: build.Dev,
|
||||||
Arch: runtime.GOARCH,
|
Arch: runtime.GOARCH,
|
||||||
Pack: false,
|
Pack: true,
|
||||||
Platform: runtime.GOOS,
|
Platform: runtime.GOOS,
|
||||||
LDFlags: flags.ldflags,
|
LDFlags: flags.ldflags,
|
||||||
Compiler: flags.compilerCommand,
|
Compiler: flags.compilerCommand,
|
||||||
@@ -287,10 +289,7 @@ func generateBuildOptions(flags devFlags) *build.Options {
|
|||||||
Verbosity: flags.verbosity,
|
Verbosity: flags.verbosity,
|
||||||
WailsJSDir: flags.wailsjsdir,
|
WailsJSDir: flags.wailsjsdir,
|
||||||
}
|
}
|
||||||
switch runtime.GOOS {
|
|
||||||
case "darwin":
|
|
||||||
result.Pack = false
|
|
||||||
}
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,21 +303,29 @@ func loadAndMergeProjectConfig(cwd string, flags *devFlags) (*project.Project, e
|
|||||||
|
|
||||||
var shouldSaveConfig bool
|
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 != "" {
|
if flags.assetDir == "" && projectConfig.AssetDirectory != "" {
|
||||||
flags.assetDir = projectConfig.AssetDirectory
|
flags.assetDir = projectConfig.AssetDirectory
|
||||||
}
|
}
|
||||||
|
|
||||||
if flags.assetDir != projectConfig.AssetDirectory {
|
if flags.assetDir != projectConfig.AssetDirectory {
|
||||||
projectConfig.AssetDirectory = filepath.ToSlash(flags.assetDir)
|
projectConfig.AssetDirectory = filepath.ToSlash(flags.assetDir)
|
||||||
|
shouldSaveConfig = true
|
||||||
}
|
}
|
||||||
|
|
||||||
flags.assetDir, err = filepath.Abs(flags.assetDir)
|
if flags.assetDir != "" {
|
||||||
if err != nil {
|
flags.assetDir, err = filepath.Abs(flags.assetDir)
|
||||||
return nil, err
|
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 != "" {
|
if flags.devServerURL == defaultDevServerURL && projectConfig.DevServerURL != defaultDevServerURL && projectConfig.DevServerURL != "" {
|
||||||
@@ -506,11 +513,26 @@ func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Proc
|
|||||||
newBinaryProcess *process.Process
|
newBinaryProcess *process.Process
|
||||||
)
|
)
|
||||||
var extensionsThatTriggerARebuild = sliceToMap(strings.Split(flags.extensions, ","))
|
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
|
quit := false
|
||||||
interval := time.Duration(flags.debounceMS) * time.Millisecond
|
interval := time.Duration(flags.debounceMS) * time.Millisecond
|
||||||
timer := time.NewTimer(interval)
|
timer := time.NewTimer(interval)
|
||||||
rebuild := false
|
rebuild := false
|
||||||
reload := false
|
reload := false
|
||||||
|
assetDir := ""
|
||||||
|
changedPaths := map[string]struct{}{}
|
||||||
for quit == false {
|
for quit == false {
|
||||||
//reload := false
|
//reload := false
|
||||||
select {
|
select {
|
||||||
@@ -522,12 +544,13 @@ func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Proc
|
|||||||
// Check for file writes
|
// Check for file writes
|
||||||
if item.Op&fsnotify.Write == fsnotify.Write {
|
if item.Op&fsnotify.Write == fsnotify.Write {
|
||||||
// Ignore directories
|
// Ignore directories
|
||||||
if fs.DirExists(item.Name) {
|
itemName := item.Name
|
||||||
|
if fs.DirExists(itemName) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate all file patterns
|
// Iterate all file patterns
|
||||||
ext := filepath.Ext(item.Name)
|
ext := filepath.Ext(itemName)
|
||||||
if ext != "" {
|
if ext != "" {
|
||||||
ext = ext[1:]
|
ext = ext[1:]
|
||||||
if _, exists := extensionsThatTriggerARebuild[ext]; exists {
|
if _, exists := extensionsThatTriggerARebuild[ext]; exists {
|
||||||
@@ -537,9 +560,17 @@ func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Proc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(item.Name, flags.assetDir) {
|
for _, reloadDir := range dirsThatTriggerAReload {
|
||||||
reload = true
|
if strings.HasPrefix(itemName, reloadDir) {
|
||||||
|
reload = true
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !reload {
|
||||||
|
changedPaths[filepath.Dir(itemName)] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
timer.Reset(interval)
|
timer.Reset(interval)
|
||||||
}
|
}
|
||||||
// Check for new directories
|
// Check for new directories
|
||||||
@@ -571,6 +602,35 @@ func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Proc
|
|||||||
debugBinaryProcess = newBinaryProcess
|
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 {
|
if reload {
|
||||||
reload = false
|
reload = false
|
||||||
_, err = http.Get("http://localhost:34115/wails/reload")
|
_, err = http.Get("http://localhost:34115/wails/reload")
|
||||||
|
|||||||
@@ -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.
|
- 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`.
|
2. Update `README.md`.
|
||||||
3. Edit `wails.json` and ensure all fields are correct, especially:
|
3. Edit `wails.json` and ensure all fields are correct, especially:
|
||||||
- `assetdir` - path to your assets
|
|
||||||
- `wailsjsdir` - path to generate wailsjs modules
|
- `wailsjsdir` - path to generate wailsjs modules
|
||||||
- `frontend:install` - The command to install your frontend dependencies
|
- `frontend:install` - The command to install your frontend dependencies
|
||||||
- `frontend:build` - The command to build your frontend
|
- `frontend:build` - The command to build your frontend
|
||||||
|
|||||||
@@ -33,10 +33,10 @@ func main() {
|
|||||||
HideWindowOnClose: false,
|
HideWindowOnClose: false,
|
||||||
RGBA: &options.RGBA{255, 255, 255, 255},
|
RGBA: &options.RGBA{255, 255, 255, 255},
|
||||||
Assets: assets,
|
Assets: assets,
|
||||||
LogLevel: logger.DEBUG,
|
LogLevel: logger.DEBUG,
|
||||||
OnStartup: app.startup,
|
OnStartup: app.startup,
|
||||||
OnDomReady: app.domReady,
|
OnDomReady: app.domReady,
|
||||||
OnShutdown: app.shutdown,
|
OnShutdown: app.shutdown,
|
||||||
Bind: []interface{}{
|
Bind: []interface{}{
|
||||||
app,
|
app,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "{{.ProjectName}}",
|
"name": "{{.ProjectName}}",
|
||||||
"outputfilename": "{{.BinaryName}}",
|
"outputfilename": "{{.BinaryName}}",
|
||||||
"assetdir": "frontend/dist",
|
|
||||||
"frontend:install": "npm install",
|
"frontend:install": "npm install",
|
||||||
"frontend:build": "npm run build",
|
"frontend:build": "npm run build",
|
||||||
"author": {
|
"author": {
|
||||||
|
|||||||
@@ -158,18 +158,17 @@ func processPackageJSON(frontendDir string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := os.ReadFile(packageJSON)
|
json, err := os.ReadFile(packageJSON)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
json := string(data)
|
|
||||||
|
|
||||||
// We will ignore these errors - it's not critical
|
// We will ignore these errors - it's not critical
|
||||||
println("Updating package.json data...")
|
println("Updating package.json data...")
|
||||||
json, _ = sjson.Set(json, "name", "{{.ProjectName}}")
|
json, _ = sjson.SetBytes(json, "name", "{{.ProjectName}}")
|
||||||
json, _ = sjson.Set(json, "author", "{{.AuthorName}}")
|
json, _ = sjson.SetBytes(json, "author", "{{.AuthorName}}")
|
||||||
|
|
||||||
err = os.WriteFile(packageJSON, []byte(json), 0644)
|
err = os.WriteFile(packageJSON, json, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,6 @@
|
|||||||
<working_directory value="$PROJECT_DIR$"/>
|
<working_directory value="$PROJECT_DIR$"/>
|
||||||
<go_parameters value="-gcflags "all=-N -l" -tags dev -o {{.PathToDesktopBinary}}"/>
|
<go_parameters value="-gcflags "all=-N -l" -tags dev -o {{.PathToDesktopBinary}}"/>
|
||||||
<useCustomBuildTags value="true"/>
|
<useCustomBuildTags value="true"/>
|
||||||
<parameters value="-assetdir {{.AssetDir}}"/>
|
|
||||||
<envs>
|
<envs>
|
||||||
<env name="CGO_ENABLED" value=""{{.CGOEnabled}}""/>
|
<env name="CGO_ENABLED" value=""{{.CGOEnabled}}""/>
|
||||||
</envs>
|
</envs>
|
||||||
|
|||||||
@@ -9,11 +9,7 @@
|
|||||||
"program": "${workspaceFolder}/{{.PathToDesktopBinary}}",
|
"program": "${workspaceFolder}/{{.PathToDesktopBinary}}",
|
||||||
"preLaunchTask": "build",
|
"preLaunchTask": "build",
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"env": {},
|
"env": {}
|
||||||
"args": [
|
|
||||||
"-assetdir",
|
|
||||||
"{{.AssetDir}}"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -4,15 +4,14 @@ import (
|
|||||||
"embed"
|
"embed"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/go-git/go-git/v5"
|
|
||||||
gofs "io/fs"
|
gofs "io/fs"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-git/go-git/v5"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/leaanthony/debme"
|
"github.com/leaanthony/debme"
|
||||||
@@ -43,7 +42,6 @@ type Data struct {
|
|||||||
AuthorNameAndEmail string
|
AuthorNameAndEmail string
|
||||||
WailsDirectory string
|
WailsDirectory string
|
||||||
GoSDKPath string
|
GoSDKPath string
|
||||||
AssetDir string
|
|
||||||
WindowsFlags string
|
WindowsFlags string
|
||||||
CGOEnabled string
|
CGOEnabled string
|
||||||
OutputFile string
|
OutputFile string
|
||||||
@@ -61,7 +59,6 @@ type Options struct {
|
|||||||
InitGit bool
|
InitGit bool
|
||||||
AuthorName string
|
AuthorName string
|
||||||
AuthorEmail string
|
AuthorEmail string
|
||||||
AssetDir string
|
|
||||||
IDE string
|
IDE string
|
||||||
ProjectNameFilename string // The project name but as a valid filename
|
ProjectNameFilename string // The project name but as a valid filename
|
||||||
WailsVersion string
|
WailsVersion string
|
||||||
@@ -262,7 +259,6 @@ func Install(options *Options) (bool, *Template, error) {
|
|||||||
AuthorName: options.AuthorName,
|
AuthorName: options.AuthorName,
|
||||||
WailsVersion: options.WailsVersion,
|
WailsVersion: options.WailsVersion,
|
||||||
GoSDKPath: options.GoSDKPath,
|
GoSDKPath: options.GoSDKPath,
|
||||||
AssetDir: options.AssetDir,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a formatted name and email combo.
|
// 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
|
// Clones the given uri and returns the temporary cloned directory
|
||||||
func gitclone(options *Options) (string, error) {
|
func gitclone(options *Options) (string, error) {
|
||||||
// Create temporary directory
|
// Create temporary directory
|
||||||
dirname, err := ioutil.TempDir("", "wails-template-*")
|
dirname, err := os.MkdirTemp("", "wails-template-*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -409,22 +405,6 @@ func installIDEFiles(o ideOptions) error {
|
|||||||
binaryName += ".exe"
|
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.PathToDesktopBinary = filepath.ToSlash(filepath.Join("build", "bin", binaryName))
|
||||||
|
|
||||||
o.options.WindowsFlags = ""
|
o.options.WindowsFlags = ""
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "{{.ProjectName}}",
|
"name": "{{.ProjectName}}",
|
||||||
"outputfilename": "{{.BinaryName}}",
|
"outputfilename": "{{.BinaryName}}",
|
||||||
"assetdir": "frontend/dist",
|
|
||||||
"frontend:install": "npm install",
|
"frontend:install": "npm install",
|
||||||
"frontend:build": "npm run build",
|
"frontend:build": "npm run build",
|
||||||
"wailsjsdir": "./frontend",
|
"wailsjsdir": "./frontend",
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "{{.ProjectName}}",
|
"name": "{{.ProjectName}}",
|
||||||
"outputfilename": "{{.BinaryName}}",
|
"outputfilename": "{{.BinaryName}}",
|
||||||
"assetdir": "frontend/src",
|
|
||||||
"wailsjsdir": "./frontend",
|
"wailsjsdir": "./frontend",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "{{.AuthorName}}",
|
"name": "{{.AuthorName}}",
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
var Version = "v2.0.0-beta.20"
|
var Version = "v2.0.0-beta.22"
|
||||||
|
|||||||
@@ -22,13 +22,13 @@ require (
|
|||||||
github.com/leaanthony/debme v1.2.1
|
github.com/leaanthony/debme v1.2.1
|
||||||
github.com/leaanthony/go-ansi-parser v1.0.1
|
github.com/leaanthony/go-ansi-parser v1.0.1
|
||||||
github.com/leaanthony/go-common-file-dialog v1.0.3
|
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 v0.0.0-20211202091502-64deee9a37e3
|
||||||
github.com/leaanthony/gosod v1.0.3
|
github.com/leaanthony/gosod v1.0.3
|
||||||
github.com/leaanthony/idgen v1.0.0
|
github.com/leaanthony/idgen v1.0.0
|
||||||
github.com/leaanthony/slicer v1.5.0
|
github.com/leaanthony/slicer v1.5.0
|
||||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7
|
github.com/leaanthony/typescriptify-golang-structs v0.1.7
|
||||||
github.com/leaanthony/webview2runtime v1.1.0
|
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/leaanthony/winicon v1.0.0
|
||||||
github.com/matryer/is v1.4.0
|
github.com/matryer/is v1.4.0
|
||||||
github.com/olekukonko/tablewriter v0.0.4
|
github.com/olekukonko/tablewriter v0.0.4
|
||||||
@@ -40,7 +40,6 @@ require (
|
|||||||
github.com/tdewolff/test v1.0.6 // indirect
|
github.com/tdewolff/test v1.0.6 // indirect
|
||||||
github.com/tidwall/sjson v1.1.7
|
github.com/tidwall/sjson v1.1.7
|
||||||
github.com/wzshiming/ctc v1.2.3
|
github.com/wzshiming/ctc v1.2.3
|
||||||
github.com/xyproto/xpm v1.2.1
|
|
||||||
github.com/ztrue/tracerr v0.3.0
|
github.com/ztrue/tracerr v0.3.0
|
||||||
golang.org/x/mod v0.4.1
|
golang.org/x/mod v0.4.1
|
||||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed
|
golang.org/x/net v0.0.0-20210510120150-4163338589ed
|
||||||
@@ -55,7 +54,7 @@ require (
|
|||||||
github.com/emirpasic/gods v1.12.0 // indirect
|
github.com/emirpasic/gods v1.12.0 // indirect
|
||||||
github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab // indirect
|
github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab // indirect
|
||||||
github.com/go-git/gcfg v1.5.0 // 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/google/go-cmp v0.5.5 // indirect
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||||
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
|
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
|
||||||
|
|||||||
16
v2/go.sum
@@ -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 h1:8WKMtJR2j8RntEXR/uvTKagfEt4GYlwQ7mntE4+0GWc=
|
||||||
github.com/go-git/go-git/v5 v5.3.0/go.mod h1:xdX4bWJ48aOrdhnl2XqHYstHbbp6+LFS4r4X+lNVprw=
|
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.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.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||||
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
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/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 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
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-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 h1:O0uGjKnWtdEADGrkg+TyAAbZylykMwwx/MNEXn9fp+Y=
|
||||||
github.com/leaanthony/go-common-file-dialog v1.0.3/go.mod h1:TGhEc9eSJgRsupZ+iH1ZgAOnEo9zp05cRH2j08RPrF0=
|
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-20211202091502-64deee9a37e3 h1:vKdQzUWiq5wtVBLTTeYuikcgQbF/HtYaOmxGzbfkcT0=
|
||||||
github.com/leaanthony/go-webview2 v0.0.0-20211022194343-1e4c8d4226f3/go.mod h1:lS5ds4bruPk9d7lzdF/OH31Z0YCerI6MmHNFGsWoUnM=
|
github.com/leaanthony/go-webview2 v0.0.0-20211202091502-64deee9a37e3/go.mod h1:iX54IaVk1FnDqMuHJ47VYLPQOcVqQiOe9SJACt9CAbU=
|
||||||
github.com/leaanthony/gosod v1.0.3 h1:Fnt+/B6NjQOVuCWOKYRREZnjGyvg+mEhd1nkkA04aTQ=
|
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/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4=
|
||||||
github.com/leaanthony/idgen v1.0.0 h1:IZreR+JGEzFV4yeVuBZA25gM0keUoFy+RDUldncQ+Jw=
|
github.com/leaanthony/idgen v1.0.0 h1:IZreR+JGEzFV4yeVuBZA25gM0keUoFy+RDUldncQ+Jw=
|
||||||
@@ -130,8 +130,8 @@ github.com/leaanthony/typescriptify-golang-structs v0.1.7 h1:yoznzWzyxkO/iWdlpq+
|
|||||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7/go.mod h1:cWtOkiVhMF77e6phAXUcfNwYmMwCJ67Sij24lfvi9Js=
|
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 h1:N0pv55ift8XtqozIp4PNOtRCJ/Qdd/qzx80lUpalS4c=
|
||||||
github.com/leaanthony/webview2runtime v1.1.0/go.mod h1:hH9GnWCve3DYzNaPOcPbhHQ7fodXR1QJNsnwixid4Tk=
|
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-20211202091710-9931d43181ff h1:FwGObElCr/T/xy8S9IKDjWsNcfJHGxgjRl/GIbcseoQ=
|
||||||
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18/go.mod h1:KEbMsKoznsebyGHwLk5LqkFOxL5uXSRdvpP4+avmAMs=
|
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 h1:ZNt5U5dY71oEoKZ97UVwJRT4e+5xo5o/ieKuHuk8NqQ=
|
||||||
github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU=
|
github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU=
|
||||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||||
@@ -213,8 +213,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/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 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI=
|
||||||
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
|
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/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 h1:lDi6EgEYhPYPnKcjsYzmWw4EkFEoA/gfe+I9Y5f+h6Y=
|
||||||
github.com/ztrue/tracerr v0.3.0/go.mod h1:qEalzze4VN9O8tnhBXScfCrmoJo10o8TN5ciKjm6Mww=
|
github.com/ztrue/tracerr v0.3.0/go.mod h1:qEalzze4VN9O8tnhBXScfCrmoJo10o8TN5ciKjm6Mww=
|
||||||
@@ -252,10 +250,10 @@ 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-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-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-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-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-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-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-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-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-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build !windows
|
||||||
// +build !windows
|
// +build !windows
|
||||||
|
|
||||||
package wails
|
package wails
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build !desktop && !hybrid && !server && !dev
|
||||||
// +build !desktop,!hybrid,!server,!dev
|
// +build !desktop,!hybrid,!server,!dev
|
||||||
|
|
||||||
package app
|
package app
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build !server && !desktop && hybrid
|
||||||
// +build !server,!desktop,hybrid
|
// +build !server,!desktop,hybrid
|
||||||
|
|
||||||
package app
|
package app
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//+build !windows
|
//go:build !windows
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
package app
|
package app
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//+build windows
|
//go:build windows
|
||||||
|
// +build windows
|
||||||
|
|
||||||
package app
|
package app
|
||||||
|
|
||||||
|
|||||||
@@ -103,6 +103,12 @@ func generateBindings(bindings *binding.Bindings) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingsTypes := filepath.Join(targetDir, "bindings.d.ts")
|
||||||
|
err = bindings.GenerateBackendTS(bindingsTypes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
32
v2/internal/appng/app_default_linux.go
Normal 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
|
||||||
|
}
|
||||||
@@ -5,7 +5,10 @@ package appng
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"embed"
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
iofs "io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
@@ -91,12 +94,30 @@ func CreateApp(appoptions *options.App) (*App, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 != "" {
|
if devServerURL != "" {
|
||||||
ctx = context.WithValue(ctx, "devserverurl", devServerURL)
|
ctx = context.WithValue(ctx, "devserverurl", devServerURL)
|
||||||
}
|
}
|
||||||
if assetdir != "" {
|
|
||||||
ctx = context.WithValue(ctx, "assetdir", assetdir)
|
|
||||||
}
|
|
||||||
|
|
||||||
if loglevel != "" {
|
if loglevel != "" {
|
||||||
level, err := pkglogger.StringToLogLevel(loglevel)
|
level, err := pkglogger.StringToLogLevel(loglevel)
|
||||||
@@ -193,6 +214,42 @@ func generateBindings(bindings *binding.Bindings) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingsTypes := filepath.Join(targetDir, "bindings.d.ts")
|
||||||
|
err = bindings.GenerateBackendTS(bindingsTypes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
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
|
||||||
|
}
|
||||||
|
|||||||
15
v2/internal/appng/app_linux.go
Normal 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
|
||||||
|
}
|
||||||
@@ -35,6 +35,9 @@ type App struct {
|
|||||||
|
|
||||||
func (a *App) Run() error {
|
func (a *App) Run() error {
|
||||||
err := a.frontend.Run(a.ctx)
|
err := a.frontend.Run(a.ctx)
|
||||||
|
if a.shutdownCallback != nil {
|
||||||
|
a.shutdownCallback(a.ctx)
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,6 +81,9 @@ func CreateApp(appoptions *options.App) (*App, error) {
|
|||||||
appFrontend := desktop.NewFrontend(ctx, appoptions, myLogger, appBindings, messageDispatcher)
|
appFrontend := desktop.NewFrontend(ctx, appoptions, myLogger, appBindings, messageDispatcher)
|
||||||
eventHandler.AddFrontend(appFrontend)
|
eventHandler.AddFrontend(appFrontend)
|
||||||
|
|
||||||
|
// Attach logger to context
|
||||||
|
ctx = context.WithValue(ctx, "logger", myLogger)
|
||||||
|
|
||||||
result := &App{
|
result := &App{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
frontend: appFrontend,
|
frontend: appFrontend,
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
//go:build !desktop
|
||||||
// +build !desktop
|
// +build !desktop
|
||||||
|
|
||||||
package assetdb
|
package assetdb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -122,6 +122,83 @@ export default go;`)
|
|||||||
return os.WriteFile(targetfile, output.Bytes(), 0755)
|
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 {
|
func goTypeToJSDocType(input string) string {
|
||||||
switch true {
|
switch true {
|
||||||
case input == "string":
|
case input == "string":
|
||||||
@@ -139,7 +216,7 @@ func goTypeToJSDocType(input string) string {
|
|||||||
return "string"
|
return "string"
|
||||||
case strings.HasPrefix(input, "[]"):
|
case strings.HasPrefix(input, "[]"):
|
||||||
arrayType := goTypeToJSDocType(input[2:])
|
arrayType := goTypeToJSDocType(input[2:])
|
||||||
return "Array.<" + arrayType + ">"
|
return "Array<" + arrayType + ">"
|
||||||
default:
|
default:
|
||||||
if strings.ContainsRune(input, '.') {
|
if strings.ContainsRune(input, '.') {
|
||||||
return strings.Split(input, ".")[1]
|
return strings.Split(input, ".")[1]
|
||||||
@@ -147,3 +224,11 @@ func goTypeToJSDocType(input string) string {
|
|||||||
return "any"
|
return "any"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func goTypeToTypescriptType(input string) string {
|
||||||
|
if strings.HasPrefix(input, "[]") {
|
||||||
|
arrayType := goTypeToJSDocType(input[2:])
|
||||||
|
return "Array<" + arrayType + ">"
|
||||||
|
}
|
||||||
|
return goTypeToJSDocType(input)
|
||||||
|
}
|
||||||
|
|||||||
@@ -78,10 +78,16 @@ func (b *Bindings) getMethods(value interface{}) ([]*BoundMethod, error) {
|
|||||||
input := methodType.In(inputIndex)
|
input := methodType.In(inputIndex)
|
||||||
thisParam := newParameter("", input)
|
thisParam := newParameter("", input)
|
||||||
|
|
||||||
|
thisInput := input
|
||||||
|
|
||||||
|
if thisInput.Kind() == reflect.Slice {
|
||||||
|
thisInput = thisInput.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
// Process struct pointer params
|
// Process struct pointer params
|
||||||
if input.Kind() == reflect.Ptr {
|
if thisInput.Kind() == reflect.Ptr {
|
||||||
if input.Elem().Kind() == reflect.Struct {
|
if thisInput.Elem().Kind() == reflect.Struct {
|
||||||
typ := input.Elem()
|
typ := thisInput.Elem()
|
||||||
a := reflect.New(typ)
|
a := reflect.New(typ)
|
||||||
s := reflect.Indirect(a).Interface()
|
s := reflect.Indirect(a).Interface()
|
||||||
b.converter.Add(s)
|
b.converter.Add(s)
|
||||||
@@ -89,8 +95,8 @@ func (b *Bindings) getMethods(value interface{}) ([]*BoundMethod, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Process struct params
|
// Process struct params
|
||||||
if input.Kind() == reflect.Struct {
|
if thisInput.Kind() == reflect.Struct {
|
||||||
a := reflect.New(input)
|
a := reflect.New(thisInput)
|
||||||
s := reflect.Indirect(a).Interface()
|
s := reflect.Indirect(a).Interface()
|
||||||
b.converter.Add(s)
|
b.converter.Add(s)
|
||||||
}
|
}
|
||||||
@@ -108,6 +114,30 @@ func (b *Bindings) getMethods(value interface{}) ([]*BoundMethod, error) {
|
|||||||
for outputIndex := 0; outputIndex < outputParamCount; outputIndex++ {
|
for outputIndex := 0; outputIndex < outputParamCount; outputIndex++ {
|
||||||
output := methodType.Out(outputIndex)
|
output := methodType.Out(outputIndex)
|
||||||
thisParam := newParameter("", output)
|
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)
|
outputs = append(outputs, thisParam)
|
||||||
}
|
}
|
||||||
boundMethod.Outputs = outputs
|
boundMethod.Outputs = outputs
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build !windows
|
||||||
// +build !windows
|
// +build !windows
|
||||||
|
|
||||||
package ffenestri
|
package ffenestri
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build windows
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
package ffenestri
|
package ffenestri
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build wv2runtime.browser
|
||||||
// +build wv2runtime.browser
|
// +build wv2runtime.browser
|
||||||
|
|
||||||
package wv2runtime
|
package wv2runtime
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// +build !wv2runtime.error
|
//go:build !wv2runtime.error && !wv2runtime.browser && !wv2runtime.embed
|
||||||
// +build !wv2runtime.browser
|
// +build !wv2runtime.error,!wv2runtime.browser,!wv2runtime.embed
|
||||||
// +build !wv2runtime.embed
|
|
||||||
|
|
||||||
package wv2runtime
|
package wv2runtime
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build wv2runtime.embed
|
||||||
// +build wv2runtime.embed
|
// +build wv2runtime.embed
|
||||||
|
|
||||||
package wv2runtime
|
package wv2runtime
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build wv2runtime.error
|
||||||
// +build wv2runtime.error
|
// +build wv2runtime.error
|
||||||
|
|
||||||
package wv2runtime
|
package wv2runtime
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
//+build windows
|
//go:build windows
|
||||||
|
// +build windows
|
||||||
|
|
||||||
package ffenestri
|
package ffenestri
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/leaanthony/slicer"
|
|
||||||
"github.com/wailsapp/wails/v2/internal/menumanager"
|
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
|
"github.com/leaanthony/slicer"
|
||||||
|
"github.com/wailsapp/wails/v2/internal/menumanager"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------------------
|
/* ---------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//+build windows,debug
|
//go:build windows && debug
|
||||||
|
// +build windows,debug
|
||||||
|
|
||||||
package ffenestri
|
package ffenestri
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build windows && !debug
|
||||||
// +build windows,!debug
|
// +build windows,!debug
|
||||||
|
|
||||||
package ffenestri
|
package ffenestri
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//+build windows
|
//go:build windows
|
||||||
|
// +build windows
|
||||||
|
|
||||||
package ffenestri
|
package ffenestri
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//+build windows
|
//go:build windows
|
||||||
|
// +build windows
|
||||||
|
|
||||||
package ffenestri
|
package ffenestri
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//+build windows
|
//go:build windows
|
||||||
|
// +build windows
|
||||||
|
|
||||||
package ffenestri
|
package ffenestri
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//+build windows
|
//go:build windows
|
||||||
|
// +build windows
|
||||||
|
|
||||||
package ffenestri
|
package ffenestri
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,13 @@ package assetserver
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
|
"context"
|
||||||
"github.com/wailsapp/wails/v2/pkg/options"
|
"io/fs"
|
||||||
"golang.org/x/net/html"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"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 {
|
type BrowserAssetServer struct {
|
||||||
runtimeJS []byte
|
assets fs.FS
|
||||||
assetdir string
|
runtimeJS []byte
|
||||||
appOptions *options.App
|
logger *logger.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBrowserAssetServer(assetdir string, bindingsJSON string, appOptions *options.App) (*BrowserAssetServer, error) {
|
func NewBrowserAssetServer(ctx context.Context, assets fs.FS, bindingsJSON string) (*BrowserAssetServer, error) {
|
||||||
result := &BrowserAssetServer{
|
result := &BrowserAssetServer{}
|
||||||
assetdir: assetdir,
|
_logger := ctx.Value("logger")
|
||||||
appOptions: appOptions,
|
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
|
var buffer bytes.Buffer
|
||||||
buffer.WriteString(`window.wailsbindings='` + bindingsJSON + `';` + "\n")
|
buffer.WriteString(`window.wailsbindings='` + bindingsJSON + `';` + "\n")
|
||||||
buffer.Write(runtime.RuntimeDesktopJS)
|
buffer.Write(runtime.RuntimeDesktopJS)
|
||||||
result.runtimeJS = buffer.Bytes()
|
result.runtimeJS = buffer.Bytes()
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *BrowserAssetServer) loadFileFromDisk(filename string) ([]byte, error) {
|
func (d *BrowserAssetServer) LogDebug(message string, args ...interface{}) {
|
||||||
return os.ReadFile(filepath.Join(a.assetdir, filename))
|
if d.logger != nil {
|
||||||
|
d.logger.Debug("[BrowserAssetServer] "+message, args...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *BrowserAssetServer) processIndexHTML() ([]byte, error) {
|
func (a *BrowserAssetServer) processIndexHTML() ([]byte, error) {
|
||||||
indexHTML, err := a.loadFileFromDisk("index.html")
|
indexHTML, err := fs.ReadFile(a.assets, "index.html")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -97,15 +105,9 @@ func (a *BrowserAssetServer) Load(filename string) ([]byte, string, error) {
|
|||||||
case "/wails/ipc.js":
|
case "/wails/ipc.js":
|
||||||
content = runtime.WebsocketIPC
|
content = runtime.WebsocketIPC
|
||||||
default:
|
default:
|
||||||
content, err = a.loadFileFromDisk(filename)
|
filename = strings.TrimPrefix(filename, "/")
|
||||||
if strings.HasSuffix(filename, ".js") {
|
a.LogDebug("Loading file: %s", filename)
|
||||||
var buffer bytes.Buffer
|
content, err = fs.ReadFile(a.assets, filename)
|
||||||
buffer.WriteString("window.awaitIPC('" + filename + "', ()=>{")
|
|
||||||
buffer.Write(content)
|
|
||||||
buffer.WriteString(`
|
|
||||||
});`)
|
|
||||||
content = buffer.Bytes()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
|
|||||||
25
v2/internal/frontend/assetserver/assetserver_common.go
Normal 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
|
||||||
|
}
|
||||||
@@ -3,26 +3,21 @@ package assetserver
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"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"
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
|
||||||
|
"github.com/wailsapp/wails/v2/internal/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DesktopAssetServer struct {
|
type DesktopAssetServer struct {
|
||||||
assets debme.Debme
|
assets fs.FS
|
||||||
runtimeJS []byte
|
runtimeJS []byte
|
||||||
assetdir string
|
|
||||||
logger *logger.Logger
|
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{}
|
result := &DesktopAssetServer{}
|
||||||
|
|
||||||
_logger := ctx.Value("logger")
|
_logger := ctx.Value("logger")
|
||||||
@@ -30,22 +25,18 @@ func NewDesktopAssetServer(ctx context.Context, assets embed.FS, bindingsJSON st
|
|||||||
result.logger = _logger.(*logger.Logger)
|
result.logger = _logger.(*logger.Logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
_assetdir := ctx.Value("assetdir")
|
var err error
|
||||||
if _assetdir != nil {
|
result.assets, err = prepareAssetsForServing(assets)
|
||||||
result.assetdir = _assetdir.(string)
|
if err != nil {
|
||||||
absdir, err := filepath.Abs(result.assetdir)
|
return nil, err
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
result.LogDebug("Loading assets from: %s", absdir)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
buffer.WriteString(`window.wailsbindings='` + bindingsJSON + `';` + "\n")
|
buffer.WriteString(`window.wailsbindings='` + bindingsJSON + `';` + "\n")
|
||||||
buffer.Write(runtime.RuntimeDesktopJS)
|
buffer.Write(runtime.RuntimeDesktopJS)
|
||||||
result.runtimeJS = buffer.Bytes()
|
result.runtimeJS = buffer.Bytes()
|
||||||
err := result.init(assets)
|
|
||||||
return result, err
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DesktopAssetServer) LogDebug(message string, args ...interface{}) {
|
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) {
|
func (a *DesktopAssetServer) processIndexHTML() ([]byte, error) {
|
||||||
indexHTML, err := a.ReadFile("index.html")
|
indexHTML, err := fs.ReadFile(a.assets, "index.html")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -146,7 +82,9 @@ func (a *DesktopAssetServer) Load(filename string) ([]byte, string, error) {
|
|||||||
case "/wails/ipc.js":
|
case "/wails/ipc.js":
|
||||||
content = runtime.DesktopIPC
|
content = runtime.DesktopIPC
|
||||||
default:
|
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 {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
|
|||||||
@@ -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))
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
//go:build production
|
|
||||||
|
|
||||||
package assetserver
|
|
||||||
|
|
||||||
func (a *DesktopAssetServer) ReadFile(filename string) ([]byte, error) {
|
|
||||||
return a.assets.ReadFile(filename)
|
|
||||||
}
|
|
||||||
20
v2/internal/frontend/desktop/common/uri_translate.go
Normal 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
|
||||||
|
}
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
@property bool alwaysOnTop;
|
@property bool alwaysOnTop;
|
||||||
@property bool startHidden;
|
@property bool startHidden;
|
||||||
|
@property bool startFullscreen;
|
||||||
@property (retain) WailsWindow* mainWindow;
|
@property (retain) WailsWindow* mainWindow;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -26,6 +26,12 @@
|
|||||||
|
|
||||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
||||||
[NSApp activateIgnoringOtherApps:YES];
|
[NSApp activateIgnoringOtherApps:YES];
|
||||||
|
if ( self.startFullscreen ) {
|
||||||
|
NSWindowCollectionBehavior behaviour = [self.mainWindow collectionBehavior];
|
||||||
|
behaviour |= NSWindowCollectionBehaviorFullScreenPrimary;
|
||||||
|
[self.mainWindow setCollectionBehavior:behaviour];
|
||||||
|
[self.mainWindow toggleFullScreen:nil];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)dealloc {
|
- (void)dealloc {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
#define WindowStartsMinimised 2
|
#define WindowStartsMinimised 2
|
||||||
#define WindowStartsFullscreen 3
|
#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);
|
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 Run(void*);
|
||||||
|
|
||||||
void SetTitle(void* ctx, const char *title);
|
void SetTitle(void* ctx, const char *title);
|
||||||
@@ -41,7 +41,7 @@ void Quit(void*);
|
|||||||
const char* GetSize(void *ctx);
|
const char* GetSize(void *ctx);
|
||||||
const char* GetPos(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 */
|
/* Dialogs */
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#import "WailsMenu.h"
|
#import "WailsMenu.h"
|
||||||
#import "WailsMenuItem.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, int windowStartState, int startsHidden) {
|
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];
|
[NSApplication sharedApplication];
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ WailsContext* Create(const char* title, int width, int height, int frameless, in
|
|||||||
fullscreen = 1;
|
fullscreen = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
[result CreateWindow:width :height :frameless :resizable :fullscreen :fullSizeContent :hideTitleBar :titlebarAppearsTransparent :hideTitle :useToolbar :hideToolbarSeparator :webviewIsTransparent :hideWindowOnClose :safeInit(appearance) :windowIsTranslucent];
|
[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 SetTitle:safeInit(title)];
|
||||||
[result Center];
|
[result Center];
|
||||||
|
|
||||||
@@ -41,19 +41,25 @@ WailsContext* Create(const char* title, int width, int height, int frameless, in
|
|||||||
result.startHidden = true;
|
result.startHidden = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( fullscreen == 1 ) {
|
||||||
|
result.startFullscreen = true;
|
||||||
|
}
|
||||||
|
|
||||||
result.alwaysOnTop = alwaysOnTop;
|
result.alwaysOnTop = alwaysOnTop;
|
||||||
result.hideOnClose = hideWindowOnClose;
|
result.hideOnClose = hideWindowOnClose;
|
||||||
|
|
||||||
return result;
|
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;
|
WailsContext *ctx = (__bridge WailsContext*) inctx;
|
||||||
NSString *nsurl = safeInit(url);
|
NSString *nsurl = safeInit(url);
|
||||||
NSString *nsContentType = safeInit(contentType);
|
NSString *nsContentType = safeInit(contentType);
|
||||||
NSData *nsdata = [NSData dataWithBytes:data length:datalength];
|
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) {
|
void ExecJS(void* inctx, const char *script) {
|
||||||
@@ -324,6 +330,7 @@ void Run(void *inctx) {
|
|||||||
delegate.mainWindow = ctx.mainWindow;
|
delegate.mainWindow = ctx.mainWindow;
|
||||||
delegate.alwaysOnTop = ctx.alwaysOnTop;
|
delegate.alwaysOnTop = ctx.alwaysOnTop;
|
||||||
delegate.startHidden = ctx.startHidden;
|
delegate.startHidden = ctx.startHidden;
|
||||||
|
delegate.startFullscreen = ctx.startFullscreen;
|
||||||
|
|
||||||
[ctx loadRequest:@"wails://wails/"];
|
[ctx loadRequest:@"wails://wails/"];
|
||||||
[app setMainMenu:ctx.applicationMenu];
|
[app setMainMenu:ctx.applicationMenu];
|
||||||
|
|||||||
@@ -11,11 +11,21 @@
|
|||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
#import <WebKit/WebKit.h>
|
#import <WebKit/WebKit.h>
|
||||||
|
|
||||||
|
#if __has_include(<UniformTypeIdentifiers/UTType.h>)
|
||||||
|
#import <UniformTypeIdentifiers/UTType.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ON_MAIN_THREAD(str) dispatch_async(dispatch_get_main_queue(), ^{ str; });
|
#define ON_MAIN_THREAD(str) dispatch_async(dispatch_get_main_queue(), ^{ str; });
|
||||||
#define unicode(input) [NSString stringWithFormat:@"%C", input]
|
#define unicode(input) [NSString stringWithFormat:@"%C", input]
|
||||||
|
|
||||||
@interface WailsWindow : NSWindow
|
@interface WailsWindow : NSWindow
|
||||||
- (BOOL)canBecomeKeyWindow;
|
|
||||||
|
@property NSSize userMinSize;
|
||||||
|
@property NSSize userMaxSize;
|
||||||
|
|
||||||
|
- (BOOL) canBecomeKeyWindow;
|
||||||
|
- (void) applyWindowConstraints;
|
||||||
|
- (void) disableWindowConstraints;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface WailsContext : NSObject <WKURLSchemeHandler,WKScriptMessageHandler,WKNavigationDelegate>
|
@interface WailsContext : NSObject <WKURLSchemeHandler,WKScriptMessageHandler,WKNavigationDelegate>
|
||||||
@@ -27,9 +37,7 @@
|
|||||||
@property bool hideOnClose;
|
@property bool hideOnClose;
|
||||||
@property bool shuttingDown;
|
@property bool shuttingDown;
|
||||||
@property bool startHidden;
|
@property bool startHidden;
|
||||||
|
@property bool startFullscreen;
|
||||||
@property NSSize maxSize;
|
|
||||||
@property NSSize minSize;
|
|
||||||
|
|
||||||
@property (retain) NSEvent* mouseEvent;
|
@property (retain) NSEvent* mouseEvent;
|
||||||
|
|
||||||
@@ -46,7 +54,7 @@
|
|||||||
@property (retain) NSString* aboutTitle;
|
@property (retain) NSString* aboutTitle;
|
||||||
@property (retain) NSString* aboutDescription;
|
@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) SetSize:(int)width :(int)height;
|
||||||
- (void) SetPosition:(int)x :(int) y;
|
- (void) SetPosition:(int)x :(int) y;
|
||||||
- (void) SetMinSize:(int)minWidth :(int)minHeight;
|
- (void) SetMinSize:(int)minWidth :(int)minHeight;
|
||||||
@@ -71,11 +79,12 @@
|
|||||||
- (void) SaveFileDialog :(NSString*)title :(NSString*)defaultFilename :(NSString*)defaultDirectory :(bool)canCreateDirectories :(bool)treatPackagesAsDirectories :(bool)showHiddenFiles :(NSString*)filters;
|
- (void) SaveFileDialog :(NSString*)title :(NSString*)defaultFilename :(NSString*)defaultDirectory :(bool)canCreateDirectories :(bool)treatPackagesAsDirectories :(bool)showHiddenFiles :(NSString*)filters;
|
||||||
|
|
||||||
- (void) loadRequest:(NSString*)url;
|
- (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;
|
- (void) ExecJS:(NSString*)script;
|
||||||
- (NSScreen*) getCurrentScreen;
|
- (NSScreen*) getCurrentScreen;
|
||||||
|
|
||||||
- (void) SetAbout :(NSString*)title :(NSString*)description :(void*)imagedata :(int)datalen;
|
- (void) SetAbout :(NSString*)title :(NSString*)description :(void*)imagedata :(int)datalen;
|
||||||
|
- (void) dealloc;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,16 @@
|
|||||||
return YES;
|
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
|
@end
|
||||||
|
|
||||||
@implementation WailsContext
|
@implementation WailsContext
|
||||||
@@ -33,7 +43,7 @@
|
|||||||
frame.origin.y += frame.size.height - height;
|
frame.origin.y += frame.size.height - height;
|
||||||
frame.size.width = width;
|
frame.size.width = width;
|
||||||
frame.size.height = height;
|
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 {
|
- (void) SetPosition:(int)x :(int)y {
|
||||||
@@ -45,8 +55,8 @@
|
|||||||
NSRect screenFrame = [screen frame];
|
NSRect screenFrame = [screen frame];
|
||||||
windowFrame.origin.x = screenFrame.origin.x + (float)x;
|
windowFrame.origin.x = screenFrame.origin.x + (float)x;
|
||||||
windowFrame.origin.y = (screenFrame.origin.y + screenFrame.size.height) - windowFrame.size.height - (float)y;
|
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 {
|
- (void) SetMinSize:(int)minWidth :(int)minHeight {
|
||||||
@@ -54,13 +64,9 @@
|
|||||||
if (self.shuttingDown) return;
|
if (self.shuttingDown) return;
|
||||||
|
|
||||||
NSSize size = { minWidth, minHeight };
|
NSSize size = { minWidth, minHeight };
|
||||||
|
self.mainWindow.userMinSize = size;
|
||||||
self.minSize = size;
|
[self.mainWindow setMinSize:size];
|
||||||
|
[self adjustWindowSize];
|
||||||
ON_MAIN_THREAD(
|
|
||||||
[self.mainWindow setMinSize:size];
|
|
||||||
[self adjustWindowSize];
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -73,12 +79,9 @@
|
|||||||
size.width = maxWidth > 0 ? maxWidth : FLT_MAX;
|
size.width = maxWidth > 0 ? maxWidth : FLT_MAX;
|
||||||
size.height = maxHeight > 0 ? maxHeight : FLT_MAX;
|
size.height = maxHeight > 0 ? maxHeight : FLT_MAX;
|
||||||
|
|
||||||
self.maxSize = size;
|
self.mainWindow.userMaxSize = size;
|
||||||
|
[self.mainWindow setMaxSize:size];
|
||||||
ON_MAIN_THREAD(
|
[self adjustWindowSize];
|
||||||
[self.mainWindow setMaxSize:size];
|
|
||||||
[self adjustWindowSize];
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -88,23 +91,23 @@
|
|||||||
|
|
||||||
NSRect currentFrame = [self.mainWindow frame];
|
NSRect currentFrame = [self.mainWindow frame];
|
||||||
|
|
||||||
if ( currentFrame.size.width > self.maxSize.width ) currentFrame.size.width = self.maxSize.width;
|
if ( currentFrame.size.width > self.mainWindow.userMaxSize.width ) currentFrame.size.width = self.mainWindow.userMaxSize.width;
|
||||||
if ( currentFrame.size.width < self.minSize.width ) currentFrame.size.width = self.minSize.width;
|
if ( currentFrame.size.width < self.mainWindow.userMinSize.width ) currentFrame.size.width = self.mainWindow.userMinSize.width;
|
||||||
if ( currentFrame.size.height > self.maxSize.height ) currentFrame.size.height = self.maxSize.height;
|
if ( currentFrame.size.height > self.mainWindow.userMaxSize.height ) currentFrame.size.height = self.mainWindow.userMaxSize.height;
|
||||||
if ( currentFrame.size.height < self.minSize.height ) currentFrame.size.height = self.minSize.height;
|
if ( currentFrame.size.height < self.mainWindow.userMinSize.height ) currentFrame.size.height = self.mainWindow.userMinSize.height;
|
||||||
|
|
||||||
[self.mainWindow setFrame:currentFrame display:YES animate:FALSE];
|
[self.mainWindow setFrame:currentFrame display:YES animate:FALSE];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) dealloc {
|
- (void) dealloc {
|
||||||
[super dealloc];
|
|
||||||
[self.appdelegate release];
|
[self.appdelegate release];
|
||||||
[self.mainWindow release];
|
[self.mainWindow release];
|
||||||
[self.mouseEvent release];
|
[self.mouseEvent release];
|
||||||
[self.userContentController release];
|
[self.userContentController release];
|
||||||
[self.urlRequests release];
|
[self.urlRequests release];
|
||||||
[self.applicationMenu release];
|
[self.applicationMenu release];
|
||||||
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSScreen*) getCurrentScreen {
|
- (NSScreen*) getCurrentScreen {
|
||||||
@@ -116,11 +119,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void) SetTitle:(NSString*)title {
|
- (void) SetTitle:(NSString*)title {
|
||||||
ON_MAIN_THREAD([self.mainWindow setTitle:title];)
|
[self.mainWindow setTitle:title];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) Center {
|
- (void) Center {
|
||||||
ON_MAIN_THREAD( [self.mainWindow center]; );
|
[self.mainWindow center];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) isFullscreen {
|
- (BOOL) isFullscreen {
|
||||||
@@ -131,37 +134,29 @@
|
|||||||
return NO;
|
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];
|
self.urlRequests = [NSMutableDictionary new];
|
||||||
|
|
||||||
NSWindowStyleMask styleMask = NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable;
|
NSWindowStyleMask styleMask = 0;
|
||||||
|
|
||||||
if (frameless) {
|
if( !frameless ) {
|
||||||
styleMask = NSWindowStyleMaskBorderless;
|
|
||||||
titlebarAppearsTransparent = true;
|
|
||||||
hideTitle = true;
|
|
||||||
} else {
|
|
||||||
if (!hideTitleBar) {
|
if (!hideTitleBar) {
|
||||||
styleMask |= NSWindowStyleMaskTitled;
|
styleMask |= NSWindowStyleMaskTitled;
|
||||||
}
|
}
|
||||||
|
styleMask |= NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable;
|
||||||
if (fullscreen) {
|
|
||||||
styleMask |= NSWindowStyleMaskFullScreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( fullSizeContent || frameless || titlebarAppearsTransparent ) {
|
|
||||||
styleMask |= NSWindowStyleMaskFullSizeContentView;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( fullSizeContent || frameless || titlebarAppearsTransparent ) {
|
||||||
|
styleMask |= NSWindowStyleMaskFullSizeContentView;
|
||||||
|
}
|
||||||
|
|
||||||
if (resizable) {
|
if (resizable) {
|
||||||
styleMask |= NSWindowStyleMaskResizable;
|
styleMask |= NSWindowStyleMaskResizable;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.mainWindow = [[[WailsWindow alloc] initWithContentRect:NSMakeRect(0, 0, width, height)
|
self.mainWindow = [[WailsWindow alloc] initWithContentRect:NSMakeRect(0, 0, width, height)
|
||||||
styleMask:styleMask backing:NSBackingStoreBuffered defer:NO]
|
styleMask:styleMask backing:NSBackingStoreBuffered defer:NO];
|
||||||
autorelease];
|
|
||||||
|
|
||||||
if (!frameless && useToolbar) {
|
if (!frameless && useToolbar) {
|
||||||
id toolbar = [[NSToolbar alloc] initWithIdentifier:@"wails.toolbar"];
|
id toolbar = [[NSToolbar alloc] initWithIdentifier:@"wails.toolbar"];
|
||||||
@@ -192,15 +187,25 @@
|
|||||||
[self.mainWindow setAppearance:nsAppearance];
|
[self.mainWindow setAppearance:nsAppearance];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up min/max
|
|
||||||
NSSize maxSize = { FLT_MAX, FLT_MAX };
|
NSSize minSize = { minWidth, minHeight };
|
||||||
self.maxSize = maxSize;
|
NSSize maxSize = { maxWidth, maxHeight };
|
||||||
NSSize minSize = { 0, 0 };
|
if (maxSize.width == 0) {
|
||||||
self.minSize = minSize;
|
maxSize.width = FLT_MAX;
|
||||||
[self adjustWindowSize];
|
}
|
||||||
|
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 *windowDelegate = [WindowDelegate new];
|
||||||
windowDelegate.hideOnClose = hideWindowOnClose;
|
windowDelegate.hideOnClose = hideWindowOnClose;
|
||||||
|
windowDelegate.ctx = self;
|
||||||
[self.mainWindow setDelegate:windowDelegate];
|
[self.mainWindow setDelegate:windowDelegate];
|
||||||
|
|
||||||
// Webview stuff here!
|
// Webview stuff here!
|
||||||
@@ -278,7 +283,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (NSMenu*) newMenu :(NSString*)title {
|
- (NSMenu*) newMenu :(NSString*)title {
|
||||||
WailsMenu *result = [[[WailsMenu new] initWithTitle:title] autorelease];
|
WailsMenu *result = [[WailsMenu new] initWithTitle:title];
|
||||||
[result setAutoenablesItems:NO];
|
[result setAutoenablesItems:NO];
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -294,14 +299,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void) SetRGBA:(int)r :(int)g :(int)b :(int)a {
|
- (void) SetRGBA:(int)r :(int)g :(int)b :(int)a {
|
||||||
float red = r/255;
|
float red = r/255.0;
|
||||||
float green = g/255;
|
float green = g/255.0;
|
||||||
float blue = b/255;
|
float blue = b/255.0;
|
||||||
float alpha = a/255;
|
float alpha = a/255.0;
|
||||||
|
|
||||||
id colour = [NSColor colorWithCalibratedRed:red green:green blue:blue alpha:alpha ];
|
id colour = [NSColor colorWithCalibratedRed:red green:green blue:blue alpha:alpha ];
|
||||||
|
|
||||||
ON_MAIN_THREAD([self.mainWindow setBackgroundColor:colour];);
|
[self.mainWindow setBackgroundColor:colour];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) HideMouse {
|
- (void) HideMouse {
|
||||||
@@ -325,66 +330,66 @@
|
|||||||
// Fullscreen sets the main window to be fullscreen
|
// Fullscreen sets the main window to be fullscreen
|
||||||
- (void) Fullscreen {
|
- (void) Fullscreen {
|
||||||
if( ! [self isFullScreen] ) {
|
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
|
// UnFullscreen resets the main window after a fullscreen
|
||||||
- (void) UnFullscreen {
|
- (void) UnFullscreen {
|
||||||
if( [self isFullScreen] ) {
|
if( [self isFullScreen] ) {
|
||||||
ON_MAIN_THREAD([self.mainWindow toggleFullScreen:nil];)
|
[self.mainWindow applyWindowConstraints];
|
||||||
|
[self.mainWindow toggleFullScreen:nil];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) Minimise {
|
- (void) Minimise {
|
||||||
ON_MAIN_THREAD([self.mainWindow miniaturize:nil];)
|
[self.mainWindow miniaturize:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) UnMinimise {
|
- (void) UnMinimise {
|
||||||
ON_MAIN_THREAD([self.mainWindow deminiaturize:nil];)
|
[self.mainWindow deminiaturize:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) Hide {
|
- (void) Hide {
|
||||||
ON_MAIN_THREAD([self.mainWindow orderOut:nil];)
|
[self.mainWindow orderOut:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) Show {
|
- (void) Show {
|
||||||
ON_MAIN_THREAD(
|
[self.mainWindow makeKeyAndOrderFront:nil];
|
||||||
[self.mainWindow makeKeyAndOrderFront:nil];
|
[NSApp activateIgnoringOtherApps:YES];
|
||||||
[NSApp activateIgnoringOtherApps:YES];
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) Maximise {
|
- (void) Maximise {
|
||||||
if (![self.mainWindow isZoomed]) {
|
if (![self.mainWindow isZoomed]) {
|
||||||
ON_MAIN_THREAD([self.mainWindow zoom:nil];)
|
[self.mainWindow zoom:nil];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) UnMaximise {
|
- (void) UnMaximise {
|
||||||
if ([self.mainWindow isZoomed]) {
|
if ([self.mainWindow isZoomed]) {
|
||||||
ON_MAIN_THREAD([self.mainWindow zoom:nil];)
|
[self.mainWindow zoom:nil];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) ExecJS:(NSString*)script {
|
- (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];
|
id<WKURLSchemeTask> urlSchemeTask = self.urlRequests[url];
|
||||||
NSURL *nsurl = [NSURL URLWithString:url];
|
NSURL *nsurl = [NSURL URLWithString:url];
|
||||||
|
|
||||||
NSHTTPURLResponse *response = [NSHTTPURLResponse new];
|
|
||||||
NSMutableDictionary *headerFields = [NSMutableDictionary new];
|
NSMutableDictionary *headerFields = [NSMutableDictionary new];
|
||||||
headerFields[@"content-type"] = contentType;
|
if ( ![contentType isEqualToString:@""] ) {
|
||||||
[response initWithURL:nsurl statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:headerFields];
|
headerFields[@"content-type"] = contentType;
|
||||||
|
}
|
||||||
|
NSHTTPURLResponse *response = [[NSHTTPURLResponse new] initWithURL:nsurl statusCode:statusCode HTTPVersion:@"HTTP/1.1" headerFields:headerFields];
|
||||||
[urlSchemeTask didReceiveResponse:response];
|
[urlSchemeTask didReceiveResponse:response];
|
||||||
[urlSchemeTask didReceiveData:data];
|
[urlSchemeTask didReceiveData:data];
|
||||||
[urlSchemeTask didFinish];
|
[urlSchemeTask didFinish];
|
||||||
[self.urlRequests removeObjectForKey:url];
|
[self.urlRequests removeObjectForKey:url];
|
||||||
|
[response release];
|
||||||
|
[headerFields release];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)webView:(nonnull WKWebView *)webView startURLSchemeTask:(nonnull id<WKURLSchemeTask>)urlSchemeTask {
|
- (void)webView:(nonnull WKWebView *)webView startURLSchemeTask:(nonnull id<WKURLSchemeTask>)urlSchemeTask {
|
||||||
@@ -406,15 +411,13 @@
|
|||||||
|
|
||||||
// Check for drag
|
// Check for drag
|
||||||
if ( [m isEqualToString:@"drag"] ) {
|
if ( [m isEqualToString:@"drag"] ) {
|
||||||
if( ! [self isFullScreen] ) {
|
if( [self isFullScreen] ) {
|
||||||
if( self.mouseEvent != nil ) {
|
|
||||||
[self HideMouse];
|
|
||||||
ON_MAIN_THREAD(
|
|
||||||
[self.mainWindow performWindowDragWithEvent:self.mouseEvent];
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if( self.mouseEvent != nil ) {
|
||||||
|
[self.mainWindow performWindowDragWithEvent:self.mouseEvent];
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *_m = [m UTF8String];
|
const char *_m = [m UTF8String];
|
||||||
@@ -455,28 +458,26 @@
|
|||||||
NSData *imageData = [NSData dataWithBytes:iconData length:iconDataLength];
|
NSData *imageData = [NSData dataWithBytes:iconData length:iconDataLength];
|
||||||
icon = [[NSImage alloc] initWithData:imageData];
|
icon = [[NSImage alloc] initWithData:imageData];
|
||||||
}
|
}
|
||||||
ON_MAIN_THREAD(
|
if( icon != nil) {
|
||||||
if( icon != nil) {
|
[alert setIcon:icon];
|
||||||
[alert setIcon:icon];
|
}
|
||||||
}
|
[alert.window setLevel:NSFloatingWindowLevel];
|
||||||
[alert.window setLevel:NSFloatingWindowLevel];
|
|
||||||
|
|
||||||
long response = [alert runModal];
|
long response = [alert runModal];
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if( response == NSAlertFirstButtonReturn ) {
|
if( response == NSAlertFirstButtonReturn ) {
|
||||||
result = 0;
|
result = 0;
|
||||||
}
|
}
|
||||||
else if( response == NSAlertSecondButtonReturn ) {
|
else if( response == NSAlertSecondButtonReturn ) {
|
||||||
result = 1;
|
result = 1;
|
||||||
}
|
}
|
||||||
else if( response == NSAlertThirdButtonReturn ) {
|
else if( response == NSAlertThirdButtonReturn ) {
|
||||||
result = 2;
|
result = 2;
|
||||||
} else {
|
} else {
|
||||||
result = 3;
|
result = 3;
|
||||||
}
|
}
|
||||||
processMessageDialogResponse(result);
|
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 {
|
-(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,20 @@
|
|||||||
|
|
||||||
// Filters - semicolon delimited list of file extensions
|
// Filters - semicolon delimited list of file extensions
|
||||||
if( allowFiles ) {
|
if( allowFiles ) {
|
||||||
if( filters != nil ) {
|
if( filters != nil && [filters length] > 0) {
|
||||||
filters = [filters stringByReplacingOccurrencesOfString:@"*." withString:@""];
|
filters = [filters stringByReplacingOccurrencesOfString:@"*." withString:@""];
|
||||||
filters = [filters stringByReplacingOccurrencesOfString:@" " withString:@""];
|
filters = [filters stringByReplacingOccurrencesOfString:@" " withString:@""];
|
||||||
NSArray *filterList = [filters componentsSeparatedByString:@";"];
|
NSArray *filterList = [filters componentsSeparatedByString:@";"];
|
||||||
[dialog setAllowedFileTypes:filterList];
|
if (@available(macOS 10.16, *)) {
|
||||||
|
NSMutableArray *contentTypes = [[NSMutableArray new] autorelease];
|
||||||
|
for (NSString *filter in filterList) {
|
||||||
|
UTType *t = [UTType typeWithFilenameExtension:filter];
|
||||||
|
[contentTypes addObject:t];
|
||||||
|
}
|
||||||
|
[dialog setAllowedContentTypes:contentTypes];
|
||||||
|
} else {
|
||||||
|
[dialog setAllowedFileTypes:filterList];
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
[dialog setAllowsOtherFileTypes:true];
|
[dialog setAllowsOtherFileTypes:true];
|
||||||
}
|
}
|
||||||
@@ -613,8 +623,7 @@
|
|||||||
[alert setIcon:self.aboutImage];
|
[alert setIcon:self.aboutImage];
|
||||||
}
|
}
|
||||||
|
|
||||||
ON_MAIN_THREAD([alert runModal];)
|
[alert runModal];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
if( appName == nil ) {
|
if( appName == nil ) {
|
||||||
appName = [[NSProcessInfo processInfo] processName];
|
appName = [[NSProcessInfo processInfo] processName];
|
||||||
}
|
}
|
||||||
WailsMenu *appMenu = [[WailsMenu new] initWithNSTitle:appName];
|
WailsMenu *appMenu = [[[WailsMenu new] initWithNSTitle:appName] autorelease];
|
||||||
id quitTitle = [@"Quit " stringByAppendingString:appName];
|
id quitTitle = [@"Quit " stringByAppendingString:appName];
|
||||||
NSMenuItem* quitMenuItem = [self newMenuItem:quitTitle :@selector(Quit) :@"q" :NSEventModifierFlagCommand];
|
NSMenuItem* quitMenuItem = [self newMenuItem:quitTitle :@selector(Quit) :@"q" :NSEventModifierFlagCommand];
|
||||||
quitMenuItem.target = ctx;
|
quitMenuItem.target = ctx;
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
}
|
}
|
||||||
case EditMenu:
|
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:@"Undo" :@selector(undoActionName) :@"z" :NSEventModifierFlagCommand]];
|
||||||
[editMenu addItem:[self newMenuItem:@"Redo" :@selector(redoActionName) :@"z" :(NSEventModifierFlagShift | NSEventModifierFlagCommand)]];
|
[editMenu addItem:[self newMenuItem:@"Redo" :@selector(redoActionName) :@"z" :(NSEventModifierFlagShift | NSEventModifierFlagCommand)]];
|
||||||
[editMenu addItem:[NSMenuItem separatorItem]];
|
[editMenu addItem:[NSMenuItem separatorItem]];
|
||||||
@@ -91,7 +91,7 @@
|
|||||||
// NSMenuItem *speechMenuItem = [[NSMenuItem new] autorelease];
|
// NSMenuItem *speechMenuItem = [[NSMenuItem new] autorelease];
|
||||||
// [speechMenuItem setTitle:@"Speech"];
|
// [speechMenuItem setTitle:@"Speech"];
|
||||||
// [editMenu addItem:speechMenuItem];
|
// [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:@"Start Speaking" :@selector(startSpeaking:) :@""]];
|
||||||
[speechMenu addItem:[self newMenuItem:@"Stop Speaking" :@selector(stopSpeaking:) :@""]];
|
[speechMenu addItem:[self newMenuItem:@"Stop Speaking" :@selector(stopSpeaking:) :@""]];
|
||||||
[editMenu appendSubmenu:speechMenu];
|
[editMenu appendSubmenu:speechMenu];
|
||||||
|
|||||||
@@ -8,10 +8,17 @@
|
|||||||
#ifndef WindowDelegate_h
|
#ifndef WindowDelegate_h
|
||||||
#define WindowDelegate_h
|
#define WindowDelegate_h
|
||||||
|
|
||||||
|
#import "WailsContext.h"
|
||||||
|
|
||||||
@interface WindowDelegate : NSObject <NSWindowDelegate>
|
@interface WindowDelegate : NSObject <NSWindowDelegate>
|
||||||
|
|
||||||
@property bool hideOnClose;
|
@property bool hideOnClose;
|
||||||
|
|
||||||
|
@property (assign) WailsContext* ctx;
|
||||||
|
|
||||||
|
- (void)windowDidExitFullScreen:(NSNotification *)notification;
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,13 +12,26 @@
|
|||||||
#import "WailsContext.h"
|
#import "WailsContext.h"
|
||||||
|
|
||||||
@implementation WindowDelegate
|
@implementation WindowDelegate
|
||||||
|
|
||||||
- (BOOL)windowShouldClose:(WailsWindow *)sender {
|
- (BOOL)windowShouldClose:(WailsWindow *)sender {
|
||||||
[sender orderOut:nil];
|
if( self.hideOnClose ) {
|
||||||
if( self.hideOnClose == false ) {
|
[NSApp hide:nil];
|
||||||
processMessage("Q");
|
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
|
@end
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ func (f *Frontend) openDialog(options *frontend.OpenDialogOptions, multiple bool
|
|||||||
|
|
||||||
// OpenFileDialog prompts the user to select a file
|
// OpenFileDialog prompts the user to select a file
|
||||||
func (f *Frontend) OpenFileDialog(options frontend.OpenDialogOptions) (string, error) {
|
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 {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -97,7 +97,7 @@ func (f *Frontend) OpenFileDialog(options frontend.OpenDialogOptions) (string, e
|
|||||||
|
|
||||||
// OpenMultipleFilesDialog prompts the user to select a file
|
// OpenMultipleFilesDialog prompts the user to select a file
|
||||||
func (f *Frontend) OpenMultipleFilesDialog(options frontend.OpenDialogOptions) ([]string, error) {
|
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
|
// SaveFileDialog prompts the user to select a file
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ package darwin
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
#cgo CFLAGS: -x objective-c
|
#cgo CFLAGS: -x objective-c
|
||||||
#cgo LDFLAGS: -framework Foundation -framework Cocoa -framework WebKit
|
#cgo LDFLAGS: -framework Foundation -framework Cocoa -framework WebKit -framework UniformTypeIdentifiers
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import "Application.h"
|
#import "Application.h"
|
||||||
#import "WailsContext.h"
|
#import "WailsContext.h"
|
||||||
@@ -16,15 +16,17 @@ import "C"
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/internal/binding"
|
"github.com/wailsapp/wails/v2/internal/binding"
|
||||||
"github.com/wailsapp/wails/v2/internal/frontend"
|
"github.com/wailsapp/wails/v2/internal/frontend"
|
||||||
"github.com/wailsapp/wails/v2/internal/frontend/assetserver"
|
"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/internal/logger"
|
||||||
"github.com/wailsapp/wails/v2/pkg/options"
|
"github.com/wailsapp/wails/v2/pkg/options"
|
||||||
)
|
)
|
||||||
@@ -51,11 +53,10 @@ type Frontend struct {
|
|||||||
assets *assetserver.DesktopAssetServer
|
assets *assetserver.DesktopAssetServer
|
||||||
|
|
||||||
// main window handle
|
// main window handle
|
||||||
mainWindow *Window
|
mainWindow *Window
|
||||||
minWidth, minHeight, maxWidth, maxHeight int
|
bindings *binding.Bindings
|
||||||
bindings *binding.Bindings
|
dispatcher frontend.Dispatcher
|
||||||
dispatcher frontend.Dispatcher
|
servingFromDisk bool
|
||||||
servingFromDisk bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher) *Frontend {
|
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() {
|
func (f *Frontend) WindowFullscreen() {
|
||||||
f.mainWindow.SetMaxSize(0, 0)
|
|
||||||
f.mainWindow.SetMinSize(0, 0)
|
|
||||||
f.mainWindow.Fullscreen()
|
f.mainWindow.Fullscreen()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Frontend) WindowUnFullscreen() {
|
func (f *Frontend) WindowUnFullscreen() {
|
||||||
f.mainWindow.UnFullscreen()
|
f.mainWindow.UnFullscreen()
|
||||||
f.mainWindow.SetMaxSize(f.maxWidth, f.maxHeight)
|
|
||||||
f.mainWindow.SetMinSize(f.minWidth, f.minHeight)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Frontend) WindowShow() {
|
func (f *Frontend) WindowShow() {
|
||||||
@@ -195,13 +192,9 @@ func (f *Frontend) WindowUnminimise() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *Frontend) WindowSetMinSize(width int, height int) {
|
func (f *Frontend) WindowSetMinSize(width int, height int) {
|
||||||
f.minWidth = width
|
|
||||||
f.minHeight = height
|
|
||||||
f.mainWindow.SetMinSize(width, height)
|
f.mainWindow.SetMinSize(width, height)
|
||||||
}
|
}
|
||||||
func (f *Frontend) WindowSetMaxSize(width int, height int) {
|
func (f *Frontend) WindowSetMaxSize(width int, height int) {
|
||||||
f.maxWidth = width
|
|
||||||
f.maxHeight = height
|
|
||||||
f.mainWindow.SetMaxSize(width, height)
|
f.mainWindow.SetMaxSize(width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,10 +206,10 @@ func (f *Frontend) WindowSetRGBA(col *options.RGBA) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *Frontend) Quit() {
|
func (f *Frontend) Quit() {
|
||||||
f.mainWindow.Quit()
|
if f.frontendOptions.OnBeforeClose != nil && f.frontendOptions.OnBeforeClose(f.ctx) {
|
||||||
if f.frontendOptions.OnShutdown != nil {
|
return
|
||||||
f.frontendOptions.OnShutdown(f.ctx)
|
|
||||||
}
|
}
|
||||||
|
f.mainWindow.Quit()
|
||||||
}
|
}
|
||||||
|
|
||||||
type EventNotify struct {
|
type EventNotify struct {
|
||||||
@@ -246,23 +239,31 @@ func (f *Frontend) processMessage(message string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := f.dispatcher.ProcessMessage(message, f)
|
//if strings.HasPrefix(message, "systemevent:") {
|
||||||
if err != nil {
|
// f.processSystemEvent(message)
|
||||||
f.logger.Error(err.Error())
|
// return
|
||||||
f.Callback(result)
|
//}
|
||||||
return
|
|
||||||
}
|
go func() {
|
||||||
if result == "" {
|
result, err := f.dispatcher.ProcessMessage(message, f)
|
||||||
return
|
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) {
|
func (f *Frontend) Callback(message string) {
|
||||||
@@ -274,17 +275,34 @@ func (f *Frontend) ExecJS(js string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *Frontend) processRequest(r *request) {
|
func (f *Frontend) processRequest(r *request) {
|
||||||
url := C.GoString(r.url)
|
uri := C.GoString(r.url)
|
||||||
url = strings.TrimPrefix(url, "wails://wails")
|
|
||||||
if !strings.HasPrefix(url, "/") {
|
var _contents []byte
|
||||||
return
|
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 {
|
if err != nil {
|
||||||
f.logger.Error(err.Error())
|
if os.IsNotExist(err) {
|
||||||
//TODO: Handle errors
|
statusCode = 404
|
||||||
return
|
} else {
|
||||||
|
err = fmt.Errorf("Error processing request %s: %w", uri, err)
|
||||||
|
f.logger.Error(err.Error())
|
||||||
|
statusCode = 500
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var data unsafe.Pointer
|
var data unsafe.Pointer
|
||||||
if _contents != nil {
|
if _contents != nil {
|
||||||
data = unsafe.Pointer(&_contents[0])
|
data = unsafe.Pointer(&_contents[0])
|
||||||
@@ -292,9 +310,25 @@ func (f *Frontend) processRequest(r *request) {
|
|||||||
mimetype := C.CString(_mimetype)
|
mimetype := C.CString(_mimetype)
|
||||||
defer C.free(unsafe.Pointer(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
|
//export processMessage
|
||||||
func processMessage(message *C.char) {
|
func processMessage(message *C.char) {
|
||||||
goMessage := C.GoString(message)
|
goMessage := C.GoString(message)
|
||||||
|
|||||||
@@ -200,9 +200,9 @@ unsigned int _Users_username_Pictures_SaltBae_png_len = 1863;
|
|||||||
|
|
||||||
int main(int argc, const char * argv[]) {
|
int main(int argc, const char * argv[]) {
|
||||||
// insert code here...
|
// insert code here...
|
||||||
int frameless = 1;
|
int frameless = 0;
|
||||||
int resizable = 0;
|
int resizable = 1;
|
||||||
int fullscreen = 0;
|
int fullscreen = 1;
|
||||||
int fullSizeContent = 1;
|
int fullSizeContent = 1;
|
||||||
int hideTitleBar = 0;
|
int hideTitleBar = 0;
|
||||||
int titlebarAppearsTransparent = 0;
|
int titlebarAppearsTransparent = 0;
|
||||||
@@ -215,7 +215,10 @@ int main(int argc, const char * argv[]) {
|
|||||||
const char* appearance = "NSAppearanceNameDarkAqua";
|
const char* appearance = "NSAppearanceNameDarkAqua";
|
||||||
int windowIsTranslucent = 1;
|
int windowIsTranslucent = 1;
|
||||||
int debug = 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);
|
SetRGBA(result, 255, 0, 0, 255);
|
||||||
void *m = NewMenu("");
|
void *m = NewMenu("");
|
||||||
SetAbout(result, "Fake title", "I am a description", _Users_username_Pictures_SaltBae_png, _Users_username_Pictures_SaltBae_png_len);
|
SetAbout(result, "Fake title", "I am a description", _Users_username_Pictures_SaltBae_png, _Users_username_Pictures_SaltBae_png_len);
|
||||||
@@ -228,7 +231,7 @@ int main(int argc, const char * argv[]) {
|
|||||||
AppendSubmenu(m, submenu);
|
AppendSubmenu(m, submenu);
|
||||||
UpdateMenuItem(menuITem, 1);
|
UpdateMenuItem(menuITem, 1);
|
||||||
SetAsApplicationMenu(result, m);
|
SetAsApplicationMenu(result, m);
|
||||||
SetPosition(result, 100, 100);
|
// SetPosition(result, 100, 100);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
//go:build darwin
|
||||||
|
// +build darwin
|
||||||
|
|
||||||
package darwin
|
package darwin
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -56,6 +59,10 @@ func NewWindow(frontendOptions *options.App, debugMode bool) *Window {
|
|||||||
|
|
||||||
width := C.int(frontendOptions.Width)
|
width := C.int(frontendOptions.Width)
|
||||||
height := C.int(frontendOptions.Height)
|
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))
|
windowStartState := C.int(int(frontendOptions.WindowStartState))
|
||||||
|
|
||||||
title = c.String(frontendOptions.Title)
|
title = c.String(frontendOptions.Title)
|
||||||
@@ -77,7 +84,8 @@ func NewWindow(frontendOptions *options.App, debugMode bool) *Window {
|
|||||||
}
|
}
|
||||||
var context *C.WailsContext = C.Create(title, width, height, frameless, resizable, fullscreen, fullSizeContent,
|
var context *C.WailsContext = C.Create(title, width, height, frameless, resizable, fullscreen, fullSizeContent,
|
||||||
hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent,
|
hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent,
|
||||||
alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, debug, windowStartState, startsHidden)
|
alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, debug, windowStartState, startsHidden,
|
||||||
|
minWidth, minHeight, maxWidth, maxHeight)
|
||||||
|
|
||||||
// Create menu
|
// Create menu
|
||||||
result := &Window{
|
result := &Window{
|
||||||
@@ -104,9 +112,6 @@ func NewWindow(frontendOptions *options.App, debugMode bool) *Window {
|
|||||||
result.SetApplicationMenu(frontendOptions.Menu)
|
result.SetApplicationMenu(frontendOptions.Menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
result.SetMinSize(frontendOptions.MinWidth, frontendOptions.MinHeight)
|
|
||||||
result.SetMaxSize(frontendOptions.MaxWidth, frontendOptions.MaxHeight)
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,16 +168,10 @@ func (w *Window) UnMinimise() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *Window) SetMinSize(width int, height int) {
|
func (w *Window) SetMinSize(width int, height int) {
|
||||||
if width == 0 && height == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
C.SetMinSize(w.context, C.int(width), C.int(height))
|
C.SetMinSize(w.context, C.int(width), C.int(height))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Window) SetMaxSize(width int, height int) {
|
func (w *Window) SetMaxSize(width int, height int) {
|
||||||
if width == 0 && height == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
C.SetMaxSize(w.context, C.int(width), C.int(height))
|
C.SetMaxSize(w.context, C.int(width), C.int(height))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
17
v2/internal/frontend/desktop/desktop_linux.go
Normal 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)
|
||||||
|
}
|
||||||
12
v2/internal/frontend/desktop/linux/browser.go
Normal 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)
|
||||||
|
}
|
||||||
26
v2/internal/frontend/desktop/linux/dialog.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
//go:build linux
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package linux
|
||||||
|
|
||||||
|
import "github.com/wailsapp/wails/v2/internal/frontend"
|
||||||
|
|
||||||
|
func (f *Frontend) OpenFileDialog(dialogOptions frontend.OpenDialogOptions) (string, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
358
v2/internal/frontend/desktop/linux/frontend.go
Normal file
@@ -0,0 +1,358 @@
|
|||||||
|
//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"
|
||||||
|
"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 {
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
id := int(cid)
|
||||||
|
fn := dispatchCallbacks[id]
|
||||||
|
if fn != nil {
|
||||||
|
go 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)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO How to return 404/500 errors to webkit?
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
14
v2/internal/frontend/desktop/linux/menu.go
Normal 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")
|
||||||
|
}
|
||||||
410
v2/internal/frontend/desktop/linux/window.go
Normal file
@@ -0,0 +1,410 @@
|
|||||||
|
//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"
|
||||||
|
#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*)
|
||||||
|
{
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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*)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"github.com/wailsapp/wails/v2/pkg/options"
|
||||||
|
"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.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()
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -19,6 +20,7 @@ import (
|
|||||||
"github.com/wailsapp/wails/v2/internal/binding"
|
"github.com/wailsapp/wails/v2/internal/binding"
|
||||||
"github.com/wailsapp/wails/v2/internal/frontend"
|
"github.com/wailsapp/wails/v2/internal/frontend"
|
||||||
"github.com/wailsapp/wails/v2/internal/frontend/assetserver"
|
"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/internal/logger"
|
||||||
"github.com/wailsapp/wails/v2/pkg/options"
|
"github.com/wailsapp/wails/v2/pkg/options"
|
||||||
)
|
)
|
||||||
@@ -43,6 +45,8 @@ type Frontend struct {
|
|||||||
bindings *binding.Bindings
|
bindings *binding.Bindings
|
||||||
dispatcher frontend.Dispatcher
|
dispatcher frontend.Dispatcher
|
||||||
servingFromDisk bool
|
servingFromDisk bool
|
||||||
|
|
||||||
|
hasStarted bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher) *Frontend {
|
func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher) *Frontend {
|
||||||
@@ -168,11 +172,17 @@ func (f *Frontend) WindowFullscreen() {
|
|||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
f.mainWindow.SetMaxSize(0, 0)
|
f.mainWindow.SetMaxSize(0, 0)
|
||||||
f.mainWindow.SetMinSize(0, 0)
|
f.mainWindow.SetMinSize(0, 0)
|
||||||
|
if f.frontendOptions.Frameless && f.frontendOptions.DisableResize == false {
|
||||||
|
f.ExecJS("window.wails.flags.enableResize = false;")
|
||||||
|
}
|
||||||
f.mainWindow.Fullscreen()
|
f.mainWindow.Fullscreen()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Frontend) WindowUnFullscreen() {
|
func (f *Frontend) WindowUnFullscreen() {
|
||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
|
if f.frontendOptions.Frameless && f.frontendOptions.DisableResize == false {
|
||||||
|
f.ExecJS("window.wails.flags.enableResize = true;")
|
||||||
|
}
|
||||||
f.mainWindow.UnFullscreen()
|
f.mainWindow.UnFullscreen()
|
||||||
f.mainWindow.SetMaxSize(f.maxWidth, f.maxHeight)
|
f.mainWindow.SetMaxSize(f.maxWidth, f.maxHeight)
|
||||||
f.mainWindow.SetMinSize(f.minWidth, f.minHeight)
|
f.mainWindow.SetMinSize(f.minWidth, f.minHeight)
|
||||||
@@ -223,7 +233,7 @@ func (f *Frontend) WindowSetRGBA(col *options.RGBA) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
f.mainWindow.Dispatch(func() {
|
f.mainWindow.Invoke(func() {
|
||||||
controller := f.chromium.GetController()
|
controller := f.chromium.GetController()
|
||||||
controller2 := controller.GetICoreWebView2Controller2()
|
controller2 := controller.GetICoreWebView2Controller2()
|
||||||
|
|
||||||
@@ -251,7 +261,12 @@ func (f *Frontend) WindowSetRGBA(col *options.RGBA) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *Frontend) Quit() {
|
func (f *Frontend) Quit() {
|
||||||
winc.Exit()
|
if f.frontendOptions.OnBeforeClose != nil && f.frontendOptions.OnBeforeClose(f.ctx) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Exit must be called on the Main-Thread. It calls PostQuitMessage which sends the WM_QUIT message to the thread's
|
||||||
|
// message queue and our message queue runs on the Main-Thread.
|
||||||
|
f.mainWindow.Invoke(winc.Exit)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Frontend) setupChromium() {
|
func (f *Frontend) setupChromium() {
|
||||||
@@ -325,33 +340,66 @@ func (f *Frontend) processRequest(req *edge.ICoreWebView2WebResourceRequest, arg
|
|||||||
//Get the request
|
//Get the request
|
||||||
uri, _ := req.GetUri()
|
uri, _ := req.GetUri()
|
||||||
|
|
||||||
// Translate URI
|
var content []byte
|
||||||
uri = strings.TrimPrefix(uri, "file://wails")
|
var mimeType string
|
||||||
if !strings.HasPrefix(uri, "/") {
|
|
||||||
return
|
// Translate URI to file
|
||||||
|
file, match, err := common.TranslateUriToFile(uri, "file", "wails")
|
||||||
|
if err == nil {
|
||||||
|
if !match {
|
||||||
|
// In this case we should let the WebView2 handle the request with it's default handler
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load file from asset store
|
||||||
|
content, mimeType, err = f.assets.Load(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load file from asset store
|
statusCode := 200
|
||||||
content, mimeType, err := f.assets.Load(uri)
|
reasonPhrase := "OK"
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
if os.IsNotExist(err) {
|
||||||
|
statusCode = 404
|
||||||
|
reasonPhrase = "Not Found"
|
||||||
|
} else {
|
||||||
|
err = fmt.Errorf("Error processing request %s: %w", uri, err)
|
||||||
|
f.logger.Error(err.Error())
|
||||||
|
statusCode = 500
|
||||||
|
reasonPhrase = "Internal Server Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
headers := []string{}
|
||||||
|
if mimeType != "" {
|
||||||
|
headers = append(headers, "Content-Type: "+mimeType)
|
||||||
|
}
|
||||||
|
if content != nil && f.servingFromDisk {
|
||||||
|
headers = append(headers, "Pragma: no-cache")
|
||||||
}
|
}
|
||||||
|
|
||||||
env := f.chromium.Environment()
|
env := f.chromium.Environment()
|
||||||
headers := "Content-Type: " + mimeType
|
response, err := env.CreateWebResourceResponse(content, statusCode, reasonPhrase, strings.Join(headers, "\n"))
|
||||||
if f.servingFromDisk {
|
|
||||||
headers += "\nPragma: no-cache"
|
|
||||||
}
|
|
||||||
response, err := env.CreateWebResourceResponse(content, 200, "OK", headers)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer response.Release()
|
||||||
|
|
||||||
// Send response back
|
// Send response back
|
||||||
err = args.PutResponse(response)
|
err = args.PutResponse(response)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return
|
}
|
||||||
|
|
||||||
|
var edgeMap = map[string]uintptr{
|
||||||
|
"n-resize": w32.HTTOP,
|
||||||
|
"ne-resize": w32.HTTOPRIGHT,
|
||||||
|
"e-resize": w32.HTRIGHT,
|
||||||
|
"se-resize": w32.HTBOTTOMRIGHT,
|
||||||
|
"s-resize": w32.HTBOTTOM,
|
||||||
|
"sw-resize": w32.HTBOTTOMLEFT,
|
||||||
|
"w-resize": w32.HTLEFT,
|
||||||
|
"nw-resize": w32.HTTOPLEFT,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Frontend) processMessage(message string) {
|
func (f *Frontend) processMessage(message string) {
|
||||||
@@ -364,27 +412,45 @@ func (f *Frontend) processMessage(message string) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
result, err := f.dispatcher.ProcessMessage(message, f)
|
if strings.HasPrefix(message, "resize:") {
|
||||||
if err != nil {
|
if !f.mainWindow.IsFullScreen() {
|
||||||
f.logger.Error(err.Error())
|
sl := strings.Split(message, ":")
|
||||||
f.Callback(result)
|
if len(sl) != 2 {
|
||||||
return
|
f.logger.Info("Unknown message returned from dispatcher: %+v", message)
|
||||||
}
|
return
|
||||||
if result == "" {
|
}
|
||||||
|
edge := edgeMap[sl[1]]
|
||||||
|
err := f.startResize(edge)
|
||||||
|
if err != nil {
|
||||||
|
f.logger.Error(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch result[0] {
|
go func() {
|
||||||
case 'c':
|
result, err := f.dispatcher.ProcessMessage(message, f)
|
||||||
// Callback from a method call
|
if err != nil {
|
||||||
f.Callback(result[1:])
|
f.logger.Error(err.Error())
|
||||||
default:
|
f.Callback(result)
|
||||||
f.logger.Info("Unknown message returned from dispatcher: %+v", 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) {
|
func (f *Frontend) Callback(message string) {
|
||||||
f.mainWindow.Dispatch(func() {
|
f.mainWindow.Invoke(func() {
|
||||||
f.chromium.Eval(`window.wails.Callback(` + strconv.Quote(message) + `);`)
|
f.chromium.Eval(`window.wails.Callback(` + strconv.Quote(message) + `);`)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -397,8 +463,16 @@ func (f *Frontend) startDrag() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *Frontend) startResize(border uintptr) error {
|
||||||
|
if !w32.ReleaseCapture() {
|
||||||
|
return fmt.Errorf("unable to release mouse capture")
|
||||||
|
}
|
||||||
|
w32.SendMessage(f.mainWindow.Handle(), w32.WM_NCLBUTTONDOWN, border, 0)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (f *Frontend) ExecJS(js string) {
|
func (f *Frontend) ExecJS(js string) {
|
||||||
f.mainWindow.Dispatch(func() {
|
f.mainWindow.Invoke(func() {
|
||||||
f.chromium.Eval(js)
|
f.chromium.Eval(js)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -408,6 +482,15 @@ func (f *Frontend) navigationCompleted(sender *edge.ICoreWebView2, args *edge.IC
|
|||||||
go f.frontendOptions.OnDomReady(f.ctx)
|
go f.frontendOptions.OnDomReady(f.ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if f.frontendOptions.Frameless && f.frontendOptions.DisableResize == false {
|
||||||
|
f.ExecJS("window.wails.flags.enableResize = true;")
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.hasStarted {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
f.hasStarted = true
|
||||||
|
|
||||||
// Hack to make it visible: https://github.com/MicrosoftEdge/WebView2Feedback/issues/1077#issuecomment-825375026
|
// Hack to make it visible: https://github.com/MicrosoftEdge/WebView2Feedback/issues/1077#issuecomment-825375026
|
||||||
err := f.chromium.Hide()
|
err := f.chromium.Hide()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -7,15 +7,12 @@ import (
|
|||||||
"github.com/leaanthony/winc/w32"
|
"github.com/leaanthony/winc/w32"
|
||||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||||
"github.com/wailsapp/wails/v2/pkg/options"
|
"github.com/wailsapp/wails/v2/pkg/options"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Window struct {
|
type Window struct {
|
||||||
winc.Form
|
winc.Form
|
||||||
frontendOptions *options.App
|
frontendOptions *options.App
|
||||||
applicationMenu *menu.Menu
|
applicationMenu *menu.Menu
|
||||||
m sync.Mutex
|
|
||||||
dispatchq []func()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWindow(parent winc.Controller, appoptions *options.App) *Window {
|
func NewWindow(parent winc.Controller, appoptions *options.App) *Window {
|
||||||
@@ -37,6 +34,9 @@ func NewWindow(parent winc.Controller, appoptions *options.App) *Window {
|
|||||||
var dwStyle = w32.WS_OVERLAPPEDWINDOW
|
var dwStyle = w32.WS_OVERLAPPEDWINDOW
|
||||||
if appoptions.Frameless {
|
if appoptions.Frameless {
|
||||||
dwStyle = w32.WS_POPUP
|
dwStyle = w32.WS_POPUP
|
||||||
|
if winoptions := appoptions.Windows; winoptions != nil && winoptions.EnableFramelessBorder {
|
||||||
|
dwStyle |= w32.WS_BORDER
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
winc.RegClassOnlyOnce("wailsWindow")
|
winc.RegClassOnlyOnce("wailsWindow")
|
||||||
@@ -86,32 +86,5 @@ func NewWindow(parent winc.Controller, appoptions *options.App) *Window {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *Window) Run() int {
|
func (w *Window) Run() int {
|
||||||
var m w32.MSG
|
return winc.RunMainLoop()
|
||||||
|
|
||||||
for w32.GetMessage(&m, 0, 0, 0) != 0 {
|
|
||||||
if m.Message == w32.WM_APP {
|
|
||||||
// Credit: https://github.com/jchv/go-webview2
|
|
||||||
w.m.Lock()
|
|
||||||
q := append([]func(){}, w.dispatchq...)
|
|
||||||
w.dispatchq = []func(){}
|
|
||||||
w.m.Unlock()
|
|
||||||
for _, v := range q {
|
|
||||||
v()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !w.PreTranslateMessage(&m) {
|
|
||||||
w32.TranslateMessage(&m)
|
|
||||||
w32.DispatchMessage(&m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
w32.GdiplusShutdown()
|
|
||||||
return int(m.WParam)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Window) Dispatch(f func()) {
|
|
||||||
w.m.Lock()
|
|
||||||
w.dispatchq = append(w.dispatchq, f)
|
|
||||||
w.m.Unlock()
|
|
||||||
w32.PostMainThreadMessage(w32.WM_APP, 0, 0)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -50,6 +49,11 @@ func (d *DevWebServer) WindowReload() {
|
|||||||
func (d *DevWebServer) Run(ctx context.Context) error {
|
func (d *DevWebServer) Run(ctx context.Context) error {
|
||||||
d.ctx = ctx
|
d.ctx = ctx
|
||||||
|
|
||||||
|
assetdir, _ := ctx.Value("assetdir").(string)
|
||||||
|
d.server.Get("/wails/assetdir", func(fctx *fiber.Ctx) error {
|
||||||
|
return fctx.SendString(assetdir)
|
||||||
|
})
|
||||||
|
|
||||||
d.server.Get("/wails/reload", func(fctx *fiber.Ctx) error {
|
d.server.Get("/wails/reload", func(fctx *fiber.Ctx) error {
|
||||||
d.WindowReload()
|
d.WindowReload()
|
||||||
d.desktopFrontend.WindowReload()
|
d.desktopFrontend.WindowReload()
|
||||||
@@ -100,25 +104,14 @@ func (d *DevWebServer) Run(ctx context.Context) error {
|
|||||||
_devServerURL := ctx.Value("devserverurl")
|
_devServerURL := ctx.Value("devserverurl")
|
||||||
if _devServerURL == "http://localhost:34115" {
|
if _devServerURL == "http://localhost:34115" {
|
||||||
// Setup internal dev server
|
// Setup internal dev server
|
||||||
_assetdir := ctx.Value("assetdir")
|
bindingsJSON, err := d.appBindings.ToJSON()
|
||||||
if _assetdir == nil {
|
if err != nil {
|
||||||
return fmt.Errorf("no assetdir provided")
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
if _assetdir != nil {
|
|
||||||
assetdir := _assetdir.(string)
|
d.assetServer, err = assetserver.NewBrowserAssetServer(ctx, d.appoptions.Assets, bindingsJSON)
|
||||||
bindingsJSON, err := d.appBindings.ToJSON()
|
if err != nil {
|
||||||
if err != nil {
|
log.Fatal(err)
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
d.assetServer, err = assetserver.NewBrowserAssetServer(assetdir, bindingsJSON, d.appoptions)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
absdir, err := filepath.Abs(assetdir)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
d.LogDebug("Serving assets from: %s", absdir)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
d.server.Get("*", d.loadAsset)
|
d.server.Get("*", d.loadAsset)
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ type OpenDialogOptions struct {
|
|||||||
DefaultFilename string
|
DefaultFilename string
|
||||||
Title string
|
Title string
|
||||||
Filters []FileFilter
|
Filters []FileFilter
|
||||||
AllowFiles bool
|
|
||||||
AllowDirectories bool
|
|
||||||
ShowHiddenFiles bool
|
ShowHiddenFiles bool
|
||||||
CanCreateDirectories bool
|
CanCreateDirectories bool
|
||||||
ResolvesAliases bool
|
ResolvesAliases bool
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ The electron alternative for Go
|
|||||||
return obj;
|
return obj;
|
||||||
};
|
};
|
||||||
let windows = _deeptest(["chrome", "webview", "postMessage"]);
|
let windows = _deeptest(["chrome", "webview", "postMessage"]);
|
||||||
let mac = _deeptest(["webkit", "messageHandlers", "external", "postMessage"]);
|
let mac_linux = _deeptest(["webkit", "messageHandlers", "external", "postMessage"]);
|
||||||
|
|
||||||
if (!windows && !mac) {
|
if (!windows && !mac_linux) {
|
||||||
console.error("Unsupported Platform");
|
console.error("Unsupported Platform");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,7 @@ The electron alternative for Go
|
|||||||
if (windows) {
|
if (windows) {
|
||||||
window.WailsInvoke = (message) => window.chrome.webview.postMessage(message);
|
window.WailsInvoke = (message) => window.chrome.webview.postMessage(message);
|
||||||
}
|
}
|
||||||
if (mac) {
|
if (mac_linux) {
|
||||||
window.WailsInvoke = (message) => window.webkit.messageHandlers.external.postMessage(message);
|
window.WailsInvoke = (message) => window.webkit.messageHandlers.external.postMessage(message);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
@@ -43,6 +43,8 @@ window.wails = {
|
|||||||
flags: {
|
flags: {
|
||||||
disableScrollbarDrag: false,
|
disableScrollbarDrag: false,
|
||||||
disableWailsDefaultContextMenu: false,
|
disableWailsDefaultContextMenu: false,
|
||||||
|
enableResize: false,
|
||||||
|
defaultCursor: null
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -60,6 +62,15 @@ if (ENV === 0) {
|
|||||||
// Setup drag handler
|
// Setup drag handler
|
||||||
// Based on code from: https://github.com/patr0nus/DeskGap
|
// Based on code from: https://github.com/patr0nus/DeskGap
|
||||||
window.addEventListener('mousedown', (e) => {
|
window.addEventListener('mousedown', (e) => {
|
||||||
|
|
||||||
|
// Check for resizing
|
||||||
|
if (window.wails.flags.resizeEdge) {
|
||||||
|
window.WailsInvoke("resize:" + window.wails.flags.resizeEdge);
|
||||||
|
e.preventDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for dragging
|
||||||
let currentElement = e.target;
|
let currentElement = e.target;
|
||||||
while (currentElement != null) {
|
while (currentElement != null) {
|
||||||
if (currentElement.hasAttribute('data-wails-no-drag')) {
|
if (currentElement.hasAttribute('data-wails-no-drag')) {
|
||||||
@@ -79,6 +90,40 @@ window.addEventListener('mousedown', (e) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function setResize(cursor) {
|
||||||
|
document.body.style.cursor = cursor || window.wails.flags.defaultCursor;
|
||||||
|
window.wails.flags.resizeEdge = cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('mousemove', function (e) {
|
||||||
|
if (!window.wails.flags.enableResize) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (window.wails.flags.defaultCursor == null) {
|
||||||
|
window.wails.flags.defaultCursor = document.body.style.cursor;
|
||||||
|
}
|
||||||
|
if (window.outerWidth - e.clientX < 16 && window.outerHeight - e.clientY < 16) {
|
||||||
|
document.body.style.cursor = "se-resize";
|
||||||
|
}
|
||||||
|
let rightBorder = window.outerWidth - e.clientX < 16;
|
||||||
|
let leftBorder = e.clientX < 16;
|
||||||
|
let topBorder = e.clientY < 16;
|
||||||
|
let bottomBorder = window.outerHeight - e.clientY < 16;
|
||||||
|
|
||||||
|
// If we aren't on an edge, but were, reset the cursor to default
|
||||||
|
if (!leftBorder && !rightBorder && !topBorder && !bottomBorder && window.wails.flags.resizeEdge !== undefined) {
|
||||||
|
setResize();
|
||||||
|
} else if (rightBorder && bottomBorder) setResize("se-resize");
|
||||||
|
else if (leftBorder && bottomBorder) setResize("sw-resize");
|
||||||
|
else if (leftBorder && topBorder) setResize("nw-resize");
|
||||||
|
else if (topBorder && rightBorder) setResize("ne-resize");
|
||||||
|
else if (leftBorder) setResize("w-resize");
|
||||||
|
else if (topBorder) setResize("n-resize");
|
||||||
|
else if (bottomBorder) setResize("s-resize");
|
||||||
|
else if (rightBorder) setResize("e-resize");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
// Setup context menu hook
|
// Setup context menu hook
|
||||||
window.addEventListener('contextmenu', function (e) {
|
window.addEventListener('contextmenu', function (e) {
|
||||||
if (window.wails.flags.disableWailsDefaultContextMenu) {
|
if (window.wails.flags.disableWailsDefaultContextMenu) {
|
||||||
|
|||||||
@@ -14,14 +14,17 @@ import Overlay from "./Overlay.svelte";
|
|||||||
import {hideOverlay, showOverlay} from "./store";
|
import {hideOverlay, showOverlay} from "./store";
|
||||||
|
|
||||||
let components = {};
|
let components = {};
|
||||||
window.ipcCallbacks = [];
|
|
||||||
window.ipcCallbackNames = [];
|
|
||||||
|
|
||||||
window.awaitIPC = (name, callback) => {
|
let wailsInvokeInternal = null;
|
||||||
if (!window.ipcCallbacks) return callback;
|
let messageQueue = [];
|
||||||
log("Queuing '" + name + "' for execution once ipc ready.");
|
|
||||||
window.ipcCallbackNames.push(name);
|
window.WailsInvoke = (message) => {
|
||||||
window.ipcCallbacks.push(callback);
|
if (!wailsInvokeInternal) {
|
||||||
|
console.log("Queueing: " + message);
|
||||||
|
messageQueue.push(message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wailsInvokeInternal(message);
|
||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener('DOMContentLoaded', () => {
|
window.addEventListener('DOMContentLoaded', () => {
|
||||||
@@ -47,15 +50,14 @@ window.onbeforeunload = function () {
|
|||||||
connect();
|
connect();
|
||||||
|
|
||||||
function setupIPCBridge() {
|
function setupIPCBridge() {
|
||||||
window.WailsInvoke = (message) => {
|
wailsInvokeInternal = (message) => {
|
||||||
websocket.send(message);
|
websocket.send(message);
|
||||||
};
|
};
|
||||||
for (let i = 0; i < window.ipcCallbacks.length; i++) {
|
for (let i = 0; i < messageQueue.length; i++) {
|
||||||
log("Executing JS: " + window.ipcCallbackNames[i]);
|
console.log("sending queued message: " + messageQueue[i]);
|
||||||
window.ipcCallbacks[i]();
|
window.WailsInvoke(messageQueue[i]);
|
||||||
}
|
}
|
||||||
delete window.ipcCallbacks;
|
messageQueue = [];
|
||||||
delete window.ipcCallbackNames;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handles incoming websocket connections
|
// Handles incoming websocket connections
|
||||||
|
|||||||
@@ -11,8 +11,8 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"esbuild": "^0.12.17",
|
"esbuild": "^0.12.17",
|
||||||
|
"esbuild-svelte": "^0.5.6",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"svelte": "^3.42.2",
|
"svelte": "^3.42.2"
|
||||||
"esbuild-svelte": "^0.5.6"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
//go:build darwin || windows
|
|
||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
import _ "embed"
|
import _ "embed"
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
(()=>{(function(){let o=function(e){for(var s=window[e.shift()];s&&e.length;)s=s[e.shift()];return s},t=o(["chrome","webview","postMessage"]),n=o(["webkit","messageHandlers","external","postMessage"]);if(!t&&!n){console.error("Unsupported Platform");return}t&&(window.WailsInvoke=e=>window.chrome.webview.postMessage(e)),n&&(window.WailsInvoke=e=>window.webkit.messageHandlers.external.postMessage(e))})();})();
|
(()=>{(function(){let n=function(e){for(var s=window[e.shift()];s&&e.length;)s=s[e.shift()];return s},o=n(["chrome","webview","postMessage"]),t=n(["webkit","messageHandlers","external","postMessage"]);if(!o&&!t){console.error("Unsupported Platform");return}o&&(window.WailsInvoke=e=>window.chrome.webview.postMessage(e)),t&&(window.WailsInvoke=e=>window.webkit.messageHandlers.external.postMessage(e))})();})();
|
||||||
|
|||||||
762
v2/internal/frontend/runtime/package-lock.json
generated
@@ -1,8 +1,768 @@
|
|||||||
{
|
{
|
||||||
"name": "runtime",
|
"name": "runtime",
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"esbuild": "^0.12.17",
|
||||||
|
"npm-run-all": "^4.1.5",
|
||||||
|
"svelte": "^3.42.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ansi-styles": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"color-convert": "^1.9.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/balanced-match": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/brace-expansion": {
|
||||||
|
"version": "1.1.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
|
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"balanced-match": "^1.0.0",
|
||||||
|
"concat-map": "0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/call-bind": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"function-bind": "^1.1.1",
|
||||||
|
"get-intrinsic": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/chalk": {
|
||||||
|
"version": "2.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||||
|
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": "^3.2.1",
|
||||||
|
"escape-string-regexp": "^1.0.5",
|
||||||
|
"supports-color": "^5.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/color-convert": {
|
||||||
|
"version": "1.9.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||||
|
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"color-name": "1.1.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/color-name": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||||
|
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/concat-map": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
|
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/cross-spawn": {
|
||||||
|
"version": "6.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
|
||||||
|
"integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"nice-try": "^1.0.4",
|
||||||
|
"path-key": "^2.0.1",
|
||||||
|
"semver": "^5.5.0",
|
||||||
|
"shebang-command": "^1.2.0",
|
||||||
|
"which": "^1.2.9"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/define-properties": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
|
||||||
|
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"object-keys": "^1.0.12"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/error-ex": {
|
||||||
|
"version": "1.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
|
||||||
|
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"is-arrayish": "^0.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-abstract": {
|
||||||
|
"version": "1.18.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz",
|
||||||
|
"integrity": "sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.2",
|
||||||
|
"es-to-primitive": "^1.2.1",
|
||||||
|
"function-bind": "^1.1.1",
|
||||||
|
"get-intrinsic": "^1.1.1",
|
||||||
|
"has": "^1.0.3",
|
||||||
|
"has-symbols": "^1.0.2",
|
||||||
|
"internal-slot": "^1.0.3",
|
||||||
|
"is-callable": "^1.2.3",
|
||||||
|
"is-negative-zero": "^2.0.1",
|
||||||
|
"is-regex": "^1.1.3",
|
||||||
|
"is-string": "^1.0.6",
|
||||||
|
"object-inspect": "^1.11.0",
|
||||||
|
"object-keys": "^1.1.1",
|
||||||
|
"object.assign": "^4.1.2",
|
||||||
|
"string.prototype.trimend": "^1.0.4",
|
||||||
|
"string.prototype.trimstart": "^1.0.4",
|
||||||
|
"unbox-primitive": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-to-primitive": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"is-callable": "^1.1.4",
|
||||||
|
"is-date-object": "^1.0.1",
|
||||||
|
"is-symbol": "^1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/esbuild": {
|
||||||
|
"version": "0.12.17",
|
||||||
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.17.tgz",
|
||||||
|
"integrity": "sha512-GshKJyVYUnlSXIZj/NheC2O0Kblh42CS7P1wJyTbbIHevTG4jYMS9NNw8EOd8dDWD0dzydYHS01MpZoUcQXB4g==",
|
||||||
|
"dev": true,
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"bin": {
|
||||||
|
"esbuild": "bin/esbuild"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/escape-string-regexp": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||||
|
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/function-bind": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/get-intrinsic": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"function-bind": "^1.1.1",
|
||||||
|
"has": "^1.0.3",
|
||||||
|
"has-symbols": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/graceful-fs": {
|
||||||
|
"version": "4.2.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
|
||||||
|
"integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/has": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"function-bind": "^1.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/has-bigints": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/has-flag": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/has-symbols": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/hosted-git-info": {
|
||||||
|
"version": "2.8.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
|
||||||
|
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/internal-slot": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"get-intrinsic": "^1.1.0",
|
||||||
|
"has": "^1.0.3",
|
||||||
|
"side-channel": "^1.0.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-arrayish": {
|
||||||
|
"version": "0.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
|
||||||
|
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/is-bigint": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/is-boolean-object": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-callable": {
|
||||||
|
"version": "1.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz",
|
||||||
|
"integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-core-module": {
|
||||||
|
"version": "2.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz",
|
||||||
|
"integrity": "sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"has": "^1.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-date-object": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-negative-zero": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-number-object": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-regex": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz",
|
||||||
|
"integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.2",
|
||||||
|
"has-symbols": "^1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-string": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-symbol": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"has-symbols": "^1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/isexe": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/json-parse-better-errors": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/load-json-file": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
|
||||||
|
"integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"graceful-fs": "^4.1.2",
|
||||||
|
"parse-json": "^4.0.0",
|
||||||
|
"pify": "^3.0.0",
|
||||||
|
"strip-bom": "^3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/memorystream": {
|
||||||
|
"version": "0.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
|
||||||
|
"integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/minimatch": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"brace-expansion": "^1.1.7"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nice-try": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/normalize-package-data": {
|
||||||
|
"version": "2.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
|
||||||
|
"integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"hosted-git-info": "^2.1.4",
|
||||||
|
"resolve": "^1.10.0",
|
||||||
|
"semver": "2 || 3 || 4 || 5",
|
||||||
|
"validate-npm-package-license": "^3.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/npm-run-all": {
|
||||||
|
"version": "4.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz",
|
||||||
|
"integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": "^3.2.1",
|
||||||
|
"chalk": "^2.4.1",
|
||||||
|
"cross-spawn": "^6.0.5",
|
||||||
|
"memorystream": "^0.3.1",
|
||||||
|
"minimatch": "^3.0.4",
|
||||||
|
"pidtree": "^0.3.0",
|
||||||
|
"read-pkg": "^3.0.0",
|
||||||
|
"shell-quote": "^1.6.1",
|
||||||
|
"string.prototype.padend": "^3.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"npm-run-all": "bin/npm-run-all/index.js",
|
||||||
|
"run-p": "bin/run-p/index.js",
|
||||||
|
"run-s": "bin/run-s/index.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/object-inspect": {
|
||||||
|
"version": "1.11.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz",
|
||||||
|
"integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/object-keys": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/object.assign": {
|
||||||
|
"version": "4.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
|
||||||
|
"integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.0",
|
||||||
|
"define-properties": "^1.1.3",
|
||||||
|
"has-symbols": "^1.0.1",
|
||||||
|
"object-keys": "^1.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/parse-json": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
|
||||||
|
"integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"error-ex": "^1.3.1",
|
||||||
|
"json-parse-better-errors": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/path-key": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
|
||||||
|
"integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/path-parse": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||||
|
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/path-type": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"pify": "^3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pidtree": {
|
||||||
|
"version": "0.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz",
|
||||||
|
"integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==",
|
||||||
|
"dev": true,
|
||||||
|
"bin": {
|
||||||
|
"pidtree": "bin/pidtree.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pify": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/read-pkg": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"load-json-file": "^4.0.0",
|
||||||
|
"normalize-package-data": "^2.3.2",
|
||||||
|
"path-type": "^3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/resolve": {
|
||||||
|
"version": "1.20.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
|
||||||
|
"integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"is-core-module": "^2.2.0",
|
||||||
|
"path-parse": "^1.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/semver": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||||
|
"dev": true,
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/shebang-command": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
|
||||||
|
"integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"shebang-regex": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/shebang-regex": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/shell-quote": {
|
||||||
|
"version": "1.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz",
|
||||||
|
"integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/side-channel": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.0",
|
||||||
|
"get-intrinsic": "^1.0.2",
|
||||||
|
"object-inspect": "^1.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/spdx-correct": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"spdx-expression-parse": "^3.0.0",
|
||||||
|
"spdx-license-ids": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/spdx-exceptions": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/spdx-expression-parse": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"spdx-exceptions": "^2.1.0",
|
||||||
|
"spdx-license-ids": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/spdx-license-ids": {
|
||||||
|
"version": "3.0.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz",
|
||||||
|
"integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/string.prototype.padend": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-/AQFLdYvePENU3W5rgurfWSMU6n+Ww8n/3cUt7E+vPBB/D7YDG8x+qjoFs4M/alR2bW7Qg6xMjVwWUOvuQ0XpQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.2",
|
||||||
|
"define-properties": "^1.1.3",
|
||||||
|
"es-abstract": "^1.18.0-next.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/string.prototype.trimend": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.2",
|
||||||
|
"define-properties": "^1.1.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/string.prototype.trimstart": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.2",
|
||||||
|
"define-properties": "^1.1.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/strip-bom": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/supports-color": {
|
||||||
|
"version": "5.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||||
|
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"has-flag": "^3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/svelte": {
|
||||||
|
"version": "3.42.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/svelte/-/svelte-3.42.5.tgz",
|
||||||
|
"integrity": "sha512-+y9ivcwMojAb0e87W7vR/UP7go44zc/3gtEciIMb8CUoIkUx6UJmPloBvVuO9MDXoGkUZM5SHr5PbLze9fJQVw==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/unbox-primitive": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"function-bind": "^1.1.1",
|
||||||
|
"has-bigints": "^1.0.1",
|
||||||
|
"has-symbols": "^1.0.2",
|
||||||
|
"which-boxed-primitive": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/validate-npm-package-license": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"spdx-correct": "^3.0.0",
|
||||||
|
"spdx-expression-parse": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/which": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"isexe": "^2.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"which": "bin/which"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/which-boxed-primitive": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"is-bigint": "^1.0.1",
|
||||||
|
"is-boolean-object": "^1.1.0",
|
||||||
|
"is-number-object": "^1.0.4",
|
||||||
|
"is-string": "^1.0.5",
|
||||||
|
"is-symbol": "^1.0.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-styles": {
|
"ansi-styles": {
|
||||||
"version": "3.2.1",
|
"version": "3.2.1",
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "run-p build:*",
|
"build": "run-p build:*",
|
||||||
"build:ipc-desktop": "esbuild desktop/ipc.js --bundle --minify --outfile=ipc.js",
|
"build:ipc-desktop": "npx esbuild desktop/ipc.js --bundle --minify --outfile=ipc.js",
|
||||||
"build:ipc-dev": "cd dev && npm run build",
|
"build:ipc-dev": "cd dev && npm install && npm run build",
|
||||||
"build:runtime-desktop-prod": "esbuild desktop/main.js --bundle --minify --outfile=runtime_prod_desktop.js --define:ENV=1",
|
"build:runtime-desktop-prod": "npx esbuild desktop/main.js --bundle --minify --outfile=runtime_prod_desktop.js --define:ENV=1",
|
||||||
"build:runtime-desktop-dev": "esbuild desktop/main.js --bundle --sourcemap=inline --outfile=runtime_dev_desktop.js --define:ENV=0",
|
"build:runtime-desktop-dev": "npx esbuild desktop/main.js --bundle --sourcemap=inline --outfile=runtime_dev_desktop.js --define:ENV=0",
|
||||||
"build:runtime-wrapper": "cd wrapper && esbuild main.js --bundle --minify --outfile=runtime.js",
|
"build:runtime-wrapper": "cd wrapper && esbuild main.js --bundle --minify --outfile=runtime.js",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
|
|||||||