mirror of
https://github.com/wailsapp/wails.git
synced 2026-03-14 14:45:49 +01:00
v2.8.1
This commit is contained in:
parent
faf36e8634
commit
372173664b
84 changed files with 16 additions and 7636 deletions
|
|
@ -1 +1 @@
|
|||
v2.8.0
|
||||
v2.8.1
|
||||
|
|
@ -13,12 +13,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- `Security` in case of vulnerabilities.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## v2.8.1 - 2024-04-11
|
||||
|
||||
### Added
|
||||
|
||||
- Added docs to help fix NixOs/Wayland font-size css issue. Added by @atterpac in [PR](https://github.com/wailsapp/wails/pull/3268)
|
||||
- Added -m (skip `go mod tidy`) flag to dev command by @te5se in [PR](https://github.com/wailsapp/wails/pull/3275)
|
||||
- Added mac option `DisableZoom` to remove zoom button. Added by @wizzymore in [PR](https://github.com/wailsapp/wails/pull/3289)
|
||||
- Changed Create a project with changing the default name to the project’s name. Changed by [@Twacqwq](https://github.com/Twacqwq) in [PR](https://github.com/wailsapp/wails/pull/3303)
|
||||
- Fix some typos in comments. Changed by [@reallylowest](https://github.com/reallylowest) in [PR](https://github.com/wailsapp/wails/pull/3357)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed some typos in comments. Changed by [@reallylowest](https://github.com/reallylowest) in [PR](https://github.com/wailsapp/wails/pull/3357)
|
||||
- Fixed an issue where the destination file was not properly closed after copying. Changed by [@testwill](https://github.com/testwill) in [PR](https://github.com/wailsapp/wails/pull/3384)
|
||||
- Fixed an issue where `xattr` calls were not working. Fixed by [@leaanthony](https://github.com/wailsapp/wails/pull/3328)
|
||||
|
||||
### Changed
|
||||
|
||||
- Changed Create a project with changing the default name to the project’s name. Changed by [@Twacqwq](https://github.com/Twacqwq) in [PR](https://github.com/wailsapp/wails/pull/3303)
|
||||
|
||||
## v2.8.0 - 2024-02-08
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"label": "Appendix",
|
||||
"position": 70
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"label": "Community",
|
||||
"position": 50
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Links
|
||||
|
||||
This page serves as a list for community related links. Please submit a PR (click `Edit this page` at the bottom)
|
||||
to submit links.
|
||||
|
||||
## Awesome Wails
|
||||
|
||||
The [definitive list](https://github.com/wailsapp/awesome-wails) of links related to Wails.
|
||||
|
||||
## Support Channels
|
||||
|
||||
- [Wails Discord Server](https://discord.gg/JDdSxwjhGf)
|
||||
- [Github Issues](https://github.com/wailsapp/wails/issues)
|
||||
- [v2 Beta Discussion Board](https://github.com/wailsapp/wails/discussions/828)
|
||||
|
||||
## Social Media
|
||||
|
||||
- [Twitter](https://twitter.com/wailsapp)
|
||||
- [Wails Chinese Community QQ Group](https://qm.qq.com/cgi-bin/qm/qr?k=PmIURne5hFGNd7QWzW5qd6FV-INEjNJv&jump_from=webapi) - Group number: 1067173054
|
||||
|
||||
## Other Tutorials and Articles
|
||||
|
||||
- [Building of Bulletin Board](https://blog.customct.com/building-bulletin-board)
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"label": "Showcase",
|
||||
"position": 1
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
# BulletinBoard
|
||||
|
||||
```mdx-code-block
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img src={require("@site/static/img/showcase/bboard.webp").default} />
|
||||
<br />
|
||||
</p>
|
||||
```
|
||||
|
||||
The [BulletinBoard](https://github.com/raguay/BulletinBoard) application is a versital message board for static messages or dialogs to get information from the user for a script. It has a TUI for creating new dialogs that can latter be used to get information from the user. It's design is to stay running on your system and show the information as needed and then hide away. I have a process for watching a file on my system and sending the contents to BulletinBoard when changed. It works great with my workflows. There is also an [Alfred workflow](https://github.com/raguay/MyAlfred/blob/master/Alfred%205/EmailIt.alfredworkflow) for sending information to the program. The workflow is also for working with [EmailIt](https://github.com/raguay/EmailIt).
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
# CFN Tracker
|
||||
|
||||
```mdx-code-block
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img src={require("@site/static/img/showcase/cfntracker.webp").default} />
|
||||
<br />
|
||||
</p>
|
||||
```
|
||||
|
||||
[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - Track any Street
|
||||
Fighter 6 or V CFN profile's live matches. Check
|
||||
[the website](https://cfn.williamsjokvist.se/) to get started.
|
||||
|
||||
## Features
|
||||
|
||||
- Real-time match tracking
|
||||
- Storing match logs and statistics
|
||||
- Support for displaying live stats to OBS via Browser Source
|
||||
- Support for both SF6 and SFV
|
||||
- Ability for users to create their own OBS Browser themes with CSS
|
||||
|
||||
### Major tech used alongside Wails
|
||||
|
||||
- [Task](https://github.com/go-task/task) - wrapping the Wails CLI to make
|
||||
common commands easy to use
|
||||
- [React](https://github.com/facebook/react) - chosen for its rich ecosystem
|
||||
(radix, framer-motion)
|
||||
- [Bun](https://github.com/oven-sh/bun) - used for its fast dependency
|
||||
resolution and build-time
|
||||
- [Rod](https://github.com/go-rod/rod) - headless browser automation for
|
||||
authentication and polling changes
|
||||
- [SQLite](https://github.com/mattn/go-sqlite3) - used for storing matches,
|
||||
sessions and profiles
|
||||
- [Server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) -
|
||||
a http stream to send tracking updates to OBS browser sources
|
||||
- [i18next](https://github.com/i18next/) - with backend connector to serve
|
||||
localization objects from the Go layer
|
||||
- [xstate](https://github.com/statelyai/xstate) - state machines for auth
|
||||
process and tracking
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
# EmailIt
|
||||
|
||||
```mdx-code-block
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img src={require("@site/static/img/showcase/emailit.webp").default} />
|
||||
<br />
|
||||
</p>
|
||||
```
|
||||
|
||||
[EmailIt](https://github.com/raguay/EmailIt/) is a Wails 2 program that is a markdown based email sender only with nine notepads, scripts to manipulate the text, and templates. It also has a scripts terminal to run scripts in EmailIt on files in your system. The scripts and templates can be used from the commandline itself or with the Alfred, Keyboard Maestro, Dropzone, or PopClip extensions. It also supports scripts and themes downloaded form GitHub. Documentation is not complete, but the programs works. It’s built using Wails2 and Svelte, and the download is a universal macOS application.
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
# EncryptEasy
|
||||
|
||||
```mdx-code-block
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img src={require("@site/static/img/showcase/encrypteasy.webp").default} />
|
||||
<br />
|
||||
</p>
|
||||
```
|
||||
|
||||
**[EncryptEasy](https://www.encrypteasy.app) is a simple and easy to use PGP encryption tool, managing all your and your contacts keys. Encryption should be simple. Developed with Wails.**
|
||||
|
||||
Encrypting messages using PGP is the industry standard. Everyone has a private and a public key. Your private key, well, needs to be kept private so only you can read messages. Your public key is distributed to anyone who wants to send you secret, encrypted messages. Managing keys, encrypting messages and decrypting messages should be a smooth experience. EncryptEasy is all about making it easy.
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
# FileHound Export Utility
|
||||
|
||||
```mdx-code-block
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img src={require("@site/static/img/showcase/filehound.webp").default} />
|
||||
<br />
|
||||
</p>
|
||||
```
|
||||
|
||||
[FileHound Export Utility](https://www.filehound.co.uk/) FileHound is a cloud document management platform made for secure file retention, business process automation and SmartCapture capabilities.
|
||||
|
||||
The FileHound Export Utility allows FileHound Administrators the ability to run a secure document and data extraction tasks for alternative back-up and recovery purposes. This application will download all documents and/or meta data saved in FileHound based on the filters you choose. The metadata will be exported in both JSON and XML formats.
|
||||
|
||||
Backend built with:
|
||||
Go 1.15
|
||||
Wails 1.11.0
|
||||
go-sqlite3 1.14.6
|
||||
go-linq 3.2
|
||||
|
||||
Frontend with:
|
||||
Vue 2.6.11
|
||||
Vuex 3.4.0
|
||||
TypeScript
|
||||
Tailwind 1.9.6
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
# hiposter
|
||||
|
||||
```mdx-code-block
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img src={require("@site/static/img/showcase/hiposter.webp").default} />
|
||||
<br />
|
||||
</p>
|
||||
```
|
||||
|
||||
[hiposter](https://github.com/obity/hiposter) is a simple and efficient http API testing client tool. Based on Wails, Go and sveltejs.
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
# Minecraft Updater
|
||||
|
||||
```mdx-code-block
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img
|
||||
src={
|
||||
require("@site/static/img/showcase/minecraft-mod-updater.webp").default
|
||||
}
|
||||
/>
|
||||
<br />
|
||||
</p>
|
||||
```
|
||||
|
||||
[Minecraft Updater](https://github.com/Gurkengewuerz/MinecraftModUpdater) is a utility tool to update and synchronize Minecraft mods for your userbase. It’s built using Wails2 and React with [antd](https://ant.design/) as frontend framework.
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
# Modal File Manager
|
||||
|
||||
```mdx-code-block
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img
|
||||
src={require("@site/static/img/showcase/modalfilemanager.webp").default}
|
||||
/>
|
||||
<br />
|
||||
</p>
|
||||
```
|
||||
|
||||
[Modal File Manager](https://github.com/raguay/ModalFileManager) is a dual pane file manager using web technologies. My original design was based on NW.js and can be found [here](https://github.com/raguay/ModalFileManager-NWjs). This version uses the same Svelte based frontend code (but it has be greatly modified since the departure from NW.js), but the backend is a [Wails 2](https://wails.io/) implementation. By using this implementation, I no longer use command line `rm`, `cp`, etc. commands, but a git install has to be on the system to download themes and extensions. It is fully coded using Go and runs much faster than the previous versions.
|
||||
|
||||
This file manager is designed around the same principle as Vim: a state controlled keyboard actions. The number of states isn't fixed, but very programmable. Therefore, an infinite number of keyboard configurations can be created and used. This is the main difference from other file managers. There are themes and extensions available to download from GitHub.
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
# Molley Wallet
|
||||
|
||||
```mdx-code-block
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img src={require("@site/static/img/showcase/mollywallet.webp").default} />
|
||||
<br />
|
||||
</p>
|
||||
```
|
||||
|
||||
[Molly Wallet](https://github.com/grvlle/constellation_wallet/) the official $DAG wallet of the Constellation Network. It'll let users interact with the Hypergraph Network in various ways, not limited to producing $DAG transactions.
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
# October
|
||||
|
||||
```mdx-code-block
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img src={require("@site/static/img/showcase/october.webp").default} />
|
||||
<br />
|
||||
</p>
|
||||
```
|
||||
|
||||
[October](https://october.utf9k.net) is a small Wails application that makes it really easy to extract highlights from [Kobo eReaders](https://en.wikipedia.org/wiki/Kobo_eReader) and then forward them to [Readwise](https://readwise.io).
|
||||
|
||||
It has a relatively small scope with all platform versions weighing in under 10MB, and that's without enabling [UPX compression](https://upx.github.io/)!
|
||||
|
||||
In contrast, the author's previous attempts with Electron quickly bloated to several hundred megabytes.
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
# Optimus
|
||||
|
||||
```mdx-code-block
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img src={require("@site/static/img/showcase/optimus.webp").default} />
|
||||
<br />
|
||||
</p>
|
||||
```
|
||||
|
||||
[Optimus](https://github.com/splode/optimus) is a desktop image optimization application. It supports conversion and compression between WebP, JPEG, and PNG image formats.
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
# Portfall
|
||||
|
||||
```mdx-code-block
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img src={require("@site/static/img/showcase/portfall.webp").default} />
|
||||
<br />
|
||||
</p>
|
||||
```
|
||||
|
||||
[Portfall](https://github.com/rekon-oss/portfall) - A desktop k8s port-forwarding portal for easy access to all your cluster UIs
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
# Restic Browser
|
||||
|
||||
```mdx-code-block
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img
|
||||
src={require("@site/static/img/showcase/restic-browser-2.png").default}
|
||||
/>
|
||||
<br />
|
||||
</p>
|
||||
```
|
||||
|
||||
[Restic-Browser](https://github.com/emuell/restic-browser) - A simple, cross-platform [restic](https://github.com/restic/restic) backup GUI for browsing and restoring restic repositories.
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
# RiftShare
|
||||
|
||||
```mdx-code-block
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img src={require("@site/static/img/showcase/riftshare-main.webp").default} />
|
||||
<br />
|
||||
</p>
|
||||
```
|
||||
|
||||
Easy, Secure, and Free file sharing for everyone. Learn more at [Riftshare.app](https://riftshare.app)
|
||||
|
||||
## Features
|
||||
|
||||
- Easy secure file sharing between computers both in the local network and through the internet
|
||||
- Supports sending files or directories securely through the [magic wormhole protocol](https://magic-wormhole.readthedocs.io/en/latest/)
|
||||
- Compatible with all other apps using magic wormhole (magic-wormhole or wormhole-william CLI, wormhole-gui, etc.)
|
||||
- Automatic zipping of multiple selected files to send at once
|
||||
- Full animations, progress bar, and cancellation support for sending and receiving
|
||||
- Native OS File Selection
|
||||
- Open files in one click once received
|
||||
- Auto Update - don't worry about having the latest release!
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
# ScriptBar
|
||||
|
||||
```mdx-code-block
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img src={require("@site/static/img/showcase/scriptbar.webp").default} />
|
||||
<br />
|
||||
</p>
|
||||
```
|
||||
|
||||
[ScriptBar](https://GitHub.com/raguay/ScriptBarApp) is a program to show the output of scripts or [Node-Red](https://nodered.org) server. It runs scripts defined in EmailIt program and shows the output. Scripts from xBar or TextBar can be used, but currently on the TextBar scripts work well. It also displays the output of scripts on your system. ScriptBar doesn't put them in the menubar, but has them all in a convient window for easy viewing. You can have multiple tabs to have many different things show. You can also keep the links to your most visited web sites.
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
# Snippet Expander
|
||||
|
||||
```mdx-code-block
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img src={require("@site/static/img/showcase/snippetexpandergui-select-snippet.png").default} />
|
||||
<br />
|
||||
Screenshot of Snippet Expander's Select Snippet window
|
||||
</p>
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img src={require("@site/static/img/showcase/snippetexpandergui-add-snippet.png").default} />
|
||||
<br />
|
||||
Screenshot of Snippet Expander's Add Snippet screen
|
||||
</p>
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img src={require("@site/static/img/showcase/snippetexpandergui-search-and-paste.png").default} />
|
||||
<br />
|
||||
Screenshot of Snippet Expander's Search & Paste window
|
||||
</p>
|
||||
```
|
||||
|
||||
[Snippet Expander](https://snippetexpander.org) is "Your little expandable text snippets helper", for Linux.
|
||||
|
||||
Snippet Expander comprises of a GUI application built with Wails for managing snippets and settings, with a Search & Paste window mode for quickly selecting and pasting a snippet.
|
||||
|
||||
The Wails based GUI, go-lang CLI and vala-lang auto expander daemon all communicate with a go-lang daemon via D-Bus. The daemon does the majority of the work, managing the database of snippets and common settings, and providing services for expanding and pasting snippets etc.
|
||||
|
||||
Check out the [source code](https://git.sr.ht/~ianmjones/snippetexpander/tree/trunk/item/cmd/snippetexpandergui/app.go#L38) to see how the Wails app sends messages from the UI to the backend that are then sent to the daemon, and subscribes to a D-Bus event to monitor changes to snippets via another instance of the app or CLI and show them instantly in the UI via a Wails event.
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
# Surge
|
||||
|
||||
```mdx-code-block
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img src={require("@site/static/img/showcase/surge.png").default} />
|
||||
<br />
|
||||
</p>
|
||||
```
|
||||
|
||||
[Surge](https://getsurge.io/) is a p2p filesharing app designed to utilize blockchain technologies to enable 100% anonymous file transfers. Surge is end-to-end encrypted, decentralized and open source.
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
# Tiny RDM
|
||||
|
||||
```mdx-code-block
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img src={require("@site/static/img/showcase/tiny-rdm1.webp").default} />
|
||||
<img src={require("@site/static/img/showcase/tiny-rdm2.webp").default} />
|
||||
<br />
|
||||
</p>
|
||||
```
|
||||
|
||||
The [Tiny RDM](https://redis.tinycraft.cc/) application is an open-source, modern lightweight Redis GUI. It has a beautful UI, intuitive Redis database management, and compatible with Windows, Mac, and Linux. It provides visual key-value data operations, supports various data decoding and viewing options, built-in console for executing commands, slow log queries and more.
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
# Wally
|
||||
|
||||
```mdx-code-block
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img src={require("@site/static/img/showcase/wally.webp").default} />
|
||||
<br />
|
||||
</p>
|
||||
```
|
||||
|
||||
[Wally](https://ergodox-ez.com/pages/wally) is the official firmware flasher for [Ergodox](https://ergodox-ez.com/) keyboards. It looks great and is a fantastic example of what you can achieve with Wails: the ability to combine the power of Go and the rich graphical tools of the web development world.
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
# Minecraft launcher for WarMine
|
||||
|
||||
```mdx-code-block
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img
|
||||
src={require("@site/static/img/showcase/warmine1.png").default}
|
||||
/>
|
||||
<img
|
||||
src={require("@site/static/img/showcase/warmine2.png").default}
|
||||
/>
|
||||
<br />
|
||||
</p>
|
||||
```
|
||||
|
||||
[Minecraft launcher for WarMine](https://warmine.ru/) is a Wails application, that allows you to easily join modded game servers and manage your game accounts.
|
||||
|
||||
The Launcher downloads the game files, checks their integrity and launches the game with a wide range of customization options for the launch arguments from the backend.
|
||||
|
||||
Frontend is written in Svelte, whole launcher fits in 9MB and supports Windows 7-11.
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
# Wombat
|
||||
|
||||
```mdx-code-block
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img src={require("@site/static/img/showcase/wombat.webp").default} />
|
||||
<br />
|
||||
</p>
|
||||
```
|
||||
|
||||
[Wombat](https://github.com/rogchap/wombat) is a cross platform gRPC client.
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
# Ytd
|
||||
|
||||
```mdx-code-block
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img src={require("@site/static/img/showcase/ytd.webp").default} />
|
||||
<br />
|
||||
</p>
|
||||
```
|
||||
|
||||
[Ytd](https://github.com/marcio199226/ytd/tree/v2-wails) is an app for downloading tracks from youtube, creating offline playlists and share them with your friends, your friends will be able to playback your playlists or download them for offline listening, has an built-in player.
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Templates
|
||||
|
||||
This page serves as a list for community supported templates. Please submit a PR (click `Edit this page` at the bottom)
|
||||
to include your templates. To build your own template, please see the [Templates](../guides/templates.mdx) guide.
|
||||
|
||||
To use these templates, run `wails init -n "Your Project Name" -t [the link below[@version]]`
|
||||
|
||||
If there is no version suffix, the main branch code template is used by default. If there is a version suffix, the code template corresponding to the tag of this version is used.
|
||||
|
||||
Example: `wails init -n "Your Project Name" -t https://github.com/misitebao/wails-template-vue`
|
||||
|
||||
:::warning Attention
|
||||
|
||||
**The Wails project does not maintain, is not responsible nor liable for 3rd party templates!**
|
||||
|
||||
If you are unsure about a template, inspect `package.json` and `wails.json` for what scripts are run and what packages are installed.
|
||||
|
||||
:::
|
||||
|
||||
## Vue
|
||||
|
||||
- [wails-template-vue](https://github.com/misitebao/wails-template-vue) - Wails template based on Vue ecology (Integrated TypeScript, Dark theme, Internationalization, Single page routing, TailwindCSS)
|
||||
- [wails-vite-vue-ts](https://github.com/codydbentley/wails-vite-vue-ts) - Vue 3 TypeScript with Vite (and instructions to add features)
|
||||
- [wails-vite-vue-the-works](https://github.com/codydbentley/wails-vite-vue-the-works) - Vue 3 TypeScript with Vite, Vuex, Vue Router, Sass, and ESLint + Prettier
|
||||
- [wails-template-quasar-js](https://github.com/sgosiaco/wails-template-quasar-js) - A template using JavaScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier)
|
||||
- [wails-template-quasar-ts](https://github.com/sgosiaco/wails-template-quasar-ts) - A template using TypeScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier, Composition API with <script setup>)
|
||||
- [wails-template-naive](https://github.com/tk103331/wails-template-naive) - Wails template based on Naive UI (A Vue 3 Component Library)
|
||||
|
||||
## Angular
|
||||
|
||||
- [wails-template-angular](https://github.com/mateothegreat/wails-template-angular) - Angular 15+ action packed & ready to roll to production.
|
||||
- [wails-angular-template](https://github.com/TAINCER/wails-angular-template) - Angular with TypeScript, Sass, Hot-Reload, Code-Splitting and i18n
|
||||
- [wails-template-angular-latest](https://github.com/mJehanno/wails-template-angular-latest) - An Angular template that will try to support latest version
|
||||
|
||||
## React
|
||||
|
||||
- [wails-react-template](https://github.com/AlienRecall/wails-react-template) - A template using reactjs
|
||||
- [wails-react-template](https://github.com/flin7/wails-react-template) - A minimal template for React that supports live development
|
||||
- [wails-template-nextjs](https://github.com/LGiki/wails-template-nextjs) - A template using Next.js and TypeScript
|
||||
- [wails-template-nextjs-app-router](https://github.com/thisisvk-in/wails-template-nextjs-app-router) - A template using Next.js and TypeScript with App router
|
||||
- [wails-vite-react-ts-tailwind-template](https://github.com/hotafrika/wails-vite-react-ts-tailwind-template) - A template for React + TypeScript + Vite + TailwindCSS
|
||||
- [wails-vite-react-ts-tailwind-shadcnui-template](https://github.com/Mahcks/wails-vite-react-tailwind-shadcnui-ts) - A template with Vite, React, TypeScript, TailwindCSS, and shadcn/ui
|
||||
|
||||
## Svelte
|
||||
|
||||
- [wails-svelte-template](https://github.com/raitonoberu/wails-svelte-template) - A template using Svelte
|
||||
- [wails-vite-svelte-template](https://github.com/BillBuilt/wails-vite-svelte-template) - A template using Svelte and Vite
|
||||
- [wails-vite-svelte-tailwind-template](https://github.com/BillBuilt/wails-vite-svelte-tailwind-template) - A template using Svelte and Vite with TailwindCSS v3
|
||||
- [wails-svelte-tailwind-vite-template](https://github.com/PylotLight/wails-vite-svelte-tailwind-template/tree/master) - An updated template using Svelte v4.2.0 and Vite with TailwindCSS v3.3.3
|
||||
- [wails-sveltekit-template](https://github.com/h8gi/wails-sveltekit-template) - A template using SvelteKit
|
||||
|
||||
## Solid
|
||||
|
||||
- [wails-template-vite-solid-ts](https://github.com/xijaja/wails-template-solid-ts) - A template using Solid + Ts + Vite
|
||||
- [wails-template-vite-solid-js](https://github.com/xijaja/wails-template-solid-js) - A template using Solid + Js + Vite
|
||||
|
||||
## Elm
|
||||
|
||||
- [wails-elm-template](https://github.com/benjamin-thomas/wails-elm-template) - Develop your GUI app with functional programming and a **snappy** hot-reload setup :tada: :rocket:
|
||||
- [wails-template-elm-tailwind](https://github.com/rnice01/wails-template-elm-tailwind) - Combine the powers :muscle: of Elm + Tailwind CSS + Wails! Hot reloading supported.
|
||||
|
||||
## HTMX
|
||||
|
||||
- [wails-htmx-templ-chi-tailwind](https://github.com/PylotLight/wails-hmtx-templ-template) - Use a unique combination of pure htmx for interactivity plus templ for creating components and forms
|
||||
|
||||
## Pure JavaScript (Vanilla)
|
||||
|
||||
- [wails-pure-js-template](https://github.com/KiddoV/wails-pure-js-template) - A template with nothing but just basic JavaScript, HTML, and CSS
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"label": "Getting Started",
|
||||
"position": 10
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
---
|
||||
sidebar_position: 6
|
||||
---
|
||||
|
||||
# Compiling your Project
|
||||
|
||||
From the project directory, run `wails build`.
|
||||
This will compile your project and save the production-ready binary in the `build/bin` directory.
|
||||
|
||||
If you run the binary, you should see the default application:
|
||||
|
||||
```mdx-code-block
|
||||
<div class="text--center">
|
||||
<img
|
||||
src={require("@site/static/img/defaultproject.webp").default}
|
||||
width="50%"
|
||||
class="screenshot"
|
||||
/>
|
||||
</div>
|
||||
<br />
|
||||
```
|
||||
|
||||
For more details on compilation options, please refer to the [CLI Reference](../reference/cli.mdx#build).
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
---
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
# Developing your Application
|
||||
|
||||
You can run your application in development mode by running `wails dev` from your project directory. This will do the following things:
|
||||
|
||||
- Build your application and run it
|
||||
- Bind your Go code to the frontend so it can be called from JavaScript
|
||||
- Using the power of [Vite](https://vitejs.dev/), will watch for modifications in your Go files and rebuild/re-run on change
|
||||
- Sets up a [webserver](http://localhost:34115) that will serve your application over a browser. This allows you to use your favourite browser extensions. You can even call your Go code from the console
|
||||
|
||||
To get started, run `wails dev` in the project directory. More information on this can be found [here](../reference/cli.mdx#dev).
|
||||
|
||||
Coming soon: Tutorial
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Creating a Project
|
||||
|
||||
## Project Generation
|
||||
|
||||
Now that the CLI is installed, you can generate a new project by using the `wails init` command.
|
||||
|
||||
Pick your favourite framework:
|
||||
|
||||
```mdx-code-block
|
||||
import Tabs from "@theme/Tabs";
|
||||
import TabItem from "@theme/TabItem";
|
||||
|
||||
<Tabs
|
||||
defaultValue="Svelte"
|
||||
values={[
|
||||
{label: "Svelte", value: "Svelte"},
|
||||
{label: "React", value: "React"},
|
||||
{label: "Vue", value: "Vue"},
|
||||
{label: "Preact", value: "Preact"},
|
||||
{label: "Lit", value: "Lit"},
|
||||
{label: "Vanilla", value: "Vanilla"},
|
||||
]}
|
||||
>
|
||||
<TabItem value="Svelte">
|
||||
Generate a <a href={"https://svelte.dev/"}>Svelte</a> project using JavaScript with:<br/><br/>
|
||||
|
||||
wails init -n myproject -t svelte
|
||||
|
||||
If you would rather use TypeScript:<br/>
|
||||
|
||||
wails init -n myproject -t svelte-ts
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="React">
|
||||
Generate a <a href={"https://reactjs.org/"}>React</a> project using JavaScript with:<br/><br/>
|
||||
|
||||
wails init -n myproject -t react
|
||||
|
||||
If you would rather use TypeScript:<br/>
|
||||
|
||||
wails init -n myproject -t react-ts
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="Vue">
|
||||
Generate a <a href={"https://vuejs.org/"}>Vue</a> project using JavaScript with:<br/><br/>
|
||||
|
||||
wails init -n myproject -t vue
|
||||
|
||||
If you would rather use TypeScript:<br/>
|
||||
|
||||
wails init -n myproject -t vue-ts
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="Preact">
|
||||
Generate a <a href={"https://preactjs.com/"}>Preact</a> project using JavaScript with:<br/><br/>
|
||||
|
||||
wails init -n myproject -t preact
|
||||
|
||||
If you would rather use TypeScript:<br/>
|
||||
|
||||
wails init -n myproject -t preact-ts
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="Lit">
|
||||
Generate a <a href={"https://lit.dev/"}>Lit</a> project using JavaScript with:<br/><br/>
|
||||
|
||||
wails init -n myproject -t lit
|
||||
|
||||
If you would rather use TypeScript:<br/>
|
||||
|
||||
wails init -n myproject -t lit-ts
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="Vanilla">
|
||||
Generate a Vanilla project using JavaScript with:<br/><br/>
|
||||
|
||||
wails init -n myproject -t vanilla
|
||||
|
||||
If you would rather use TypeScript:<br/>
|
||||
|
||||
wails init -n myproject -t vanilla-ts
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
<hr />
|
||||
|
||||
There are also [community templates](../community/templates.mdx) available that offer different capabilities and frameworks.
|
||||
|
||||
To see the other options available, you can run `wails init -help`.
|
||||
More details can be found in the [CLI Reference](../reference/cli.mdx#init).
|
||||
|
||||
## Project Layout
|
||||
|
||||
Wails projects have the following layout:
|
||||
|
||||
```
|
||||
.
|
||||
├── build/
|
||||
│ ├── appicon.png
|
||||
│ ├── darwin/
|
||||
│ └── windows/
|
||||
├── frontend/
|
||||
├── go.mod
|
||||
├── go.sum
|
||||
├── main.go
|
||||
└── wails.json
|
||||
```
|
||||
|
||||
### Project structure rundown
|
||||
|
||||
- `/main.go` - The main application
|
||||
- `/frontend/` - Frontend project files
|
||||
- `/build/` - Project build directory
|
||||
- `/build/appicon.png` - The application icon
|
||||
- `/build/darwin/` - Mac specific project files
|
||||
- `/build/windows/` - Windows specific project files
|
||||
- `/wails.json` - The project configuration
|
||||
- `/go.mod` - Go module file
|
||||
- `/go.sum` - Go module checksum file
|
||||
|
||||
The `frontend` directory has nothing specific to Wails and can be any frontend project of your choosing.
|
||||
|
||||
The `build` directory is used during the build process. These files may be updated to customise your builds. If
|
||||
files are removed from the build directory, default versions will be regenerated.
|
||||
|
||||
The default module name in `go.mod` is "changeme". You should change this to something more appropriate.
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Installation
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
- Windows 10/11 AMD64/ARM64
|
||||
- MacOS 10.13+ AMD64
|
||||
- MacOS 11.0+ ARM64
|
||||
- Linux AMD64/ARM64
|
||||
|
||||
## Dependencies
|
||||
|
||||
Wails has a number of common dependencies that are required before installation:
|
||||
|
||||
- Go 1.18+
|
||||
- NPM (Node 15+)
|
||||
|
||||
### Go
|
||||
|
||||
Download Go from the [Go Downloads Page](https://go.dev/dl/).
|
||||
|
||||
Ensure that you follow the official [Go installation instructions](https://go.dev/doc/install). You will also need to ensure that your `PATH` environment variable also includes the path to your `~/go/bin` directory. Restart your terminal and do the following checks:
|
||||
|
||||
- Check Go is installed correctly: `go version`
|
||||
- Check "~/go/bin" is in your PATH variable: `echo $PATH | grep go/bin`
|
||||
|
||||
### NPM
|
||||
|
||||
Download NPM from the [Node Downloads Page](https://nodejs.org/en/download/). It is best to use the latest release as that is what we generally test against.
|
||||
|
||||
Run `npm --version` to verify.
|
||||
|
||||
## Platform Specific Dependencies
|
||||
|
||||
You will also need to install platform specific dependencies:
|
||||
|
||||
```mdx-code-block
|
||||
import Tabs from "@theme/Tabs";
|
||||
import TabItem from "@theme/TabItem";
|
||||
|
||||
<Tabs
|
||||
defaultValue="Windows"
|
||||
values={[
|
||||
{ label: "Windows", value: "Windows" },
|
||||
{ label: "MacOS", value: "MacOS" },
|
||||
{ label: "Linux", value: "Linux" },
|
||||
]}
|
||||
>
|
||||
<TabItem value="MacOS">
|
||||
Wails requires that the xcode command line tools are installed. This can be
|
||||
done by running <code>xcode-select --install</code>.
|
||||
</TabItem>
|
||||
<TabItem value="Windows">
|
||||
Wails requires that the <a href="https://developer.microsoft.com/en-us/microsoft-edge/webview2/">WebView2</a> runtime is installed. Some Windows installations will already have this installed. You can check using the <code>wails doctor</code> command.
|
||||
</TabItem>
|
||||
<TabItem value={"Linux"}>
|
||||
Linux requires the standard <code>gcc</code> build tools plus <code>libgtk3</code> and <code>libwebkit</code>. Rather than list a ton of commands for different distros, Wails can try to determine what the installation commands are for your specific distribution. Run <code>wails doctor</code> after installation to be shown how to install the dependencies. If your distro/package manager is not supported, please consult the <a href={"/docs/guides/linux-distro-support"}>Add Linux Distro</a> guide.
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
## Optional Dependencies
|
||||
|
||||
- [UPX](https://upx.github.io/) for compressing your applications.
|
||||
- [NSIS](https://wails.io/docs/guides/windows-installer/) for generating Windows installers.
|
||||
|
||||
## Installing Wails
|
||||
|
||||
Run `go install github.com/wailsapp/wails/v2/cmd/wails@latest` to install the Wails CLI.
|
||||
|
||||
Note: If you get an error similar to this:
|
||||
|
||||
```shell
|
||||
....\Go\pkg\mod\github.com\wailsapp\wails\v2@v2.1.0\pkg\templates\templates.go:28:12: pattern all:ides/*: no matching files found
|
||||
```
|
||||
please check you have Go 1.18+ installed:
|
||||
```shell
|
||||
go version
|
||||
```
|
||||
|
||||
## System Check
|
||||
|
||||
Running `wails doctor` will check if you have the correct dependencies installed. If not, it will advise on what is missing and help on how to rectify any problems.
|
||||
|
||||
## The `wails` command appears to be missing?
|
||||
|
||||
If your system is reporting that the `wails` command is missing, make sure you have followed the Go installation guide
|
||||
correctly. Normally, it means that the `go/bin` directory in your User's home directory is not in the `PATH` environment
|
||||
variable. You will also normally need to close and reopen any open command prompts so that changes to the environment
|
||||
made by the installer are reflected at the command prompt.
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"label": "Guides",
|
||||
"position": 50
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
# Angular
|
||||
|
||||
Whilst Wails does not have an Angular template, it is possible to use Angular with Wails.
|
||||
|
||||
## Dev Mode
|
||||
|
||||
To get dev mode working with Angular, you need to add the following to your `wails.json`:
|
||||
|
||||
```json
|
||||
"frontend:build": "npx ng build",
|
||||
"frontend:install": "npm install",
|
||||
"frontend:dev:watcher": "npx ng serve",
|
||||
"frontend:dev:serverUrl": "http://localhost:4200",
|
||||
```
|
||||
|
|
@ -1,312 +0,0 @@
|
|||
# Application Development
|
||||
|
||||
There are no hard and fast rules for developing applications with Wails, but there are some basic guidelines.
|
||||
|
||||
## Application Setup
|
||||
|
||||
The pattern used by the default templates are that `main.go` is used for configuring and running the application, whilst
|
||||
`app.go` is used for defining the application logic.
|
||||
|
||||
The `app.go` file will define a struct that has 2 methods which act as hooks into the main application:
|
||||
|
||||
```go title="app.go"
|
||||
type App struct {
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func NewApp() *App {
|
||||
return &App{}
|
||||
}
|
||||
|
||||
func (a *App) startup(ctx context.Context) {
|
||||
a.ctx = ctx
|
||||
}
|
||||
|
||||
func (a *App) shutdown(ctx context.Context) {
|
||||
}
|
||||
```
|
||||
|
||||
- The startup method is called as soon as Wails allocates the resources it needs and is a good place for creating resources,
|
||||
setting up event listeners and anything else the application needs at startup.
|
||||
It is given a `context.Context` which is usually saved in a struct field. This context is needed for calling the
|
||||
[runtime](../reference/runtime/intro.mdx). If this method returns an error, the application will terminate.
|
||||
In dev mode, the error will be output to the console.
|
||||
|
||||
- The shutdown method will be called by Wails right at the end of the shutdown process. This is a good place to deallocate
|
||||
memory and perform any shutdown tasks.
|
||||
|
||||
The `main.go` file generally consists of a single call to `wails.Run()`, which accepts the application configuration.
|
||||
The pattern used by the templates is that before the call to `wails.Run()`, an instance of the struct we defined in
|
||||
`app.go` is created and saved in a variable called `app`. This configuration is where we add our callbacks:
|
||||
|
||||
```go {3,9,10} title="main.go"
|
||||
func main() {
|
||||
|
||||
app := NewApp()
|
||||
|
||||
err := wails.Run(&options.App{
|
||||
Title: "My App",
|
||||
Width: 800,
|
||||
Height: 600,
|
||||
OnStartup: app.startup,
|
||||
OnShutdown: app.shutdown,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
More information on application lifecycle hooks can be found [here](../howdoesitwork.mdx#application-lifecycle-callbacks).
|
||||
|
||||
## Binding Methods
|
||||
|
||||
It is likely that you will want to call Go methods from the frontend. This is normally done by adding public methods to
|
||||
the already defined struct in `app.go`:
|
||||
|
||||
```go {16-18} title="app.go"
|
||||
type App struct {
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func NewApp() *App {
|
||||
return &App{}
|
||||
}
|
||||
|
||||
func (a *App) startup(ctx context.Context) {
|
||||
a.ctx = ctx
|
||||
}
|
||||
|
||||
func (a *App) shutdown(ctx context.Context) {
|
||||
}
|
||||
|
||||
func (a *App) Greet(name string) string {
|
||||
return fmt.Sprintf("Hello %s!", name)
|
||||
}
|
||||
```
|
||||
|
||||
In the main application configuration, the `Bind` key is where we can tell Wails what we want to bind:
|
||||
|
||||
```go {11-13} title="main.go"
|
||||
func main() {
|
||||
|
||||
app := NewApp()
|
||||
|
||||
err := wails.Run(&options.App{
|
||||
Title: "My App",
|
||||
Width: 800,
|
||||
Height: 600,
|
||||
OnStartup: app.startup,
|
||||
OnShutdown: app.shutdown,
|
||||
Bind: []interface{}{
|
||||
app,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
This will bind all public methods in our `App` struct (it will never bind the startup and shutdown methods).
|
||||
|
||||
### Dealing with context when binding multiple structs
|
||||
|
||||
If you want to bind methods for multiple structs but want each struct to keep a reference to the context so that you
|
||||
can use the runtime functions, a good pattern is to pass the context from the `OnStartup` method to your struct instances
|
||||
:
|
||||
|
||||
```go
|
||||
func main() {
|
||||
|
||||
app := NewApp()
|
||||
otherStruct := NewOtherStruct()
|
||||
|
||||
err := wails.Run(&options.App{
|
||||
Title: "My App",
|
||||
Width: 800,
|
||||
Height: 600,
|
||||
OnStartup: func(ctx context.Context){
|
||||
app.SetContext(ctx)
|
||||
otherStruct.SetContext(ctx)
|
||||
},
|
||||
OnShutdown: app.shutdown,
|
||||
Bind: []interface{}{
|
||||
app,
|
||||
otherStruct
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Also you might want to use Enums in your structs and have models for them on frontend.
|
||||
In that case you should create array that will contain all possible enum values, instrument enum type and bind it to the app:
|
||||
|
||||
```go {16-18} title="app.go"
|
||||
type Weekday string
|
||||
|
||||
const (
|
||||
Sunday Weekday = "Sunday"
|
||||
Monday Weekday = "Monday"
|
||||
Tuesday Weekday = "Tuesday"
|
||||
Wednesday Weekday = "Wednesday"
|
||||
Thursday Weekday = "Thursday"
|
||||
Friday Weekday = "Friday"
|
||||
Saturday Weekday = "Saturday"
|
||||
)
|
||||
|
||||
var AllWeekdays = []struct {
|
||||
Value Weekday
|
||||
TSName string
|
||||
}{
|
||||
{Sunday, "SUNDAY"},
|
||||
{Monday, "MONDAY"},
|
||||
{Tuesday, "TUESDAY"},
|
||||
{Wednesday, "WEDNESDAY"},
|
||||
{Thursday, "THURSDAY"},
|
||||
{Friday, "FRIDAY"},
|
||||
{Saturday, "SATURDAY"},
|
||||
}
|
||||
```
|
||||
|
||||
In the main application configuration, the `EnumBind` key is where we can tell Wails what we want to bind enums as well:
|
||||
|
||||
```go {11-13} title="main.go"
|
||||
func main() {
|
||||
|
||||
app := NewApp()
|
||||
|
||||
err := wails.Run(&options.App{
|
||||
Title: "My App",
|
||||
Width: 800,
|
||||
Height: 600,
|
||||
OnStartup: app.startup,
|
||||
OnShutdown: app.shutdown,
|
||||
Bind: []interface{}{
|
||||
app,
|
||||
},
|
||||
EnumBind: []interface{}{
|
||||
AllWeekdays,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
This will add missing enums to your `model.ts` file.
|
||||
|
||||
More information on Binding can be found [here](../howdoesitwork.mdx#method-binding).
|
||||
|
||||
## Application Menu
|
||||
|
||||
Wails supports adding a menu to your application. This is done by passing a [Menu](../reference/menus.mdx#menu) struct
|
||||
to application config. It's common to use a method that returns a Menu, and even more common for that to be a method on
|
||||
the `App` struct used for the lifecycle hooks.
|
||||
|
||||
```go {11} title="main.go"
|
||||
func main() {
|
||||
|
||||
app := NewApp()
|
||||
|
||||
err := wails.Run(&options.App{
|
||||
Title: "My App",
|
||||
Width: 800,
|
||||
Height: 600,
|
||||
OnStartup: app.startup,
|
||||
OnShutdown: app.shutdown,
|
||||
Menu: app.menu(),
|
||||
Bind: []interface{}{
|
||||
app,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Assets
|
||||
|
||||
The great thing about the way Wails v2 handles assets is that it doesn't! The only thing you need to give Wails is an
|
||||
`embed.FS`. How you get to that is entirely up to you. You can use vanilla html/css/js files like the vanilla template.
|
||||
You could have some complicated build system, it doesn't matter.
|
||||
|
||||
When `wails build` is run, it will check the `wails.json` project file at the project root. There are 2 keys in the
|
||||
project file that are read:
|
||||
|
||||
- "frontend:install"
|
||||
- "frontend:build"
|
||||
|
||||
The first, if given, will be executed in the `frontend` directory to install the node modules.
|
||||
The second, if given, will be executed in the `frontend` directory to build the frontend project.
|
||||
|
||||
If these 2 keys aren't given, then Wails does absolutely nothing with the frontend. It is only expecting that `embed.FS`.
|
||||
|
||||
### AssetsHandler
|
||||
|
||||
A Wails v2 app can optionally define a `http.Handler` in the `options.App`, which allows hooking into the AssetServer to
|
||||
create files on the fly or process POST/PUT requests.
|
||||
GET requests are always first handled by the `assets` FS. If the FS doesn't find the requested file the request will be
|
||||
forwarded to the `http.Handler` for serving. Any requests other than GET will be directly processed by the `AssetsHandler`
|
||||
if specified.
|
||||
It's also possible to only use the `AssetsHandler` by specifiy `nil` as the `Assets` option.
|
||||
|
||||
## Built in Dev Server
|
||||
|
||||
Running `wails dev` will start the built in dev server which will start a file watcher in your project directory. By
|
||||
default, if any file changes, wails checks if it was an application file (default: `.go`, configurable with `-e` flag).
|
||||
If it was, then it will rebuild your application and relaunch it. If the changed file was in the assets,
|
||||
it will issue a reload after a short amount of time.
|
||||
|
||||
The dev server uses a technique called "debouncing" which means it doesn't reload straight away,
|
||||
as there may be multiple files changed in a short amount of time. When a trigger occurs, it waits for a set amount of time
|
||||
before issuing a reload. If another trigger happens, it resets to the wait time again. By default this value is `100ms`.
|
||||
If this value doesn't work for your project, it can be configured using the `-debounce` flag. If used, this value will
|
||||
be saved to your project config and become the default.
|
||||
|
||||
## External Dev Server
|
||||
|
||||
Some frameworks come with their own live-reloading server, however they will not be able to take advantage of the Wails
|
||||
Go bindings. In this scenario, it is best to run a watcher script that rebuilds the project into the build directory, which
|
||||
Wails will be watching. For an example, see the default svelte template that uses [rollup](https://rollupjs.org/guide/en/).
|
||||
|
||||
### Create React App
|
||||
|
||||
The process for a Create-React-App project is slightly more complicated. In order to support live frontend reloading the following configuration
|
||||
needs to be added to your `wails.json`:
|
||||
|
||||
```json
|
||||
"frontend:dev:watcher": "yarn start",
|
||||
"frontend:dev:serverUrl": "http://localhost:3000",
|
||||
```
|
||||
|
||||
The `frontend:dev:watcher` command will start the Create-React-App development server (hosted on port `3000` typically). The `frontend:dev:serverUrl` command then
|
||||
instructs Wails to serve assets from the development server when loading the frontend rather than from the build folder. In addition to the above, the
|
||||
`index.html` needs to be updated with the following:
|
||||
|
||||
```html
|
||||
<head>
|
||||
<meta name="wails-options" content="noautoinject" />
|
||||
<script src="/wails/ipc.js"></script>
|
||||
<script src="/wails/runtime.js"></script>
|
||||
</head>
|
||||
```
|
||||
|
||||
This is required as the watcher command that rebuilds the frontend prevents Wails from injecting the required scripts. This circumvents that issue by ensuring
|
||||
the scripts are always injected. With this configuration, `wails dev` can be run which will appropriately build the frontend and backend with hot-reloading enabled.
|
||||
Additionally, when accessing the application from a browser the React developer tools can now be used on a non-minified version of the application for straightforward
|
||||
debugging. Finally, for faster builds, `wails dev -s` can be run to skip the default building of the frontend by Wails as this is an unnecessary step.
|
||||
|
||||
## Go Module
|
||||
|
||||
The default Wails templates generate a `go.mod` file that contains the module name "changeme". You should change this
|
||||
to something more appropriate after project generation.
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
# Crossplatform build with Github Actions
|
||||
|
||||
To build a Wails project for all the available platforms, you need to create an application build for each operating system. One effective method to achieve this is by utilizing GitHub Actions.
|
||||
|
||||
An action that facilitates building a Wails app is available at:
|
||||
https://github.com/dAppServer/wails-build-action
|
||||
|
||||
In case the existing action doesn't fulfill your requirements, you can select only the necessary steps from the source:
|
||||
https://github.com/dAppServer/wails-build-action/blob/main/action.yml
|
||||
|
||||
Below is a comprehensive example that demonstrates building an app upon the creation of a new Git tag and subsequently uploading it to the Actions artifacts:
|
||||
|
||||
```yaml
|
||||
name: Wails build
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
# Match any new tag
|
||||
- '*'
|
||||
|
||||
env:
|
||||
# Necessary for most environments as build failure can occur due to OOM issues
|
||||
NODE_OPTIONS: "--max-old-space-size=4096"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
# Failure in one platform build won't impact the others
|
||||
fail-fast: false
|
||||
matrix:
|
||||
build:
|
||||
- name: 'App'
|
||||
platform: 'linux/amd64'
|
||||
os: 'ubuntu-latest'
|
||||
- name: 'App'
|
||||
platform: 'windows/amd64'
|
||||
os: 'windows-latest'
|
||||
- name: 'App'
|
||||
platform: 'darwin/universal'
|
||||
os: 'macos-latest'
|
||||
|
||||
runs-on: ${{ matrix.build.os }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Build wails
|
||||
uses: dAppServer/wails-build-action@v2.2
|
||||
id: build
|
||||
with:
|
||||
build-name: ${{ matrix.build.name }}
|
||||
build-platform: ${{ matrix.build.platform }}
|
||||
package: false
|
||||
go-version: '1.20'
|
||||
```
|
||||
|
||||
This example offers opportunities for various enhancements, including:
|
||||
- Caching dependencies
|
||||
- Code signing
|
||||
- Uploading to platforms like S3, Supbase, etc.
|
||||
- Injecting secrets as environment variables
|
||||
- Utilizing environment variables as build variables (such as version variable extracted from the current Git tag)
|
||||
|
|
@ -1,189 +0,0 @@
|
|||
# Custom Protocol Scheme association
|
||||
|
||||
Custom Protocols feature allows you to associate specific custom protocol with your app so that when users open links with this protocol,
|
||||
your app is launched to handle them. This can be particularly useful to connect your desktop app with your web app.
|
||||
In this guide, we'll walk through the steps to implement custom protocols in Wails app.
|
||||
|
||||
|
||||
## Set Up Custom Protocol Schemes Association:
|
||||
To set up custom protocol, you need to modify your application's wails.json file.
|
||||
In "info" section add a "protocols" section specifying the protocols your app should be associated with.
|
||||
|
||||
For example:
|
||||
```json
|
||||
{
|
||||
"info": {
|
||||
"protocols": [
|
||||
{
|
||||
"scheme": "myapp",
|
||||
"description": "My App Protocol",
|
||||
"role": "Editor"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Property | Description |
|
||||
|:------------|:--------------------------------------------------------------------------------------|
|
||||
| scheme | Custom Protocol scheme. e.g. myapp |
|
||||
| description | Windows-only. The description. |
|
||||
| role | macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole. |
|
||||
|
||||
## Platform Specifics:
|
||||
|
||||
### macOS
|
||||
When you open custom protocol with your app, the system will launch your app and call the `OnUrlOpen` function in your Wails app. Example:
|
||||
```go title="main.go"
|
||||
func main() {
|
||||
// Create application with options
|
||||
err := wails.Run(&options.App{
|
||||
Title: "wails-open-file",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
},
|
||||
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
|
||||
Mac: &mac.Options{
|
||||
OnUrlOpen: func(url string) { println(url) },
|
||||
},
|
||||
Bind: []interface{}{
|
||||
app,
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
println("Error:", err.Error())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Windows
|
||||
On Windows Custom Protocol Schemes is supported only with NSIS installer. During installation, the installer will create a
|
||||
registry entry for your schemes. When you open url with your app, new instance of app is launched and url is passed
|
||||
as argument to your app. To handle this you should parse command line arguments in your app. Example:
|
||||
```go title="main.go"
|
||||
func main() {
|
||||
argsWithoutProg := os.Args[1:]
|
||||
|
||||
if len(argsWithoutProg) != 0 {
|
||||
println("launchArgs", argsWithoutProg)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You also can enable single instance lock for your app. In this case, when you open url with your app, new instance of app is not launched
|
||||
and arguments are passed to already running instance. Check single instance lock guide for details. Example:
|
||||
```go title="main.go"
|
||||
func main() {
|
||||
// Create application with options
|
||||
err := wails.Run(&options.App{
|
||||
Title: "wails-open-file",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
},
|
||||
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
|
||||
SingleInstanceLock: &options.SingleInstanceLock{
|
||||
UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc",
|
||||
OnSecondInstanceLaunch: app.onSecondInstanceLaunch,
|
||||
},
|
||||
Bind: []interface{}{
|
||||
app,
|
||||
},
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### Linux
|
||||
Currently, Wails doesn't support bundling for Linux. So, you need to create file associations manually.
|
||||
For example if you distribute your app as a .deb package, you can create file associations by adding required files in you bundle.
|
||||
You can use [nfpm](https://nfpm.goreleaser.com/) to create .deb package for your app.
|
||||
|
||||
1. Create a .desktop file for your app and specify file associations there (note that `%u` is important in Exec). Example:
|
||||
```ini
|
||||
[Desktop Entry]
|
||||
Categories=Office
|
||||
Exec=/usr/bin/wails-open-file %u
|
||||
Icon=wails-open-file.png
|
||||
Name=wails-open-file
|
||||
Terminal=false
|
||||
Type=Application
|
||||
MimeType=x-scheme-handler/myapp;
|
||||
```
|
||||
|
||||
2. Prepare postInstall/postRemove scripts for your package. Example:
|
||||
```sh
|
||||
# reload desktop database to load app in list of available
|
||||
update-desktop-database /usr/share/applications
|
||||
```
|
||||
3. Configure nfpm to use your scripts and files. Example:
|
||||
```yaml
|
||||
name: "wails-open-file"
|
||||
arch: "arm64"
|
||||
platform: "linux"
|
||||
version: "1.0.0"
|
||||
section: "default"
|
||||
priority: "extra"
|
||||
maintainer: "FooBarCorp <FooBarCorp@gmail.com>"
|
||||
description: "Sample Package"
|
||||
vendor: "FooBarCorp"
|
||||
homepage: "http://example.com"
|
||||
license: "MIT"
|
||||
contents:
|
||||
- src: ../bin/wails-open-file
|
||||
dst: /usr/bin/wails-open-file
|
||||
- src: ./main.desktop
|
||||
dst: /usr/share/applications/wails-open-file.desktop
|
||||
- src: ../appicon.svg
|
||||
dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg
|
||||
# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme
|
||||
- src: ../appicon.svg
|
||||
dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg
|
||||
scripts:
|
||||
postinstall: ./postInstall.sh
|
||||
postremove: ./postRemove.sh
|
||||
```
|
||||
6. Build your .deb package using nfpm:
|
||||
```sh
|
||||
nfpm pkg --packager deb --target .
|
||||
```
|
||||
7. Now when your package is installed, your app will be associated with custom protocol scheme. When you open url with your app,
|
||||
new instance of app is launched and file path is passed as argument to your app.
|
||||
To handle this you should parse command line arguments in your app. Example:
|
||||
```go title="main.go"
|
||||
func main() {
|
||||
argsWithoutProg := os.Args[1:]
|
||||
|
||||
if len(argsWithoutProg) != 0 {
|
||||
println("launchArgs", argsWithoutProg)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You also can enable single instance lock for your app. In this case, when you open url with your app, new instance of app is not launched
|
||||
and arguments are passed to already running instance. Check single instance lock guide for details. Example:
|
||||
```go title="main.go"
|
||||
func main() {
|
||||
// Create application with options
|
||||
err := wails.Run(&options.App{
|
||||
Title: "wails-open-file",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
},
|
||||
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
|
||||
SingleInstanceLock: &options.SingleInstanceLock{
|
||||
UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc",
|
||||
OnSecondInstanceLaunch: app.onSecondInstanceLaunch,
|
||||
},
|
||||
Bind: []interface{}{
|
||||
app,
|
||||
},
|
||||
})
|
||||
}
|
||||
```
|
||||
|
|
@ -1,144 +0,0 @@
|
|||
# Dynamic Assets
|
||||
|
||||
If you want to load or generate assets for your frontend dynamically, you can achieve that using the
|
||||
[AssetsHandler](../reference/options#assetshandler) option. The AssetsHandler is a generic `http.Handler` which will
|
||||
be called for any non GET request on the assets server and for GET requests which can not be served from the
|
||||
bundled assets because the file is not found.
|
||||
|
||||
By installing a custom AssetsHandler, you can serve your own assets using a custom asset server.
|
||||
|
||||
## Example
|
||||
|
||||
In our example project, we will create a simple assets handler which will load files off disk:
|
||||
|
||||
```go title=main.go {17-36,49}
|
||||
package main
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"fmt"
|
||||
"github.com/wailsapp/wails/v2"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
//go:embed all:frontend/dist
|
||||
var assets embed.FS
|
||||
|
||||
type FileLoader struct {
|
||||
http.Handler
|
||||
}
|
||||
|
||||
func NewFileLoader() *FileLoader {
|
||||
return &FileLoader{}
|
||||
}
|
||||
|
||||
func (h *FileLoader) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
||||
var err error
|
||||
requestedFilename := strings.TrimPrefix(req.URL.Path, "/")
|
||||
println("Requesting file:", requestedFilename)
|
||||
fileData, err := os.ReadFile(requestedFilename)
|
||||
if err != nil {
|
||||
res.WriteHeader(http.StatusBadRequest)
|
||||
res.Write([]byte(fmt.Sprintf("Could not load file %s", requestedFilename)))
|
||||
}
|
||||
|
||||
res.Write(fileData)
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Create an instance of the app structure
|
||||
app := NewApp()
|
||||
|
||||
// Create application with options
|
||||
err := wails.Run(&options.App{
|
||||
Title: "helloworld",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
Handler: NewFileLoader(),
|
||||
},
|
||||
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 255},
|
||||
OnStartup: app.startup,
|
||||
Bind: []interface{}{
|
||||
app,
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
println("Error:", err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When we run the application in dev mode using `wails dev`, we will see the following output:
|
||||
|
||||
```
|
||||
DEB | [ExternalAssetHandler] Loading 'http://localhost:3001/favicon.ico'
|
||||
DEB | [ExternalAssetHandler] Loading 'http://localhost:3001/favicon.ico' failed, using AssetHandler
|
||||
Requesting file: favicon.ico
|
||||
```
|
||||
|
||||
As you can see, the assets handler is called when the default assets server is unable to serve
|
||||
the `favicon.ico` file.
|
||||
|
||||
If you right click the main application and select "inspect" to bring up the devtools, you can test
|
||||
this feature out by typing the following into the console:
|
||||
|
||||
```
|
||||
let response = await fetch('does-not-exist.txt');
|
||||
```
|
||||
|
||||
This will generate an error in the devtools. We can see that the error is what we expect, returned by
|
||||
our custom assets handler:
|
||||
|
||||
```mdx-code-block
|
||||
<p className="text--center">
|
||||
<img
|
||||
src={require("@site/static/img/assetshandler-does-not-exist.webp").default}
|
||||
/>
|
||||
</p>
|
||||
```
|
||||
|
||||
However, if we request `go.mod`, we will see the following output:
|
||||
|
||||
```mdx-code-block
|
||||
<p className="text--center">
|
||||
<img src={require("@site/static/img/assetshandler-go-mod.webp").default} />
|
||||
</p>
|
||||
```
|
||||
|
||||
This technique can be used to load images directly into the page. If we updated our default vanilla template and
|
||||
replaced the logo image:
|
||||
|
||||
```html
|
||||
<img id="logo" class="logo" />
|
||||
```
|
||||
|
||||
with:
|
||||
|
||||
```html
|
||||
<img src="build/appicon.png" style="width: 300px" />
|
||||
```
|
||||
|
||||
Then we would see the following:
|
||||
|
||||
```mdx-code-block
|
||||
<p className="text--center">
|
||||
<img
|
||||
src={require("@site/static/img/assetshandler-image.webp").default}
|
||||
style={{ width: "75%" }}
|
||||
/>
|
||||
</p>
|
||||
```
|
||||
|
||||
:::warning
|
||||
|
||||
Exposing your filesystem in this way is a security risk. It is recommended that you properly manage access
|
||||
to your filesystem.
|
||||
|
||||
:::
|
||||
|
|
@ -1,228 +0,0 @@
|
|||
# File Association
|
||||
|
||||
File association feature allows you to associate specific file types with your app so that when users open those files,
|
||||
your app is launched to handle them. This can be particularly useful for text editors, image viewers, or any application
|
||||
that works with specific file formats. In this guide, we'll walk through the steps to implement file association in Wails app.
|
||||
|
||||
|
||||
## Set Up File Association:
|
||||
To set up file association, you need to modify your application's wails.json file.
|
||||
In "info" section add a "fileAssociations" section specifying the file types your app should be associated with.
|
||||
|
||||
For example:
|
||||
```json
|
||||
{
|
||||
"info": {
|
||||
"fileAssociations": [
|
||||
{
|
||||
"ext": "wails",
|
||||
"name": "Wails",
|
||||
"description": "Wails Application File",
|
||||
"iconName": "wailsFileIcon",
|
||||
"role": "Editor"
|
||||
},
|
||||
{
|
||||
"ext": "jpg",
|
||||
"name": "JPEG",
|
||||
"description": "Image File",
|
||||
"iconName": "jpegFileIcon",
|
||||
"role": "Editor"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Property | Description |
|
||||
|:------------|:---------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| ext | The extension (minus the leading period). e.g. png |
|
||||
| name | The name. e.g. PNG File |
|
||||
| iconName | The icon name without extension. Icons should be located in build folder. Proper icons will be generated from .png file for both macOS and Windows |
|
||||
| description | Windows-only. The description. It is displayed on the `Type` column on Windows Explorer. |
|
||||
| role | macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole. |
|
||||
|
||||
## Platform Specifics:
|
||||
|
||||
### macOS
|
||||
When you open file (or files) with your app, the system will launch your app and call the `OnFileOpen` function in your Wails app. Example:
|
||||
```go title="main.go"
|
||||
func main() {
|
||||
// Create application with options
|
||||
err := wails.Run(&options.App{
|
||||
Title: "wails-open-file",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
},
|
||||
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
|
||||
Mac: &mac.Options{
|
||||
OnFileOpen: func(filePaths []string) { println(filestring) },
|
||||
},
|
||||
Bind: []interface{}{
|
||||
app,
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
println("Error:", err.Error())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Windows
|
||||
On Windows file association is supported only with NSIS installer. During installation, the installer will create a
|
||||
registry entry for your file associations. When you open file with your app, new instance of app is launched and file path is passed
|
||||
as argument to your app. To handle this you should parse command line arguments in your app. Example:
|
||||
```go title="main.go"
|
||||
func main() {
|
||||
argsWithoutProg := os.Args[1:]
|
||||
|
||||
if len(argsWithoutProg) != 0 {
|
||||
println("launchArgs", argsWithoutProg)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You also can enable single instance lock for your app. In this case, when you open file with your app, new instance of app is not launched
|
||||
and arguments are passed to already running instance. Check single instance lock guide for details. Example:
|
||||
```go title="main.go"
|
||||
func main() {
|
||||
// Create application with options
|
||||
err := wails.Run(&options.App{
|
||||
Title: "wails-open-file",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
},
|
||||
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
|
||||
SingleInstanceLock: &options.SingleInstanceLock{
|
||||
UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc",
|
||||
OnSecondInstanceLaunch: app.onSecondInstanceLaunch,
|
||||
},
|
||||
Bind: []interface{}{
|
||||
app,
|
||||
},
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### Linux
|
||||
Currently, Wails doesn't support bundling for Linux. So, you need to create file associations manually.
|
||||
For example if you distribute your app as a .deb package, you can create file associations by adding required files in you bundle.
|
||||
You can use [nfpm](https://nfpm.goreleaser.com/) to create .deb package for your app.
|
||||
|
||||
1. Create a .desktop file for your app and specify file associations there. Example:
|
||||
```ini
|
||||
[Desktop Entry]
|
||||
Categories=Office
|
||||
Exec=/usr/bin/wails-open-file %u
|
||||
Icon=wails-open-file.png
|
||||
Name=wails-open-file
|
||||
Terminal=false
|
||||
Type=Application
|
||||
MimeType=application/x-wails;application/x-test
|
||||
```
|
||||
|
||||
2. Create mime types file. Example:
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
|
||||
<mime-type type="application/x-wails">
|
||||
<comment>Wails Application File</comment>
|
||||
<glob pattern="*.wails"/>
|
||||
</mime-type>
|
||||
</mime-info>
|
||||
```
|
||||
|
||||
3. Create icons for your file types. SVG icons are recommended.
|
||||
4. Prepare postInstall/postRemove scripts for your package. Example:
|
||||
```sh
|
||||
# reload mime types to register file associations
|
||||
update-mime-database /usr/share/mime
|
||||
# reload desktop database to load app in list of available
|
||||
update-desktop-database /usr/share/applications
|
||||
# update icons
|
||||
update-icon-caches /usr/share/icons/*
|
||||
```
|
||||
5. Configure nfpm to use your scripts and files. Example:
|
||||
```yaml
|
||||
name: "wails-open-file"
|
||||
arch: "arm64"
|
||||
platform: "linux"
|
||||
version: "1.0.0"
|
||||
section: "default"
|
||||
priority: "extra"
|
||||
maintainer: "FooBarCorp <FooBarCorp@gmail.com>"
|
||||
description: "Sample Package"
|
||||
vendor: "FooBarCorp"
|
||||
homepage: "http://example.com"
|
||||
license: "MIT"
|
||||
contents:
|
||||
- src: ../bin/wails-open-file
|
||||
dst: /usr/bin/wails-open-file
|
||||
- src: ./main.desktop
|
||||
dst: /usr/share/applications/wails-open-file.desktop
|
||||
- src: ./application-wails-mime.xml
|
||||
dst: /usr/share/mime/packages/application-x-wails.xml
|
||||
- src: ./application-test-mime.xml
|
||||
dst: /usr/share/mime/packages/application-x-test.xml
|
||||
- src: ../appicon.svg
|
||||
dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg
|
||||
- src: ../wailsFileIcon.svg
|
||||
dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-wails.svg
|
||||
- src: ../testFileIcon.svg
|
||||
dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-test.svg
|
||||
# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme
|
||||
- src: ../appicon.svg
|
||||
dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg
|
||||
- src: ../wailsFileIcon.svg
|
||||
dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-wails.svg
|
||||
- src: ../testFileIcon.svg
|
||||
dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-test.svg
|
||||
scripts:
|
||||
postinstall: ./postInstall.sh
|
||||
postremove: ./postRemove.sh
|
||||
```
|
||||
6. Build your .deb package using nfpm:
|
||||
```sh
|
||||
nfpm pkg --packager deb --target .
|
||||
```
|
||||
7. Now when your package is installed, your app will be associated with specified file types. When you open file with your app,
|
||||
new instance of app is launched and file path is passed as argument to your app.
|
||||
To handle this you should parse command line arguments in your app. Example:
|
||||
```go title="main.go"
|
||||
func main() {
|
||||
argsWithoutProg := os.Args[1:]
|
||||
|
||||
if len(argsWithoutProg) != 0 {
|
||||
println("launchArgs", argsWithoutProg)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You also can enable single instance lock for your app. In this case, when you open file with your app, new instance of app is not launched
|
||||
and arguments are passed to already running instance. Check single instance lock guide for details. Example:
|
||||
```go title="main.go"
|
||||
func main() {
|
||||
// Create application with options
|
||||
err := wails.Run(&options.App{
|
||||
Title: "wails-open-file",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
},
|
||||
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
|
||||
SingleInstanceLock: &options.SingleInstanceLock{
|
||||
UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc",
|
||||
OnSecondInstanceLaunch: app.onSecondInstanceLaunch,
|
||||
},
|
||||
Bind: []interface{}{
|
||||
app,
|
||||
},
|
||||
})
|
||||
}
|
||||
```
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
# Frameless Applications
|
||||
|
||||
Wails supports application that have no frames. This can be achieved by using the [frameless](../reference/options.mdx#frameless)
|
||||
field in [Application Options](../reference/options.mdx#application-options).
|
||||
|
||||
Wails offers a simple solution for dragging the window: Any HTML element that has the CSS style `--wails-draggable:drag` will
|
||||
act as a "drag handle". This property applies to all child elements. If you need to indicate that a nested element
|
||||
should not drag, then use the attribute '--wails-draggable:no-drag' on that element.
|
||||
|
||||
```html
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="/main.css" />
|
||||
</head>
|
||||
|
||||
<body style="--wails-draggable:drag">
|
||||
<div id="logo"></div>
|
||||
<div id="input" style="--wails-draggable:no-drag">
|
||||
<input id="name" type="text" />
|
||||
<button onclick="greet()">Greet</button>
|
||||
</div>
|
||||
<div id="result"></div>
|
||||
|
||||
<script src="/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
For some projects, using a CSS variable may not be possible due to dynamic styling. In this case, you can use the
|
||||
`CSSDragProperty` and `CSSDragValue` application options to define a property and value that will be used to indicate
|
||||
draggable regions:
|
||||
|
||||
```go title=main.go
|
||||
package main
|
||||
|
||||
import (
|
||||
"embed"
|
||||
|
||||
"github.com/wailsapp/wails/v2"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
||||
)
|
||||
|
||||
//go:embed all:frontend/dist
|
||||
var assets embed.FS
|
||||
|
||||
func main() {
|
||||
// Create an instance of the app structure
|
||||
app := NewApp()
|
||||
|
||||
// Create application with options
|
||||
err := wails.Run(&options.App{
|
||||
Title: "alwaysontop",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
},
|
||||
Frameless: true,
|
||||
CSSDragProperty: "widows",
|
||||
CSSDragValue: "1",
|
||||
Bind: []interface{}{
|
||||
app,
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
println("Error:", err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```html title=index.html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport" />
|
||||
<title>alwaysontop</title>
|
||||
</head>
|
||||
<body style="widows: 1">
|
||||
<div id="app"></div>
|
||||
<script src="./src/main.js" type="module"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
:::info Fullscreen
|
||||
|
||||
If you allow your application to go fullscreen, this drag functionality will be disabled.
|
||||
|
||||
:::
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
# Frontend
|
||||
|
||||
## Script Injection
|
||||
|
||||
When Wails serves your `index.html`, by default, it will inject 2 script entries into the `<body>` tag to load `/wails/ipc.js`
|
||||
and `/wails/runtime.js`. These files install the bindings and runtime respectively.
|
||||
|
||||
The code below shows where these are injected by default:
|
||||
|
||||
```html
|
||||
<html>
|
||||
<head>
|
||||
<title>injection example</title>
|
||||
<link rel="stylesheet" href="/main.css" />
|
||||
<!-- <script src="/wails/ipc.js"></script> -->
|
||||
<!-- <script src="/wails/runtime.js"></script> -->
|
||||
</head>
|
||||
|
||||
<body data-wails-drag>
|
||||
<div class="logo"></div>
|
||||
<div class="result" id="result">Please enter your name below 👇</div>
|
||||
<div class="input-box" id="input" data-wails-no-drag>
|
||||
<input class="input" id="name" type="text" autocomplete="off" />
|
||||
<button class="btn" onclick="greet()">Greet</button>
|
||||
</div>
|
||||
|
||||
<script src="/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
### Overriding Default Script Injection
|
||||
|
||||
To provide more flexibility to developers, there is a meta tag that may be used to customise this behaviour:
|
||||
|
||||
```html
|
||||
<meta name="wails-options" content="[options]" />
|
||||
```
|
||||
|
||||
The options are as follows:
|
||||
|
||||
| Value | Description |
|
||||
| ------------------- | ------------------------------------------------ |
|
||||
| noautoinjectruntime | Disable the autoinjection of `/wails/runtime.js` |
|
||||
| noautoinjectipc | Disable the autoinjection of `/wails/ipc.js` |
|
||||
| noautoinject | Disable all autoinjection of scripts |
|
||||
|
||||
Multiple options may be used provided they are comma seperated.
|
||||
|
||||
This code is perfectly valid and operates the same as the autoinjection version:
|
||||
|
||||
```html
|
||||
<html>
|
||||
<head>
|
||||
<title>injection example</title>
|
||||
<meta name="wails-options" content="noautoinject" />
|
||||
<link rel="stylesheet" href="/main.css" />
|
||||
</head>
|
||||
|
||||
<body data-wails-drag>
|
||||
<div class="logo"></div>
|
||||
<div class="result" id="result">Please enter your name below 👇</div>
|
||||
<div class="input-box" id="input" data-wails-no-drag>
|
||||
<input class="input" id="name" type="text" autocomplete="off" />
|
||||
<button class="btn" onclick="greet()">Greet</button>
|
||||
</div>
|
||||
|
||||
<script src="/wails/ipc.js"></script>
|
||||
<script src="/wails/runtime.js"></script>
|
||||
<script src="/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
|
@ -1,131 +0,0 @@
|
|||
# IDEs
|
||||
|
||||
Wails aims to provide a great development experience. To that aim, we now support generating IDE specific configuration
|
||||
to provide smoother project setup.
|
||||
|
||||
Currently, we support [Visual Studio Code](https://code.visualstudio.com/) but aim to support other IDEs such as Goland.
|
||||
|
||||
## Visual Studio Code
|
||||
|
||||
```mdx-code-block
|
||||
<p className="text--center">
|
||||
<img
|
||||
src={require("@site/static/img/vscode.webp").default}
|
||||
style={{ width: "75%" }}
|
||||
/>
|
||||
</p>
|
||||
```
|
||||
|
||||
When generating a project using the `-ide vscode` flags, IDE files will be created alongside the other project files.
|
||||
These files are placed into the `.vscode` directory and provide the correct configuration for debugging your application.
|
||||
|
||||
The 2 files generated are `tasks.json` and `launch.json`. Below are the files generated for the default vanilla project:
|
||||
|
||||
```json title="tasks.json"
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "build",
|
||||
"type": "shell",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
"command": "go",
|
||||
"args": [
|
||||
"build",
|
||||
"-tags",
|
||||
"dev",
|
||||
"-gcflags",
|
||||
"all=-N -l",
|
||||
"-o",
|
||||
"build/bin/myproject.exe"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
```json title="launch.json"
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Wails: Debug myproject",
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"mode": "exec",
|
||||
"program": "${workspaceFolder}/build/bin/myproject.exe",
|
||||
"preLaunchTask": "build",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"env": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Configuring the install and build steps
|
||||
|
||||
The `tasks.json` file is simple for the default project as there is no `npm install` or `npm run build` step needed.
|
||||
For projects that have a frontend build step, such as the svelte template, we would need to edit `tasks.json` to
|
||||
add the install and build steps:
|
||||
|
||||
```json title="tasks.json"
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "npm install",
|
||||
"type": "npm",
|
||||
"script": "install",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/frontend"
|
||||
},
|
||||
"presentation": {
|
||||
"clear": true,
|
||||
"panel": "shared",
|
||||
"showReuseMessage": false
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "npm run build",
|
||||
"type": "npm",
|
||||
"script": "build",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/frontend"
|
||||
},
|
||||
"presentation": {
|
||||
"clear": true,
|
||||
"panel": "shared",
|
||||
"showReuseMessage": false
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "build",
|
||||
"type": "shell",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
"command": "go",
|
||||
"args": [
|
||||
"build",
|
||||
"-tags",
|
||||
"dev",
|
||||
"-gcflags",
|
||||
"all=-N -l",
|
||||
"-o",
|
||||
"build/bin/vscode.exe"
|
||||
],
|
||||
"dependsOn": ["npm install", "npm run build"]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
:::info Future Enhancement
|
||||
|
||||
In the future, we hope to generate a `tasks.json` that includes the install and build steps automatically.
|
||||
|
||||
:::
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
# Linux Distro Support
|
||||
|
||||
## Overview
|
||||
|
||||
Wails offers Linux support but providing installation instructions for all available distributions is an impossible task.
|
||||
Instead, Wails tries to determine if the packages you need to develop applications are available via your system's package
|
||||
manager. Currently, we support the following package managers:
|
||||
|
||||
- apt
|
||||
- dnf
|
||||
- emerge
|
||||
- eopkg
|
||||
- nixpkgs
|
||||
- pacman
|
||||
- zypper
|
||||
|
||||
## Adding package names
|
||||
|
||||
There may be circumstances where your distro uses one of the supported package managers but the package name
|
||||
is different. For example, you may use an Ubuntu derivative, but the package name for gtk may be different. Wails
|
||||
attempts to find the correct package by iterating through a list of package names.
|
||||
The list of packages are stored in the packagemanager specific file in the `v2/internal/system/packagemanager`
|
||||
directory. In our example, this would be `v2/internal/system/packagemanager/apt.go`.
|
||||
|
||||
In this file, the list of packages are defined by the `Packages()` method:
|
||||
|
||||
```go
|
||||
func (a *Apt) Packages() packagemap {
|
||||
return packagemap{
|
||||
"libgtk-3": []*Package{
|
||||
{Name: "libgtk-3-dev", SystemPackage: true, Library: true},
|
||||
},
|
||||
"libwebkit": []*Package{
|
||||
{Name: "libwebkit2gtk-4.0-dev", SystemPackage: true, Library: true},
|
||||
},
|
||||
"gcc": []*Package{
|
||||
{Name: "build-essential", SystemPackage: true},
|
||||
},
|
||||
"pkg-config": []*Package{
|
||||
{Name: "pkg-config", SystemPackage: true},
|
||||
},
|
||||
"npm": []*Package{
|
||||
{Name: "npm", SystemPackage: true},
|
||||
},
|
||||
"docker": []*Package{
|
||||
{Name: "docker.io", SystemPackage: true, Optional: true},
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Let's assume that in our linux distro, `libgtk-3` is packaged under the name `lib-gtk3-dev`.
|
||||
We could add support for this by adding the following line:
|
||||
|
||||
```go {5}
|
||||
func (a *Apt) Packages() packagemap {
|
||||
return packagemap{
|
||||
"libgtk-3": []*Package{
|
||||
{Name: "libgtk-3-dev", SystemPackage: true, Library: true},
|
||||
{Name: "lib-gtk3-dev", SystemPackage: true, Library: true},
|
||||
},
|
||||
"libwebkit": []*Package{
|
||||
{Name: "libwebkit2gtk-4.0-dev", SystemPackage: true, Library: true},
|
||||
},
|
||||
"gcc": []*Package{
|
||||
{Name: "build-essential", SystemPackage: true},
|
||||
},
|
||||
"pkg-config": []*Package{
|
||||
{Name: "pkg-config", SystemPackage: true},
|
||||
},
|
||||
"npm": []*Package{
|
||||
{Name: "npm", SystemPackage: true},
|
||||
},
|
||||
"docker": []*Package{
|
||||
{Name: "docker.io", SystemPackage: true, Optional: true},
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Adding new package managers
|
||||
|
||||
To add a new package manager, perform the following steps:
|
||||
|
||||
- Create a new file in `v2/internal/system/packagemanager` called `<pm>.go`, where `<pm>` is the name of the package manager.
|
||||
- Define a struct that conforms to the package manager interface defined in `pm.go`:
|
||||
|
||||
```go
|
||||
type PackageManager interface {
|
||||
Name() string
|
||||
Packages() packagemap
|
||||
PackageInstalled(*Package) (bool, error)
|
||||
PackageAvailable(*Package) (bool, error)
|
||||
InstallCommand(*Package) string
|
||||
}
|
||||
```
|
||||
|
||||
- `Name()` should return the name of the package manager
|
||||
- `Packages()` should return a `packagemap`, that provides candidate filenames for dependencies
|
||||
- `PackageInstalled()` should return `true` if the given package is installed
|
||||
- `PackageAvailable()` should return `true` if the given package is not installed but available for installation
|
||||
- `InstallCommand()` should return the exact command to install the given package name
|
||||
|
||||
Take a look at the other package managers code to get an idea how this works.
|
||||
|
||||
:::info Remember
|
||||
|
||||
If you add support for a new package manager, don't forget to also update this page!
|
||||
|
||||
:::
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
# Linux
|
||||
|
||||
This page has miscellaneous guides related to developing Wails applications for Linux.
|
||||
|
||||
## Video tag doesn't fire "ended" event
|
||||
|
||||
When using a video tag, the "ended" event is not fired when the video is finished playing. This is a bug
|
||||
in WebkitGTK, however you can use the following workaround to fix it:
|
||||
|
||||
```js
|
||||
videoTag.addEventListener("timeupdate", (event) => {
|
||||
if (event.target.duration - event.target.currentTime < 0.2) {
|
||||
let ended = new Event("ended");
|
||||
event.target.dispatchEvent(ended);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Source: [Lyimmi](https://github.com/Lyimmi) on the
|
||||
[discussions board](https://github.com/wailsapp/wails/issues/1729#issuecomment-1212291275)
|
||||
|
||||
## GStreamer error when using Audio or Video elements
|
||||
|
||||
If you are seeing the following error when including `<Audio>` or `<Video>` elements on Linux, you may need to install `gst-plugins-good`.
|
||||
|
||||
```
|
||||
GStreamer element autoaudiosink not found. Please install it
|
||||
```
|
||||
|
||||
### Installing
|
||||
|
||||
Run the following distro relevant install command:
|
||||
|
||||
```mdx-code-block
|
||||
import Tabs from "@theme/Tabs";
|
||||
import TabItem from "@theme/TabItem";
|
||||
|
||||
<Tabs
|
||||
defaultValue="Arch"
|
||||
values={[
|
||||
{ label: "Arch", value: "Arch" },
|
||||
{ label: "Debian/Ubuntu", value: "Debian" },
|
||||
{ label: "Fedora", value: "Fedora" },
|
||||
]}
|
||||
>
|
||||
<TabItem value="Arch">
|
||||
|
||||
pacman -S gst-plugins-good
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="Debian">
|
||||
|
||||
apt-get install gstreamer1.0-plugins-good
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="Fedora">
|
||||
|
||||
dnf install gstreamer1-plugins-good
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
```
|
||||
|
||||
If the added package does not resolve the issue, additional GStreamer dependencies may be required. [See the GStreamer installation page for more details.](https://gstreamer.freedesktop.org/documentation/installing/on-linux.html)
|
||||
|
||||
### Additional Notes
|
||||
|
||||
- This issue is caused by [an upstream issue with WebkitGTK](https://bugs.webkit.org/show_bug.cgi?id=146351).
|
||||
- [Arch based systems](https://wiki.archlinux.org/title/Arch-based_distributions) seem to have this issue more often than other distributions.
|
||||
- This issue impacts [Tauri apps](https://tauri.app/).
|
||||
|
||||
Source: [developomp](https://github.com/developomp) on the [Tauri discussion board](https://github.com/tauri-apps/tauri/issues/4642#issuecomment-1643229562).
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
# Local Development
|
||||
|
||||
## Overview
|
||||
|
||||
Wails is in constant development and new releases are regularly "tagged". This usually happens when all the newer code
|
||||
on `master` has been tested and confirmed working. If you need a bugfix or feature that has not yet made it to a release,
|
||||
it's possible to use the latest "bleeding edge" version using the following steps:
|
||||
|
||||
- `git clone https://github.com/wailsapp/wails`
|
||||
- `cd wails/v2/cmd/wails`
|
||||
- `go install`
|
||||
|
||||
NOTE: The directory that you cloned the project into will now be called "clonedir".
|
||||
|
||||
The Wails CLI will now be at the very latest version.
|
||||
|
||||
### Updating your project
|
||||
|
||||
To update projects to use the latest version of the Wails library, update the project's
|
||||
`go.mod` and ensure the following line is at the bottom of the file:
|
||||
|
||||
`replace github.com/wailsapp/wails/v2 => <clonedir>`
|
||||
|
||||
Example:
|
||||
|
||||
On Windows:
|
||||
`replace github.com/wailsapp/wails/v2 => C:\Users\leaan\Documents\wails-v2-beta\wails\v2`
|
||||
|
||||
On 'nix:
|
||||
`replace github.com/wailsapp/wails/v2 => /home/me/projects/wails/v2`
|
||||
|
||||
To revert to a stable version, run:
|
||||
|
||||
`go install github.com/wailsapp/wails/v2/cmd/wails@latest`
|
||||
|
||||
## Testing a Branch
|
||||
|
||||
If you want to test a branch, follow the instructions above, but ensure you switch the branch you want to test before installing:
|
||||
|
||||
- `git clone https://github.com/wailsapp/wails`
|
||||
- `cd wails`
|
||||
- `git checkout -b branch-to-test --track origin/branch-to-test`
|
||||
- `cd v2/cmd/wails`
|
||||
- `go install`
|
||||
|
||||
Make sure you [update your project](#updating-your-project) as described above.
|
||||
|
||||
## Testing a PR
|
||||
|
||||
If you want to test a PR, follow the instructions above, but ensure you fetch the PR and switch the branch before installing.
|
||||
Please replace `[IDofThePR]` with the ID of the PR shown on github.com:
|
||||
|
||||
- `git clone https://github.com/wailsapp/wails`
|
||||
- `cd wails`
|
||||
- `git fetch -u origin pull/[IDofThePR]/head:test/pr-[IDofThePR]`
|
||||
- `git checkout test/pr-[IDofThePR]`
|
||||
- `git reset --hard HEAD`
|
||||
- `cd v2/cmd/wails`
|
||||
- `go install`
|
||||
|
||||
Make sure you [update your project](#updating-your-project) as described above.
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
# Mac App Store Guide
|
||||
|
||||
This page gives a brief overview of how to submit your Wails App to the Mac App Store.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- You will need to have an Apple Developer account. Please find more information on the [Apple Developer Program](https://developer.apple.com/support/compare-memberships/) site
|
||||
- You will need to have your Certificates, Identifiers, and App created on the developer portal. More on this below
|
||||
- Xcode command line tools will need to be installed on your local machine
|
||||
|
||||
#### Create Certificates and Identifiers
|
||||
|
||||
1. Go to your [Apple Developer Account](https://developer.apple.com/account/)
|
||||
2. Under `Certificates, Identifiers & Profiles`, click `Identifiers` and Register a New App ID. Use the format (com.example.app)
|
||||
3. Under the same page click `Certificates` and generate new Certificates for Mac App Store Distribution. Download them and import the certificates into Keychain on your local machine.
|
||||
|
||||
#### Create App Submission
|
||||
|
||||
1. Go to the [App Store Connect Site](https://appstoreconnect.apple.com/apps)
|
||||
2. Register a new application and link the bundle ID that you created in the previous step
|
||||
3. Populate your app with the correct screen shots, descriptions, etc. as required by Apple
|
||||
4. Create a new version of your app
|
||||
|
||||
#### Create Provisioning Profile
|
||||
1. Go to the [Apple Developer Profiles](https://developer.apple.com/account/resources/profiles/list) page
|
||||
2. Add a new provisioning profile for Mac App Store Distribution
|
||||
3. Set the Profile Type as Mac and select the App ID for the application created above
|
||||
4. Select the Mac App Distribution certificate
|
||||
5. Name the Provisioning Profile embedded and download the created profile.
|
||||
|
||||
## Mac App Store Process
|
||||
|
||||
#### Enable Apple's App Sandbox
|
||||
|
||||
Apps submitted to the Mac App Store must run under Apple's [App Sandbox](https://developer.apple.com/app-sandboxing/). You must create an `entitlements.plist` file for this to work. The recommendation is to create this file under this path `{PROJECT_DIR}/build/darwin/entitlements.plist`.
|
||||
|
||||
**Example Entitlements File**
|
||||
|
||||
This is an example entitlements file from the [RiftShare](https://github.com/achhabra2/riftshare) app. For reference please put in the entitlements your app requires. Refer to [this site](https://developer.apple.com/documentation/bundleresources/entitlements) for more information. You will need to replace the Team ID and Application Name with the ones you registered above.
|
||||
|
||||
```xml title="entitlements.plist"
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.downloads.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.application-identifier</key>
|
||||
<string>TEAM_ID.APP_NAME</string>
|
||||
<key>com.apple.developer.team-identifier</key>
|
||||
<string>TEAM_ID</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
**Add the Embedded Provisioning Profile**
|
||||
The Provisioning Profile created above needs to be added to the root of the applicaton. It needs to be named embedded.provisionprofile.
|
||||
|
||||
#### Build and Sign the App Package
|
||||
|
||||
The following is an example script for building and signing your app for Mac App Store submission. It assumes you are running the script from your root project directory.
|
||||
|
||||
Note the certificates for signing the app and signing the installer are different. Please make sure both are imported into Keychain. Find the strings in Keychain and insert them below. Populate your certificate names, and app name below. Running the following script will generate a signed `app.pkg` file in the root directory of your app.
|
||||
|
||||
```bash title="macappstore-build.sh"
|
||||
#!/bin/bash
|
||||
|
||||
APP_CERTIFICATE="3rd Party Mac Developer Application: YOUR NAME (CODE)"
|
||||
PKG_CERTIFICATE="3rd Party Mac Developer Installer: YOUR NAME (CODE)"
|
||||
APP_NAME="YourApp"
|
||||
|
||||
wails build -platform darwin/universal -clean
|
||||
|
||||
cp ./embedded.provisionprofile "./build/bin/$APP_NAME.app/Contents"
|
||||
|
||||
codesign --timestamp --options=runtime -s "$APP_CERTIFICATE" -v --entitlements ./build/darwin/entitlements.plist ./build/bin/$APP_NAME.app
|
||||
|
||||
productbuild --sign "$PKG_CERTIFICATE" --component ./build/bin/$APP_NAME.app /Applications ./$APP_NAME.pkg
|
||||
```
|
||||
|
||||
#### Upload App Bundle
|
||||
|
||||
You will need to upload the generated package file and associate it to your Application before you will be able to submit it for review.
|
||||
|
||||
1. Download the [Transporter App](https://apps.apple.com/us/app/transporter/id1450874784) from the Mac App Store
|
||||
2. Open it and sign in with your Apple ID
|
||||
3. Click the + sign and select the `APP_NAME.pkg` file that you generated in the previous step. Upload it
|
||||
4. Go back to the [App Store Connect](https://appstoreconnect.apple.com/apps) site and navigate back into your app submission. Select the version that you are ready to make available on the App Store. Under `Build` select the package that you uploaded via Transporter.
|
||||
|
||||
That's it! You can now use the site to submit your App for review. After a few business days if all goes well you should see your App live on the Mac App Store.
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
# Manual Builds
|
||||
|
||||
The Wails CLI does a lot of heavy lifting for the project, but sometimes it's desirable to manually build your project.
|
||||
This document will discuss the different operations the CLI does and how this may be achieved in different ways.
|
||||
|
||||
## Build Process
|
||||
|
||||
When either `wails build` or `wails dev` are used, the Wails CLI performs a common build process:
|
||||
|
||||
- Install frontend dependencies
|
||||
- Build frontend project
|
||||
- Generate build assets
|
||||
- Compile application
|
||||
- [optional] Compress application
|
||||
|
||||
### Install frontend dependencies
|
||||
|
||||
#### CLI Steps
|
||||
|
||||
- If the `-s` flag is given, this step is skipped
|
||||
- Checks `wails.json` to see if there is an install command in the key `frontend:install`
|
||||
- If there isn't, it skips this step
|
||||
- If there is, it checks if `package.json` exists in the frontend directory. If it doesn't exist, it skips this step
|
||||
- An MD5 sum is generated from the `package.json` file contents
|
||||
- It checks for the existence of `package.json.md5` and if it exists, will compare the contents of it (an MD5 sum)
|
||||
with the one generated to see if the contents have changed. If they are the same, this step is skipped
|
||||
- If `package.json.md5` does not exist, it creates it using the generated MD5 sum
|
||||
- If a build is now required, or `node_modules` does not exist, or the `-f` flag is given, the install command is
|
||||
executed in the frontend directory
|
||||
|
||||
#### Manual Steps
|
||||
|
||||
This step could be done from the command line or a script with `npm install`.
|
||||
|
||||
### Build frontend project
|
||||
|
||||
#### Wails CLI
|
||||
|
||||
- If the `-s` flag is given, this step is skipped
|
||||
- Checks `wails.json` to see if there is a build command in the key `frontend:build`
|
||||
- If there isn't, it skips this step
|
||||
- If there is, it is executed in the frontend directory
|
||||
|
||||
#### Manual Steps
|
||||
|
||||
This step could be done from the command line or a script with `npm run build` or whatever the frontend build script is.
|
||||
|
||||
### Generate assets
|
||||
|
||||
#### Wails CLI
|
||||
|
||||
- If `-nopackage` flag is set, this stage is skipped
|
||||
- If the `build/appicon.png` file does not exist, a default one is created
|
||||
- For Windows, see [Bundling for Windows](#windows)
|
||||
- If `build/windows/icon.ico` does not exist, it will create it from the `build/appicon.png` image.
|
||||
|
||||
##### Windows
|
||||
|
||||
- If `build/windows/icon.ico` does not exist, it will create it from `build/appicon.png` using icon sizes of 256, 128, 64, 48, 32 and 16. This is done using [winicon](https://github.com/leaanthony/winicon).
|
||||
- If the `build/windows/<projectname>.manifest` file does not exist, it creates it from a default version.
|
||||
- Compiles the application as a production build (above)
|
||||
- Uses [winres](https://github.com/tc-hib/winres) to bundle the icon and manifest into a `.syso` file ready for linking.
|
||||
|
||||
#### Manual Steps
|
||||
|
||||
- Create `icon.ico` using the [winicon](https://github.com/leaanthony/winicon) CLI tool (or any other tool).
|
||||
- Create / Update a `.manifest` file for your application
|
||||
- Use the [winres CLI](https://github.com/tc-hib/go-winres) to generate a `.syso` file.
|
||||
|
||||
### Compile application
|
||||
|
||||
#### Wails CLI
|
||||
|
||||
- If the `-clean` flag is provided, the `build` directory is deleted and recreated
|
||||
- For `wails dev`, the following default Go flags are used: `-tags dev -gcflags "all=-N -l"`
|
||||
- For `wails build`, the following default Go flags are used: `-tags desktop,production -ldflags "-w -s"`
|
||||
- On Windows, `-ldflags "-w -h -H windowsgui"`
|
||||
- Additional tags passed to the CLI using `-tags` are added to the defaults
|
||||
- Additional ldflags passed to the CLI using `-ldflags` are added to the defaults
|
||||
- The `-o` flag is passed through
|
||||
- The Go compiler specified by `-compiler` will be used for compilation
|
||||
|
||||
#### Manual steps
|
||||
|
||||
- For dev build, the minimum command would be: `go build -tags dev -gcflags "all=-N -l"`
|
||||
- For production build, the minimum command would be: `go build -tags desktop,production -ldflags "-w -s -H windowsgui"`
|
||||
- Ensure that you compile in the same directory as the `.syso` file
|
||||
|
||||
### Compress application
|
||||
|
||||
#### Wails CLI
|
||||
|
||||
- If the `-upx` flag has been given, the `upx` program will be run to compress the application with the default settings
|
||||
- If `-upxflags` is also passed, these flags are used instead of the default ones
|
||||
|
||||
#### Manual steps
|
||||
|
||||
- Run `upx [flags]` manually to compress the application.
|
||||
|
|
@ -1,208 +0,0 @@
|
|||
# Migrating from v1
|
||||
|
||||
## Overview
|
||||
|
||||
Wails v2 is a significant change from v1. This document aims to highlight the changes and the steps in migrating an existing project.
|
||||
|
||||
### Creating the Application
|
||||
|
||||
In v1, the main application is created using `wails.CreateApp`, bindings are added with `app.Bind`, then the
|
||||
application is run using `app.Run()`.
|
||||
|
||||
Example:
|
||||
|
||||
```go title="v1"
|
||||
app := wails.CreateApp(&wails.AppConfig{
|
||||
Title: "MyApp",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
JS: js,
|
||||
CSS: css,
|
||||
Colour: "#131313",
|
||||
})
|
||||
app.Bind(basic)
|
||||
app.Run()
|
||||
```
|
||||
|
||||
In v2, there is just a single method, `wails.Run()`, that accepts [application options](../reference/options.mdx#application-options).
|
||||
|
||||
```go title="v2"
|
||||
err := wails.Run(&options.App{
|
||||
Title: "MyApp",
|
||||
Width: 800,
|
||||
Height: 600,
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
},
|
||||
Bind: []interface{}{
|
||||
basic,
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### Binding
|
||||
|
||||
In v1, it was possible to bind both arbitrary functions and structs. In v2, this has been simplified to only binding structs.
|
||||
The struct instances that were previously passed to the `Bind()` method in v1, are now specified in the `Bind` field of
|
||||
the [application options](../reference/options.mdx#application-options):
|
||||
|
||||
```go title="v1"
|
||||
app := wails.CreateApp(/* options */)
|
||||
app.Bind(basic)
|
||||
```
|
||||
|
||||
```go title="v2"
|
||||
err := wails.Run(&options.App{
|
||||
/* other options */
|
||||
Bind: []interface{}{
|
||||
basic,
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
In v1, bound methods were available to the frontend at `window.backend`. This has changed to `window.go`.``
|
||||
|
||||
### Application Lifecycle
|
||||
|
||||
In v1, there were 2 special methods in a bound struct: `WailsInit()` and `WailsShutdown()`. These have
|
||||
been replaced with 3 lifecycle hooks as part of the [application options](../reference/options.mdx#application-options):
|
||||
|
||||
- [OnStartup](../reference/options.mdx#onstartup)
|
||||
- [OnShutdown](../reference/options.mdx#onshutdown)
|
||||
- [OnDomReady](../reference/options.mdx#ondomready)
|
||||
|
||||
Note: [OnDomReady](../reference/options.mdx#ondomready) replaces the `wails:ready` system event in v1.
|
||||
|
||||
These methods can be standard functions, but a common practice is to have them part of a struct:
|
||||
|
||||
```go title="v2"
|
||||
basic := NewBasicApp()
|
||||
err := wails.Run(&options.App{
|
||||
/* Other Options */
|
||||
OnStartup: basic.startup,
|
||||
OnShutdown: basic.shutdown,
|
||||
OnDomReady: basic.domready,
|
||||
})
|
||||
...
|
||||
type Basic struct {
|
||||
ctx context.Context
|
||||
}
|
||||
func (b *Basic) startup(ctx context.Context) {
|
||||
b.ctx = ctx
|
||||
}
|
||||
...
|
||||
```
|
||||
|
||||
### Runtime
|
||||
|
||||
The runtime in v2 is much richer than v1 with support for menus, window manipulation
|
||||
and better dialogs. The signature of the methods has changed slightly - please refer
|
||||
the the [Runtime Reference](../reference/runtime/intro.mdx).
|
||||
|
||||
In v1, the [runtime](../reference/runtime/intro.mdx) was available via a struct passed to `WailsInit()`.
|
||||
In v2, the runtime has been moved out to its own package. Each method in the runtime takes the
|
||||
`context.Context` that is passed to the [OnStartup](../reference/options.mdx#onstartup) method.
|
||||
|
||||
```go title="Runtime Example"
|
||||
package main
|
||||
|
||||
import "github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
|
||||
type Basic struct {
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
// startup is called at application startup
|
||||
func (a *App) startup(ctx context.Context) {
|
||||
a.ctx = ctx
|
||||
runtime.LogInfo(ctx, "Application Startup called!")
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Assets
|
||||
|
||||
The _biggest_ change in v2 is how assets are handled.
|
||||
|
||||
In v1, assets were passed via 2 application options:
|
||||
|
||||
- `JS` - The application's JavaScript
|
||||
- `CSS` - The application's CSS
|
||||
|
||||
This meant that the responsibility of generating a single JS and CSS file was on the
|
||||
developer. This essentially required the use of complicated packers such as webpack.
|
||||
|
||||
In v2, Wails makes no assumptions about your frontend assets, just like a webserver.
|
||||
All of your application assets are passed to the application options as an `embed.FS`.
|
||||
|
||||
**This means there is no requirement to bundle your assets, encode images as Base64 or
|
||||
attempt the dark art of bundler configuration to use custom fonts**.
|
||||
|
||||
At startup, Wails
|
||||
will scan the given `embed.FS` for `index.html` and use its location as the root path
|
||||
for all the other application assets - just like a webserver would.
|
||||
|
||||
Example: An application has the following project layout. All final assets are placed in the
|
||||
`frontend/dist` directory:
|
||||
|
||||
```shell
|
||||
.
|
||||
├── build/
|
||||
├── frontend/
|
||||
│ └── dist/
|
||||
│ ├── index.html
|
||||
│ ├── main.js
|
||||
│ ├── main.css
|
||||
│ └── logo.svg
|
||||
├── main.go
|
||||
└── wails.json
|
||||
```
|
||||
|
||||
Those assets may be used by the application by simply creating an `embed.FS`:
|
||||
|
||||
```go title="Assets Example"
|
||||
//go:embed all:frontend/dist
|
||||
var assets embed.FS
|
||||
|
||||
func main() {
|
||||
err := wails.Run(&options.App{
|
||||
/* Other Options */
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
},
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
Of course, bundlers can be used if you wish to. The only requirement is to pass
|
||||
the final application assets directory to Wails using an `embed.FS` in the `Assets`
|
||||
key of the [application options](../reference/options.mdx#application-options).
|
||||
|
||||
### Project Configuration
|
||||
|
||||
In v1, the project configuration was stored in the `project.json` file in the project root.
|
||||
In v2, the project configuration is stored in the `wails.json` file in the project root.
|
||||
|
||||
The format of the file is slightly different. Here is a comparison:
|
||||
|
||||
<p align="center">
|
||||
|
||||
| v1 | v2 | Notes |
|
||||
| ------------------ | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| name | name | |
|
||||
| description | | Removed |
|
||||
| author / name | author / name | |
|
||||
| author / email | author / email | |
|
||||
| version | version | |
|
||||
| binaryname | outputfilename | Changed |
|
||||
| frontend / dir | | Removed |
|
||||
| frontend / install | frontend:install | Changed |
|
||||
| frontend / build | frontend:build | Changed |
|
||||
| frontend / bridge | | Removed |
|
||||
| frontend / serve | | Removed |
|
||||
| tags | | Removed |
|
||||
| | wailsjsdir | The directory to generate wailsjs modules |
|
||||
| | assetdir | The directory of the compiled frontend assets for `dev` mode. This is normally inferred and could be left empty. |
|
||||
| | reloaddirs | Comma separated list of additional directories to watch for changes and to trigger reloads in `dev` mode. This is only needed for some more advanced asset configurations. |
|
||||
|
||||
</p>
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
# Mouse Buttons
|
||||
|
||||
The Wails runtime intercepts mouse clicks to determine whether a frameless window needs resizing or a window needs to be moved.
|
||||
It has been asked how to detect when a mouse click has occurred, because `window.onclick` doesn't report the mouse buttons correctly.
|
||||
The following code shows how to detect mouse clicks:
|
||||
|
||||
```javascript
|
||||
window.addEventListener("mousedown", handleMouseButtonDown);
|
||||
|
||||
function handleMouseButtonDown(event) {
|
||||
if (event.button === 0) {
|
||||
// left mouse button
|
||||
} else if (event.button === 1) {
|
||||
// middle mouse button
|
||||
} else if (event.button === 2) {
|
||||
// right mouse button
|
||||
} else if (event.button === 3) {
|
||||
// back mouse button
|
||||
} else if (event.button === 4) {
|
||||
// forward mouse button
|
||||
} else {
|
||||
// other mouse button
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Reference: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
# Obfuscated Builds
|
||||
|
||||
Wails includes support for obfuscating your application using [garble](https://github.com/burrowers/garble).
|
||||
|
||||
To produce an obfuscated build, you can use the `-obfuscate` flag with the `wails build` command:
|
||||
|
||||
```bash
|
||||
wails build -obfuscated
|
||||
```
|
||||
|
||||
To customise the obfuscation settings, you can use the `-garbleargs` flag:
|
||||
|
||||
```bash
|
||||
wails build -obfuscated -garbleargs "-literals -tiny -seed=myrandomseed"
|
||||
```
|
||||
|
||||
These settings may be persisted in your [project config](../reference/project-config).
|
||||
|
||||
## How it works
|
||||
|
||||
In a standard build, all bound methods are available in the frontend under the `window.go`
|
||||
variable. When these methods are called, the corresponding backend method is called using
|
||||
the fully qualified function name. When using an obfuscated build, methods are bound using
|
||||
an ID instead of a name. The bindings generated in the `wailsjs` directory use these IDs to
|
||||
call the backend functions.
|
||||
|
||||
:::note
|
||||
|
||||
To ensure that your application will work in obfuscated mode, you must use the generated
|
||||
bindings under the `wailsjs` directory in your application.
|
||||
|
||||
:::
|
||||
|
||||
## Example
|
||||
|
||||
Importing the "Greet" method from the bindings like this:
|
||||
|
||||
```js
|
||||
import { Greet } from "../../wailsjs/go/main/App";
|
||||
|
||||
// snip
|
||||
Greet("World");
|
||||
```
|
||||
|
||||
will ensure that the method will work correctly in obfuscated mode, as the bindings will
|
||||
be regenerated with IDs and the call mechanism updated.
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
# Overscroll
|
||||
|
||||
[Overscroll](https://developer.mozilla.org/en-US/docs/Web/CSS/overscroll-behavior) is the "bounce effect" you sometimes
|
||||
get when you scroll beyond a page's content boundaries. This is common in mobile apps. This can be disabled using CSS:
|
||||
|
||||
```css
|
||||
html {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
```
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
# Routing
|
||||
|
||||
Routing is a popular way to switch views in an application. This page offers some guidance around how to do that.
|
||||
|
||||
## Vue
|
||||
|
||||
The recommended approach for routing in Vue is [Hash Mode](https://next.router.vuejs.org/guide/essentials/history-mode.html#hash-mode):
|
||||
|
||||
```js
|
||||
import { createRouter, createWebHashHistory } from "vue-router";
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
routes: [
|
||||
//...
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
## Angular
|
||||
|
||||
The recommended approach for routing in Angular is [HashLocationStrategy](https://codecraft.tv/courses/angular/routing/routing-strategies#_hashlocationstrategy):
|
||||
|
||||
```ts
|
||||
RouterModule.forRoot(routes, { useHash: true });
|
||||
```
|
||||
|
||||
## React
|
||||
|
||||
The recommended approach for routing in React is [HashRouter](https://reactrouter.com/en/main/router-components/hash-router):
|
||||
|
||||
```jsx
|
||||
import { HashRouter } from "react-router-dom";
|
||||
|
||||
ReactDOM.render(
|
||||
<HashRouter basename={"/"}>
|
||||
{/* The rest of your app goes here */}
|
||||
<Routes>
|
||||
<Route path="/" element={<Page0 />} exact />
|
||||
<Route path="/page1" element={<Page1 />} />
|
||||
<Route path="/page2" element={<Page2 />} />
|
||||
{/* more... */}
|
||||
</Routes>
|
||||
</HashRouter>,
|
||||
root
|
||||
);
|
||||
```
|
||||
|
|
@ -1,422 +0,0 @@
|
|||
# Code Signing
|
||||
|
||||
This is a guide on how you can sign your binaries generated with Wails on MacOS and Windows.
|
||||
The guide will target CI environments, more specifically GitHub Actions.
|
||||
|
||||
## Windows
|
||||
|
||||
First off you need a code signing certificate. If you do not already have one, Microsoft's
|
||||
info page lists some providers [here](https://docs.microsoft.com/en-us/windows-hardware/drivers/dashboard/get-a-code-signing-certificate).
|
||||
Please note that an EV certificate is not required unless you need to write kernel-level
|
||||
software such as device drivers. For signing your Wails app, a standard code signing
|
||||
certificate will do just fine.
|
||||
|
||||
It may be a good idea to check with your certificate provider
|
||||
how to sign your binaries on your local machine before targeting automated build systems, just so you know if there
|
||||
are any special requirements. For instance, [here](https://www.ssl.com/how-to/using-your-code-signing-certificate/) is SSL.com's code signing guide for Windows.
|
||||
If you know how to sign locally, it will be easier to
|
||||
troubleshoot any potential issues in a CI environment.
|
||||
For instance, SSL.com code signing certificates require the `/tr` flag for [SignTool.exe](https://docs.microsoft.com/en-us/windows/win32/seccrypto/signtool)
|
||||
while other providers may only need the `/t` flag for providing the timestamping server. Popular GitHub Actions for signing
|
||||
Windows binaries like [this one](https://github.com/Dana-Prajea/code-sign-action) does not support the `/tr` flag on SignTool.exe.
|
||||
Therefore this guide will focus on signing our app manually with PowerShell commands, but you can use actions like the [code-sign-action](https://github.com/Dana-Prajea/code-sign-action)
|
||||
Action if you prefer.
|
||||
|
||||
First off, let's make sure we are able to build our Wails app in our GitHub CI. Here is a small workflow template:
|
||||
|
||||
```yaml
|
||||
name: "example"
|
||||
on:
|
||||
workflow_dispatch:
|
||||
# This Action only starts when you go to Actions and manually run the workflow.
|
||||
|
||||
jobs:
|
||||
package:
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [windows-latest, macos-latest]
|
||||
go-version: [1.18]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
- name: setup node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 14
|
||||
# You may need to manually build you frontend manually here, unless you have configured frontend build and install commands in wails.json.
|
||||
- name: Get Wails
|
||||
run: go install github.com/wailsapp/wails/v2/cmd/wails@latest
|
||||
- name: Build Wails app
|
||||
run: |
|
||||
wails build
|
||||
- name: upload artifacts macOS
|
||||
if: matrix.platform == 'macos-latest'
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: wails-binaries-macos
|
||||
path: build/bin/*
|
||||
- name: upload artifacts windows
|
||||
if: matrix.platform == 'windows-latest'
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: wails-binaries-windows
|
||||
path: build/bin/*
|
||||
```
|
||||
|
||||
Next we need to give the GitHub workflow access to our signing certificate. This is done by encoding your .pfx or .p12 certificate
|
||||
into a base64 string. To do this in PowerShell, you can use the following command assuming your certificate is called 'my-cert.p12':
|
||||
|
||||
```PowerShell
|
||||
certutil -encode .\my-cert.p12 my-cert-base64.txt
|
||||
```
|
||||
|
||||
You should now have your .txt file with the base64 encoded certificate. It should start with _-----BEGIN CERTIFICATE-----_ and
|
||||
end with _-----END CERTIFICATE-----_. Now you need to make two action secrets on GitHub. Navigate to _Settings -> Secrets -> Actions_ and create the
|
||||
two following secrets:
|
||||
|
||||
- **WIN_SIGNING_CERT** with the contents of your base64 encoded certificate text.
|
||||
- **WIN_SIGNING_CERT_PASSWORD** with the contents of your certificate password.
|
||||
|
||||
Now we're ready to implement the signing in our workflow using one of the two methods:
|
||||
|
||||
### Method 1: signing with commands
|
||||
|
||||
This method uses PowerShell commands to sign our app, and leaves you control over the entire signing process.
|
||||
|
||||
After the `"Build Wails app"` step, we can add the following step to our workflow:
|
||||
|
||||
```yaml
|
||||
- name: Sign Windows binaries
|
||||
if: matrix.platform == 'windows-latest'
|
||||
run: |
|
||||
echo "Creating certificate file"
|
||||
New-Item -ItemType directory -Path certificate
|
||||
Set-Content -Path certificate\certificate.txt -Value '${{ secrets.WIN_SIGNING_CERT }}'
|
||||
certutil -decode certificate\certificate.txt certificate\certificate.pfx
|
||||
echo "Signing our binaries"
|
||||
& 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd <signing algorithm> /t <timestamping server> /f certificate\certificate.pfx /p '${{ secrets.WIN_SIGNING_CERT_PASSWORD }}' <path to binary>
|
||||
|
||||
```
|
||||
|
||||
This script creates a new directory for your certificate file, creates the certificate file from our base64 secret, converts it to a .pfx file,
|
||||
and finally signs the binary. The following variables needs to be replaced in the last line:
|
||||
|
||||
- **signing algorithm**: usually sha256.
|
||||
- **timestamping server**: URL to the timestamping server to use with your certificate.
|
||||
- **path to binary**: path to the binary you want to sign.
|
||||
|
||||
Given that our Wails config has `outputfilename` set to "app.exe" and that we have a certificate from SSL.com, this would be our workflow:
|
||||
|
||||
```yaml
|
||||
name: "example"
|
||||
on:
|
||||
workflow_dispatch:
|
||||
# This Action only starts when you go to Actions and manually run the workflow.
|
||||
|
||||
jobs:
|
||||
package:
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [windows-latest, macos-latest]
|
||||
go-version: [1.18]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
- name: setup node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 14
|
||||
# You may need to manually build you frontend here, unless you have configured frontend build and install commands in wails.json.
|
||||
- name: Get Wails
|
||||
run: go install github.com/wailsapp/wails/v2/cmd/wails@latest
|
||||
- name: Build Wails app
|
||||
run: |
|
||||
wails build
|
||||
- name: Sign Windows binaries
|
||||
if: matrix.platform == 'windows-latest'
|
||||
run: |
|
||||
echo "Creating certificate file"
|
||||
New-Item -ItemType directory -Path certificate
|
||||
Set-Content -Path certificate\certificate.txt -Value '${{ secrets.WIN_SIGNING_CERT }}'
|
||||
certutil -decode certificate\certificate.txt certificate\certificate.pfx
|
||||
echo "Signing our binaries"
|
||||
& 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd sha256 /tr http://ts.ssl.com /f certificate\certificate.pfx /p '${{ secrets.WIN_SIGNING_CERT_PASSWORD }}' .\build\bin\app.exe
|
||||
|
||||
- name: upload artifacts macOS
|
||||
if: matrix.platform == 'macos-latest'
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: wails-binaries-macos
|
||||
path: build/bin/*
|
||||
- name: upload artifacts windows
|
||||
if: matrix.platform == 'windows-latest'
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: wails-binaries-windows
|
||||
path: build/bin/*
|
||||
```
|
||||
|
||||
### Method 2: automatically signing with Action
|
||||
|
||||
It is possible to use a Windows code signing Action like [this](https://github.com/marketplace/actions/code-sign-a-file-with-pfx-certificate) one,
|
||||
but note it requires a SHA1 hash for the certificate and a certificate name. View an example of how to configure it on the Action's [marketplace](https://github.com/marketplace/actions/code-sign-a-file-with-pfx-certificate).
|
||||
|
||||
---
|
||||
|
||||
## MacOS
|
||||
|
||||
First off you need your code signing certificate from Apple. If you do not have one, a simple Google search will help you acquire one.
|
||||
Once you have your certificate, you need to export it and encode it to base64. [This tutorial](https://localazy.com/blog/how-to-automatically-sign-macos-apps-using-github-actions)
|
||||
shows you how to do that in an easy manner. Once you have exported your .p12 certificate file, you can encode it to base64 as seen in the tutorial with the following command:
|
||||
|
||||
```bash
|
||||
base64 Certificates.p12 | pbcopy
|
||||
```
|
||||
|
||||
Now you're ready to create some GitHub project secrets, just as with Windows:
|
||||
|
||||
- **APPLE_DEVELOPER_CERTIFICATE_P12_BASE64** with the contents of your newly copied base64 certificate.
|
||||
- **APPLE_DEVELOPER_CERTIFICATE_PASSWORD** with the contents of your certificate password.
|
||||
- **APPLE_PASSWORD** with the contents of an App-Specific password to your Apple-ID account which you can generate [here](https://appleid.apple.com/account/manage).
|
||||
|
||||
Let's make sure we are able to build our Wails app in our GitHub Action workflow. Here is a small template:
|
||||
|
||||
```yaml
|
||||
name: "example"
|
||||
on:
|
||||
workflow_dispatch:
|
||||
# This Action only starts when you go to Actions and manually run the workflow.
|
||||
|
||||
jobs:
|
||||
package:
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [windows-latest, macos-latest]
|
||||
go-version: [1.18]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
- name: setup node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 14
|
||||
# You may need to manually build you frontend here, unless you have configured frontend build and install commands in wails.json.
|
||||
- name: Get Wails
|
||||
run: go install github.com/wailsapp/wails/v2/cmd/wails@latest
|
||||
- name: Build Wails app
|
||||
run: |
|
||||
wails build
|
||||
- name: upload artifacts macOS
|
||||
if: matrix.platform == 'macos-latest'
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: wails-binaries-macos
|
||||
path: build/bin/*
|
||||
- name: upload artifacts windows
|
||||
if: matrix.platform == 'windows-latest'
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: wails-binaries-windows
|
||||
path: build/bin/*
|
||||
```
|
||||
|
||||
For code signing on macOS, [gon](https://github.com/Bearer/gon) is a very handy tool for code signing and communicating with Apple servers, also written in Go, and
|
||||
will be used in this guide.
|
||||
|
||||
After the `Build Wails app` step, add the following to the workflow:
|
||||
|
||||
```yaml
|
||||
- name: MacOS download gon for code signing and app notarization
|
||||
if: matrix.platform == 'macos-latest'
|
||||
run: |
|
||||
brew install Bearer/tap/gon
|
||||
```
|
||||
|
||||
Now we need to configure some gon config files in our `build/darwin` directory:
|
||||
|
||||
1. gon-sign.json:
|
||||
|
||||
```json
|
||||
{
|
||||
"source": ["./build/bin/app.app"],
|
||||
"bundle_id": "app.myapp",
|
||||
"apple_id": {
|
||||
"username": "my-appleid@email.com",
|
||||
"password": "@env:APPLE_PASSWORD",
|
||||
"provider": "ABCDE12345"
|
||||
},
|
||||
"sign": {
|
||||
"application_identity": "Developer ID Application: Human User"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Here is a brief break down of the above fields:
|
||||
|
||||
- `source`: The location of your wails binary to be signed
|
||||
- `apple_id`:
|
||||
- `username`: Your Apple ID email address
|
||||
- `password`: Your app-specific password, referenced using Gon's environment variable syntax
|
||||
- `provider`: Your team ID for your App Store Connect account
|
||||
- `sign`:
|
||||
- `application_identity`: Your Apple developer identity
|
||||
|
||||
Your developer identity and team ID can both by found on macOS by running the following command:
|
||||
|
||||
```bash
|
||||
$ security find-identity -v -p codesigning
|
||||
1) 00000000000000000000000000000000000000000 "Developer ID Application: Human User (ABCDE12345)"
|
||||
```
|
||||
|
||||
2. entitlements.plist:
|
||||
|
||||
```plist
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.downloads.read-write</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
In this file you configure the entitlements you need for you app, e.g. camera permissions if your app uses the camera. Read more about entitlements [here](https://developer.apple.com/documentation/bundleresources/entitlements).
|
||||
|
||||
Make sure you have updated your `Info.plist` file with the same bundle ID as you entered in `gon-sign.json`.
|
||||
Here's an example `Info.plist` file:
|
||||
|
||||
```plist
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0"><dict>
|
||||
<key>CFBundlePackageType</key><string>APPL</string>
|
||||
<key>CFBundleName</key><string>MyApp</string>
|
||||
<key>CFBundleExecutable</key><string>app</string>
|
||||
<key>CFBundleIdentifier</key><string>app.myapp</string>
|
||||
<key>CFBundleVersion</key><string>0.1.0</string>
|
||||
<key>CFBundleGetInfoString</key><string>My app is cool and nice and chill and</string>
|
||||
<key>CFBundleShortVersionString</key><string>0.1.0</string>
|
||||
<key>CFBundleIconFile</key><string>iconfile</string>
|
||||
<key>LSMinimumSystemVersion</key><string>10.13.0</string>
|
||||
<key>NSHighResolutionCapable</key><string>true</string>
|
||||
<key>LSApplicationCategoryType</key><string>public.app-category.utilities</string>
|
||||
<key>NSHumanReadableCopyright</key><string>© Me</string>
|
||||
</dict></plist>
|
||||
```
|
||||
|
||||
Now we're ready to add the signing step in our workflow after building the Wails app:
|
||||
|
||||
```yaml
|
||||
- name: Import Code-Signing Certificates for macOS
|
||||
if: matrix.platform == 'macos-latest'
|
||||
uses: Apple-Actions/import-codesign-certs@v1
|
||||
with:
|
||||
# The certificates in a PKCS12 file encoded as a base64 string
|
||||
p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }}
|
||||
# The password used to import the PKCS12 file.
|
||||
p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }}
|
||||
- name: Sign our macOS binary
|
||||
if: matrix.platform == 'macos-latest'
|
||||
run: |
|
||||
echo "Signing Package"
|
||||
gon -log-level=info ./build/darwin/gon-sign.json
|
||||
```
|
||||
|
||||
Please note that signing binaries with Apple could take anywhere from minutes to hours.
|
||||
|
||||
## Combined workflow file:
|
||||
|
||||
Here is our GitHub workflow file with Windows + macOS combined:
|
||||
|
||||
```yaml
|
||||
name: "example combined"
|
||||
on:
|
||||
workflow_dispatch:
|
||||
# This Action only starts when you go to Actions and manually run the workflow.
|
||||
|
||||
jobs:
|
||||
package:
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [windows-latest, macos-latest]
|
||||
go-version: [1.18]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
- name: setup node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 14
|
||||
# You may need to manually build you frontend here, unless you have configured frontend build and install commands in wails.json.
|
||||
- name: Get Wails
|
||||
run: go install github.com/wailsapp/wails/v2/cmd/wails@latest
|
||||
- name: Build Wails app
|
||||
run: |
|
||||
wails build
|
||||
- name: MacOS download gon for code signing and app notarization
|
||||
if: matrix.platform == 'macos-latest'
|
||||
run: |
|
||||
brew install Bearer/tap/gon
|
||||
- name: Import Code-Signing Certificates for macOS
|
||||
if: matrix.platform == 'macos-latest'
|
||||
uses: Apple-Actions/import-codesign-certs@v1
|
||||
with:
|
||||
# The certificates in a PKCS12 file encoded as a base64 string
|
||||
p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }}
|
||||
# The password used to import the PKCS12 file.
|
||||
p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }}
|
||||
- name: Sign our macOS binary
|
||||
if: matrix.platform == 'macos-latest'
|
||||
run: |
|
||||
echo "Signing Package"
|
||||
gon -log-level=info ./build/darwin/gon-sign.json
|
||||
- name: Sign Windows binaries
|
||||
if: matrix.platform == 'windows-latest'
|
||||
run: |
|
||||
echo "Creating certificate file"
|
||||
New-Item -ItemType directory -Path certificate
|
||||
Set-Content -Path certificate\certificate.txt -Value '${{ secrets.WIN_SIGNING_CERT }}'
|
||||
certutil -decode certificate\certificate.txt certificate\certificate.pfx
|
||||
echo "Signing our binaries"
|
||||
& 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd sha256 /tr http://ts.ssl.com /f certificate\certificate.pfx /p '${{ secrets.WIN_SIGNING_CERT_PASSWORD }}' .\build\bin\Monitor.exe
|
||||
- name: upload artifacts macOS
|
||||
if: matrix.platform == 'macos-latest'
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: wails-binaries-macos
|
||||
path: build/bin/*
|
||||
- name: upload artifacts windows
|
||||
if: matrix.platform == 'windows-latest'
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: wails-binaries-windows
|
||||
path: build/bin/*
|
||||
```
|
||||
|
||||
# End notes
|
||||
|
||||
This guide inspired by the RiftShare project and its workflow, which is highly recommended to check out [here](https://github.com/achhabra2/riftshare/blob/main/.github/workflows/build.yaml).
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
# Single Instance Lock
|
||||
|
||||
Single instance lock is a mechanism that allows you to prevent multiple instances of your app from running at the same time.
|
||||
It is useful for apps that are designed to open files from the command line or from the OS file explorer.
|
||||
|
||||
## Important
|
||||
|
||||
Single Instance Lock does not implement a secure communications protocol between instances. When using single instance lock,
|
||||
your app should treat any data passed to it from second instance callback as untrusted.
|
||||
You should verify that args that you receive are valid and don't contain any malicious data.
|
||||
|
||||
## How it works
|
||||
|
||||
Windows: Single instance lock is implemented using a named mutex. The mutex name is generated from the unique id that you provide. Data is passed to the first instance via a shared window using [SendMessage](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage)
|
||||
macOS: Single instance lock is implemented using a named mutex. The mutex name is generated from the unique id that you provide. Data is passed to the first instance via [NSDistributedNotificationCenter](https://developer.apple.com/documentation/foundation/nsdistributednotificationcenter)
|
||||
Linux: Single instance lock is implemented using [dbus](https://www.freedesktop.org/wiki/Software/dbus/). The dbus name is generated from the unique id that you provide. Data is passed to the first instance via [dbus](https://www.freedesktop.org/wiki/Software/dbus/)
|
||||
|
||||
## Usage
|
||||
When creating your app, you can enable single instance lock by passing a `SingleInstanceLock` struct to the `App` struct.
|
||||
Use the `UniqueId` field to specify a unique id for your app.
|
||||
This id is used to generate the mutex name on Windows and macOS and the dbus name on Linux. Use a UUID to ensure that the id is unique.
|
||||
The `OnSecondInstanceLaunch` field is used to specify a callback that is called when a second instance of your app is launched.
|
||||
The callback receives a `SecondInstanceData` struct that contains the command line arguments passed to the second instance and the working directory of the second instance.
|
||||
|
||||
Note that OnSecondInstanceLaunch don't trigger windows focus.
|
||||
You need to call `runtime.WindowUnminimise` and `runtime.Show` to bring your app to the front.
|
||||
Note that on linux systems window managers may prevent your app from being brought to the front to avoid stealing focus.
|
||||
|
||||
```go title="main.go"
|
||||
var wailsContext *context.Context
|
||||
|
||||
// NewApp creates a new App application struct
|
||||
func NewApp() *App {
|
||||
return &App{}
|
||||
}
|
||||
|
||||
// startup is called when the app starts. The context is saved
|
||||
// so we can call the runtime methods
|
||||
func (a *App) startup(ctx context.Context) {
|
||||
wailsContext = &ctx
|
||||
}
|
||||
|
||||
func (a *App) onSecondInstanceLaunch(secondInstanceData options.SecondInstanceData) {
|
||||
secondInstanceArgs = secondInstanceData.Args
|
||||
|
||||
println("user opened second instance", strings.Join(secondInstanceData.Args, ","))
|
||||
println("user opened second from", secondInstanceData.WorkingDirectory)
|
||||
runtime.WindowUnminimise(*wailsContext)
|
||||
runtime.Show(*wailsContext)
|
||||
go runtime.EventsEmit(*wailsContext, "launchArgs", secondInstanceArgs)
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Create an instance of the app structure
|
||||
app := NewApp()
|
||||
|
||||
// Create application with options
|
||||
err := wails.Run(&options.App{
|
||||
Title: "wails-open-file",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
},
|
||||
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
|
||||
OnStartup: app.startup,
|
||||
SingleInstanceLock: &options.SingleInstanceLock{
|
||||
UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc",
|
||||
OnSecondInstanceLaunch: app.onSecondInstanceLaunch,
|
||||
},
|
||||
Bind: []interface{}{
|
||||
app,
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
println("Error:", err.Error())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
# SvelteKit
|
||||
|
||||
This guide will go into:
|
||||
1. Miminal Installation Steps - The steps needed to get a minimum Wails setup working for SvelteKit.
|
||||
2. Install Script - Bash script for accomplishing the Minimal Installation Steps with optional Wails branding.
|
||||
3. Important Notes - Issues that can be encountered when using SvelteKit + Wails and fixes.
|
||||
|
||||
## 1. Minimal Installation Steps
|
||||
|
||||
##### Install Wails for Svelte.
|
||||
- `wails init -n myapp -t svelte`
|
||||
|
||||
##### Delete the svelte frontend.
|
||||
- Navigate into your newly created myapp folder.
|
||||
- Delete the folder named "frontend"
|
||||
|
||||
##### While in the Wails project root. Use your favorite package manager and install SvelteKit as the new frontend. Follow the prompts.
|
||||
- `npm create svelte@latest frontend`
|
||||
|
||||
##### Modify wails.json.
|
||||
- Add `"wailsjsdir": "./frontend/src/lib",` Do note that this is where your Go and runtime functions will appear.
|
||||
- Change your package manager frontend here if not using npm.
|
||||
|
||||
##### Modify main.go.
|
||||
- The first comment `//go:embed all:frontend/dist` needs to be changed to `//go:embed all:frontend/build`
|
||||
|
||||
##### Modify .gitignore
|
||||
- The line `frontend/dist` needs to be replaced with `frontend/build`
|
||||
|
||||
##### Install/remove dependencies using your favorite package manager.
|
||||
- Navigate into your "frontend" folder.
|
||||
- `npm i`
|
||||
- `npm uninstall @sveltejs/adapter-auto`
|
||||
- `npm i -D @sveltejs/adapter-static`
|
||||
|
||||
##### Change adapter in svelte.config.js
|
||||
- First line of file change `import adapter from '@sveltejs/adapter-auto';` to `import adapter from '@sveltejs/adapter-static';`
|
||||
|
||||
##### Put SvelteKit into SPA mode with prerendering.
|
||||
- Create a file under myapp/frontend/src/routes/ named +layout.ts/+layout.js.
|
||||
- Add two lines into the newly created file `export const prerender = true` and `export const ssr = false`
|
||||
|
||||
##### Test installation.
|
||||
- Navigate back into the Wails project root (one directory up).
|
||||
- run `wails dev`
|
||||
- If the application doesn't run please check through the previous steps.
|
||||
|
||||
## 2. Install Script
|
||||
|
||||
##### This Bash Script does the steps listed above. Make sure to read over the script and understand what the script is doing on your computer.
|
||||
|
||||
- Create a file sveltekit-wails.sh
|
||||
- Copy the below code into the new file then save it.
|
||||
- Make it executable with `chmod +x sveltekit-wails.sh`
|
||||
- Brand is an optional param below that adds back in the wails branding. Leave third param blank to not insert the Wails branding.
|
||||
- Example usage: `./sveltekit-wails.sh pnpm newapp brand`
|
||||
|
||||
##### sveltekit-wails.sh:
|
||||
```
|
||||
manager=$1
|
||||
project=$2
|
||||
brand=$3
|
||||
wails init -n $project -t svelte
|
||||
cd $project
|
||||
sed -i "s|npm|$manager|g" wails.json
|
||||
sed -i 's|"auto",|"auto",\n "wailsjsdir": "./frontend/src/lib",|' wails.json
|
||||
sed -i "s|all:frontend/dist|all:frontend/build|" main.go
|
||||
if [[ -n $brand ]]; then
|
||||
mv frontend/src/App.svelte +page.svelte
|
||||
sed -i "s|'./assets|'\$lib/assets|" +page.svelte
|
||||
sed -i "s|'../wails|'\$lib/wails|" +page.svelte
|
||||
mv frontend/src/assets .
|
||||
fi
|
||||
rm -r frontend
|
||||
$manager create svelte@latest frontend
|
||||
if [[ -n $brand ]]; then
|
||||
mv +page.svelte frontend/src/routes/+page.svelte
|
||||
mkdir frontend/src/lib
|
||||
mv assets frontend/src/lib/
|
||||
fi
|
||||
cd frontend
|
||||
$manager i
|
||||
$manager uninstall @sveltejs/adapter-auto
|
||||
$manager i -D @sveltejs/adapter-static
|
||||
echo -e "export const prerender = true\nexport const ssr = false" > src/routes/+layout.ts
|
||||
sed -i "s|-auto';|-static';|" svelte.config.js
|
||||
cd ..
|
||||
wails dev
|
||||
```
|
||||
|
||||
## 3. Important Notes
|
||||
|
||||
##### Server files will cause build failures.
|
||||
- +layout.server.ts, +page.server.ts, +server.ts or any file with "server" in the name will fail to build as all routes are prerendered.
|
||||
|
||||
##### The Wails runtime unloads with full page navigations!
|
||||
- Anything that causes full page navigations: `window.location.href = '/<some>/<page>'` or Context menu reload when using wails dev. What this means is that you can end up losing the ability to call any runtime breaking the app. There are two ways to work around this.
|
||||
- Use `import { goto } from '$app/navigation'` then call `goto('/<some>/<page>')` in your +page.svelte. This will prevent a full page navigation.
|
||||
- If full page navigation can't be prevented the Wails runtime can be added to all pages by adding the below into the `<head>` of myapp/frontend/src/app.html
|
||||
```
|
||||
<head>
|
||||
...
|
||||
<meta name="wails-options" content="noautoinject" />
|
||||
<script src="/wails/ipc.js"></script>
|
||||
<script src="/wails/runtime.js"></script>
|
||||
...
|
||||
</head>
|
||||
```
|
||||
See https://wails.io/docs/guides/frontend for more information.
|
||||
|
||||
##### Inital data can be loaded and refreshed from +page.ts/+page.js to +page.svelte.
|
||||
- +page.ts/+page.js works well with load() https://kit.svelte.dev/docs/load#page-data
|
||||
- invalidateAll() in +page.svelte will call load() from +page.ts/+page.js https://kit.svelte.dev/docs/load#rerunning-load-functions-manual-invalidation.
|
||||
|
||||
##### Error Handling
|
||||
- Expected errors using Throw error works in +page.ts/+page.js with a +error.svelte page. https://kit.svelte.dev/docs/errors#expected-errors
|
||||
- Unexpected errors will cause the application to become unusable. Only recovery option (known so far) from unexpected errors is to reload the app. To do this create a file myapp/frontend/src/hooks.client.ts then add the below code to the file.
|
||||
```
|
||||
import { WindowReloadApp } from '$lib/wailsjs/runtime/runtime'
|
||||
export async function handleError() {
|
||||
WindowReloadApp()
|
||||
}
|
||||
```
|
||||
|
||||
##### Using Forms and handling functions
|
||||
- The simplest way is to call a function from the form is the standard, bind:value your variables and prevent submission `<form method="POST" on:submit|preventDefault={handle}>`
|
||||
- The more advanced way is to use:enhance (progressive enhancement) which will allow for convenient access to formData, formElement, submitter. The important note is to always cancel() the form which prevents server side behavior. https://kit.svelte.dev/docs/form-actions#progressive-enhancement Example:
|
||||
```
|
||||
<form method="POST" use:enhance={({cancel, formData, formElement, submitter}) => {
|
||||
cancel()
|
||||
console.log(Object.fromEntries(formData))
|
||||
console.log(formElement)
|
||||
console.log(submitter)
|
||||
handle()
|
||||
}}>
|
||||
```
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
# Templates
|
||||
|
||||
Wails generates projects from pre-created templates. In v1, this was a difficult to maintain set of projects that were
|
||||
subject to going out of date. In v2, to empower the community, a couple of new features have been added for templates:
|
||||
|
||||
- Ability to generate projects from [Remote Templates](../reference/cli.mdx#remote-templates)
|
||||
- Tooling to help create your own templates
|
||||
|
||||
## Creating Templates
|
||||
|
||||
To create a template, you can use the `wails generate template` command. To generate a default template, run:
|
||||
|
||||
`wails generate template -name mytemplate `
|
||||
|
||||
This creates the directory "mytemplate" with default files:
|
||||
|
||||
```shell title=mytemplate/
|
||||
.
|
||||
|-- NEXTSTEPS.md
|
||||
|-- README.md
|
||||
|-- app.tmpl.go
|
||||
|-- frontend
|
||||
| `-- dist
|
||||
| |-- assets
|
||||
| | |-- fonts
|
||||
| | | |-- OFL.txt
|
||||
| | | `-- nunito-v16-latin-regular.woff2
|
||||
| | `-- images
|
||||
| | `-- logo-dark.svg
|
||||
| |-- index.html
|
||||
| |-- main.css
|
||||
| `-- main.js
|
||||
|-- go.mod.tmpl
|
||||
|-- main.tmpl.go
|
||||
|-- template.json
|
||||
`-- wails.tmpl.json
|
||||
```
|
||||
|
||||
### Template Overview
|
||||
|
||||
The default template consists of the following files and directories:
|
||||
|
||||
| Filename / Dir | Description |
|
||||
| --------------- | -------------------------------------------- |
|
||||
| NEXTSTEPS.md | Instructions on how to complete the template |
|
||||
| README.md | The README published with the template |
|
||||
| app.tmpl.go | `app.go` template file |
|
||||
| frontend/ | The directory containing frontend assets |
|
||||
| go.mod.tmpl | `go.mod` template file |
|
||||
| main.tmpl.go | `main.go` template file |
|
||||
| template.json | The template metadata |
|
||||
| wails.tmpl.json | `wails.json` template file |
|
||||
|
||||
At this point it is advisable to follow the steps in `NEXTSTEPS.md`.
|
||||
|
||||
## Creating a Template from an Existing Project
|
||||
|
||||
It's possible to create a template from an existing frontend project by passing the path to the project when generating
|
||||
the template. We will now walk through how to create a Vue 3 template:
|
||||
|
||||
- Install the vue cli: `npm install -g @vue/cli`
|
||||
- Create the default project: `vue create vue3-base`
|
||||
- Select `Default (Vue 3) ([Vue 3] babel, eslint)`
|
||||
- After the project has been generated, run:
|
||||
|
||||
```shell
|
||||
> wails generate template -name wails-vue3-template -frontend .\vue3-base\
|
||||
Extracting base template files...
|
||||
Migrating existing project files to frontend directory...
|
||||
Updating package.json data...
|
||||
Renaming package.json -> package.tmpl.json...
|
||||
Updating package-lock.json data...
|
||||
Renaming package-lock.json -> package-lock.tmpl.json...
|
||||
```
|
||||
|
||||
- The template may now be customised as specified in the `NEXTSTEPS.md` file
|
||||
- Once the files are ready, it can be tested by running: `wails init -n my-vue3-project -t .\wails-vue3-template\`
|
||||
- To test the new project, run: `cd my-vue3-project` then `wails build`
|
||||
- Once the project has compiled, run it: `.\build\bin\my-vue3-project.exe`
|
||||
- You should have a fully functioning Vue3 application:
|
||||
|
||||
```mdx-code-block
|
||||
<div className="text--center">
|
||||
<img
|
||||
src={require("@site/static/img/vue3-template.png").default}
|
||||
width="50%"
|
||||
/>
|
||||
</div>
|
||||
```
|
||||
|
||||
## Publishing Templates
|
||||
|
||||
Publishing a template is simply pushing the files to GitHub. The following best practice is encouraged:
|
||||
|
||||
- Remove any unwanted files and directories (such as `.git`) from your frontend directory
|
||||
- Ensure that `template.json` is complete, especially `helpurl`
|
||||
- Push the files to GitHub
|
||||
- Create a PR on the [Community Templates](../community/templates.mdx) page
|
||||
- Announce the template on the [Template Announcement](https://github.com/wailsapp/wails/discussions/825) discussion board
|
||||
|
|
@ -1,385 +0,0 @@
|
|||
# Troubleshooting
|
||||
|
||||
An assortment of troubleshooting tips.
|
||||
|
||||
## The `wails` command appears to be missing?
|
||||
|
||||
If your system is reporting that the `wails` command is missing, make sure you have followed the Go installation guide
|
||||
correctly. Normally, it means that the `go/bin` directory in your User's home directory is not in the `PATH` environment
|
||||
variable. You will also normally need to close and reopen any open command prompts so that changes to the environment
|
||||
made by the installer are reflected at the command prompt.
|
||||
|
||||
## My application is displaying a white/blank screen
|
||||
|
||||
Check that your application includes the assets from the correct directory. In your `main.go` file, you will have
|
||||
something similar to the following code:
|
||||
|
||||
```go
|
||||
//go:embed all:frontend/dist
|
||||
var assets embed.FS
|
||||
```
|
||||
|
||||
Check that `frontend/dist` contains your application assets.
|
||||
|
||||
### Mac
|
||||
|
||||
If this happens on Mac, try adding the following to your `Info.plist`:
|
||||
|
||||
```xml
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsLocalNetworking</key>
|
||||
<true/>
|
||||
</dict>
|
||||
```
|
||||
|
||||
Reference: https://github.com/wailsapp/wails/issues/1504#issuecomment-1174317433
|
||||
|
||||
## Mac application not valid
|
||||
|
||||
If your built application looks like this in finder:
|
||||
|
||||
```mdx-code-block
|
||||
<p className="text--center">
|
||||
<img
|
||||
src={
|
||||
require("@site/static/img/troubleshooting/invalid_mac_app.png").default
|
||||
}
|
||||
/>
|
||||
</p>
|
||||
```
|
||||
|
||||
it's likely that your application's `info.plist` is invalid. Update the file in `build/<yourapp>.app/Contents/info.plist`
|
||||
and check if the data is valid, EG check the binary name is correct. To persist the changes, copy the file back to
|
||||
the `build/darwin` directory.
|
||||
|
||||
## My application is not displaying the correct icon in Windows Explorer
|
||||
|
||||
If your application is not displaying the correct icon, try deleting the hidden `IconCache.db` file located in the
|
||||
`C:\Users\<your username>\AppData\Local` directory. This will force Windows to rebuild the icon cache.
|
||||
|
||||
Source: https://github.com/wailsapp/wails/issues/2360#issuecomment-1556070036
|
||||
|
||||
## Cannot call backend method from frontend with variadic arguments
|
||||
|
||||
If you have a backend method defined with variadic parameters, eg:
|
||||
|
||||
```go
|
||||
func (a *App) TestFunc(msg string, args ...interface{}) error {
|
||||
// Code
|
||||
}
|
||||
```
|
||||
|
||||
calling this method from the frontend like this will fail:
|
||||
|
||||
```js
|
||||
var msg = "Hello: ";
|
||||
var args = ["Go", "JS"];
|
||||
window.go.main.App.TestFunc(msg, ...args)
|
||||
.then((result) => {
|
||||
//do things here
|
||||
})
|
||||
.catch((error) => {
|
||||
//handle error
|
||||
});
|
||||
```
|
||||
|
||||
Workaround:
|
||||
|
||||
```js
|
||||
var msg = "Hello ";
|
||||
var args = ["Go", "JS"];
|
||||
window.go.main.App.TestFunc(msg, args)
|
||||
.then((result) => {
|
||||
//without the 3 dots
|
||||
//do things here
|
||||
})
|
||||
.catch((error) => {
|
||||
//handle error
|
||||
});
|
||||
```
|
||||
|
||||
Credit: https://github.com/wailsapp/wails/issues/1186
|
||||
|
||||
## I'm having getting proxy errors when trying to install Wails
|
||||
|
||||
If you are getting errors like this:
|
||||
|
||||
```
|
||||
"https://proxy.golang.org/github.com/wailsapp/wails/cmd/wails/@v/list": dial tcp 172.217.163.49:443: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
|
||||
```
|
||||
|
||||
it's probably because the official Go Proxy is being blocked (Users in China have reported this).
|
||||
The solution is to set up the proxy manually, eg:
|
||||
|
||||
```
|
||||
go env -w GO111MODULE=on
|
||||
go env -w GOPROXY=https://goproxy.cn,direct
|
||||
```
|
||||
|
||||
Source: https://github.com/wailsapp/wails/issues/1233
|
||||
|
||||
## The generated TypeScript doesn't have the correct types
|
||||
|
||||
Sometimes the generated TypeScript doesn't have the correct types. To mitigate this,
|
||||
it is possible to specify what types should be generated using the `ts_type` struct tag. For
|
||||
more details, please read [this](https://github.com/tkrajina/typescriptify-golang-structs#custom-types).
|
||||
|
||||
## When I navigate away from `index.html`, I am unable to call methods on the frontend
|
||||
|
||||
If you navigate away from `index.html` to a new html file, the context will be lost. This can be fixed by adding
|
||||
the following imports to the `<head>` section of any new page you navigate to:
|
||||
|
||||
```html
|
||||
<head>
|
||||
<script src="/wails/ipc.js"></script>
|
||||
<script src="/wails/runtime.js"></script>
|
||||
</head>
|
||||
```
|
||||
|
||||
Source: https://github.com/wailsapp/wails/discussions/1512
|
||||
|
||||
## I get `too many open files` errors on my Mac when I run `wails dev`
|
||||
|
||||
By default, macOS will only allow you to open a maximum of 256 files. This can affect the `wails dev` command.
|
||||
This limit can be increased by running: `ulimit -n 1024` in the terminal.
|
||||
|
||||
FSNotify is [looking to move to Apple's fsevents](https://github.com/fsnotify/fsnotify/issues/11) for Mac.
|
||||
If this isn't completed soon, we will create our own implementation, tracked [here](https://github.com/wailsapp/wails/issues/1733).
|
||||
|
||||
## My Mac app gives me weird compilation errors
|
||||
|
||||
A few users have reported seeing compilation errors such as the following:
|
||||
|
||||
```shell
|
||||
# github.com/wailsapp/wails/v2/internal/frontend/desktop/darwin
|
||||
In file included from ../../pkg/mod/github.com/wailsapp/wails/v2@v2.0.0-beta.44.2/internal/frontend/desktop/darwin/callbacks.go:9:
|
||||
In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h:12:
|
||||
/Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSBundle.h:91:143: error: function does not return NSString
|
||||
- (NSAttributedString *)localizedAttributedStringForKey:(NSString *)key value:(nullable NSString *)value table:(nullable NSString *)tableName NS_FORMAT_ARGUMENT(1) NS_REFINED_FOR_SWIFT API_AVAILABLE(macos(12.0), ios(15.0), watchos(8.0), tvos(15.0));
|
||||
~~~~~~~~~~~~~~ ^ ~
|
||||
/Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:103:48: note: expanded from macro 'NS_FORMAT_ARGUMENT'
|
||||
#define NS_FORMAT_ARGUMENT(A) __attribute__ ((format_arg(A)))
|
||||
```
|
||||
|
||||
This is _normally_ due to a mismatch with the OS version you are running and the version of the XCode Command Line Tools
|
||||
installed. If you see an error like this, try upgrading your XCode Command Line Tools to the latest version.
|
||||
|
||||
If reinstalling Xcode Command Tools still fails, you can check the path where the toolkit is located using:
|
||||
|
||||
`xcode-select -p`
|
||||
|
||||
If `/Applications/Xcode.app/Contents/Developer` is displayed, run `sudo xcode-select --switch /Library/Developer/CommandLineTools`
|
||||
|
||||
Sources: https://github.com/wailsapp/wails/issues/1806 and https://github.com/wailsapp/wails/issues/1140#issuecomment-1290446496
|
||||
|
||||
## My application won't compile on Mac
|
||||
|
||||
If you are getting errors like this:
|
||||
|
||||
```shell
|
||||
l1@m2 GoEasyDesigner % go build -tags dev -gcflags "all=-N -l"
|
||||
/Users/l1/sdk/go1.20.5/pkg/tool/darwin_arm64/link: running clang failed: exit status 1
|
||||
Undefined symbols for architecture arm64:
|
||||
"_OBJC_CLASS_$_UTType", referenced from:
|
||||
objc-class-ref in 000016.o
|
||||
ld: symbol(s) not found for architecture arm64
|
||||
clang: error: linker command failed with exit code 1 (use -v to see invocation)
|
||||
```
|
||||
Ensure you have the latest SDK installed. If so and you're still experiencing this issue, try the following:
|
||||
|
||||
```shell
|
||||
export CGO_LDFLAGS="-framework UniformTypeIdentifiers" && go build -tags dev -gcflags "all=-N -l"
|
||||
```
|
||||
|
||||
Sources: https://github.com/wailsapp/wails/pull/2925#issuecomment-1726828562
|
||||
|
||||
|
||||
--
|
||||
|
||||
## Cannot start service: Host version "x.x.x does not match binary version "x.x.x"
|
||||
|
||||
It's preferable to add `frontend/node_modules` and `frontend/package-lock.json` to your `.gitignore`. Otherwise when opening your repository on another machine
|
||||
that may have different versions of Node installed, you may not be able to run your application.
|
||||
|
||||
If this does happen, simply delete `frontend/node_modules` and `frontend/package-lock.json` and run your `wails build` or `wails dev` command again.
|
||||
|
||||
## Build process stuck on "Generating bindings"
|
||||
|
||||
Bindings generation process runs your application in a special mode. If application, intentionally or unintentionally, contains an endless loop (i.e. not exiting after `wails.Run()` finished), this can lead to build process stuck on the stage of bindings generation. Please make sure your code exits properly.
|
||||
|
||||
## Mac application flashes white at startup
|
||||
|
||||
This is due to the default background of the webview being white. If you want to use the window background colour instead,
|
||||
you can make the webview background transparent using the following config:
|
||||
|
||||
```go
|
||||
err := wails.Run(&options.App{
|
||||
Title: "macflash",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
// Other settings
|
||||
Mac: &mac.Options{
|
||||
WebviewIsTransparent: true,
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## I get a "Microsoft Edge can't read or write to its data directory" error when running my program as admin on Windows
|
||||
|
||||
You set your program to require admin permissions and it worked great! Unfortunately, some users are seeing a "Microsoft Edge can't read or write to its data directory" error when running it.
|
||||
|
||||
When a Windows machine has two local accounts:
|
||||
|
||||
- Alice, an admin
|
||||
- Bob, a regular user
|
||||
|
||||
Bob sees a UAC prompt when running your program. Bob enters Alice's admin credentials into this prompt. The app launches with admin permissions under Alice's account.
|
||||
|
||||
Wails instructs WebView2 to store user data at the specified `WebviewUserDataPath`. It defaults to `%APPDATA%\[BinaryName.exe]`.
|
||||
|
||||
Because the application is running under Alice's account, `%APPDATA%\[BinaryName.exe]` resolves to `C:\Users\Alice\AppData\Roaming\[BinaryName.exe]`.
|
||||
|
||||
WebView2 [creates some child processes under Bob's logged-in account instead of Alice's admin account](https://github.com/MicrosoftEdge/WebView2Feedback/issues/932#issue-807464179). Since Bob cannot access `C:\Users\Alice\AppData\Roaming\[BinaryName.exe]`, the "Microsoft Edge can't read or write to its data directory" error is shown.
|
||||
|
||||
Possible solution #1:
|
||||
|
||||
Refactor your application to work without constant admin permissions. If you just need to perform a small set of admin tasks (such as running an updater), you can run your application with the minimum permissions and then use the `runas` command to run these tasks with admin permissions as needed:
|
||||
|
||||
```go
|
||||
//go:build windows
|
||||
|
||||
package sample
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/windows"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Calling RunAs("C:\path\to\my\updater.exe") shows Bob a UAC prompt. Bob enters Alice's admin credentials. The updater launches with admin permissions under Alice's account.
|
||||
func RunAs(path string) error {
|
||||
verbPtr, _ := syscall.UTF16PtrFromString("runas")
|
||||
exePtr, _ := syscall.UTF16PtrFromString(path)
|
||||
cwdPtr, _ := syscall.UTF16PtrFromString("")
|
||||
argPtr, _ := syscall.UTF16PtrFromString("")
|
||||
|
||||
var showCmd int32 = 1 //SW_NORMAL
|
||||
|
||||
err := windows.ShellExecute(0, verbPtr, exePtr, argPtr, cwdPtr, showCmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
Possible solution #2:
|
||||
|
||||
Run your application with extended permissions. If you absolutely must run with constant admin permissions, WebView2 will function correctly if you use a data directory accessible by both users and you also launch your app with the `SeBackupPrivilege`, `SeDebugPrivilege`, and `SeRestorePrivilege` permissions. Here's an example:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/fourcorelabs/wintoken"
|
||||
"github.com/hectane/go-acl"
|
||||
"github.com/wailsapp/wails/v2"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/windows"
|
||||
)
|
||||
|
||||
//go:embed all:frontend/dist
|
||||
var assets embed.FS
|
||||
|
||||
const (
|
||||
fixedTokenKey = "SAMPLE_RANDOM_KEY"
|
||||
fixedTokenVal = "with-fixed-token"
|
||||
webviewDir = "C:\\ProgramData\\Sample"
|
||||
)
|
||||
|
||||
func runWithFixedToken() {
|
||||
println("Re-launching self")
|
||||
token, err := wintoken.OpenProcessToken(0, wintoken.TokenPrimary) //pass 0 for own process
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer token.Close()
|
||||
|
||||
token.EnableTokenPrivileges([]string{
|
||||
"SeBackupPrivilege",
|
||||
"SeDebugPrivilege",
|
||||
"SeRestorePrivilege",
|
||||
})
|
||||
|
||||
cmd := exec.Command(os.Args[0])
|
||||
cmd.Args = os.Args
|
||||
cmd.Env = os.Environ()
|
||||
cmd.Env = append(cmd.Env, fmt.Sprintf("%v=%v", fixedTokenKey, fixedTokenVal))
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{Token: syscall.Token(token.Token())}
|
||||
if err := cmd.Run(); err != nil {
|
||||
println("Error after launching self:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
println("Clean self launch :)")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func main() {
|
||||
if runtime.GOOS == "windows" && os.Getenv(fixedTokenKey) != fixedTokenVal {
|
||||
runWithFixedToken()
|
||||
}
|
||||
|
||||
println("Setting data dir to", webviewDir)
|
||||
if err := os.MkdirAll(webviewDir, os.ModePerm); err != nil {
|
||||
println("Failed creating dir:", err)
|
||||
}
|
||||
if err := acl.Chmod(webviewDir, 0777); err != nil {
|
||||
println("Failed setting ACL on dir:", err)
|
||||
}
|
||||
|
||||
app := NewApp()
|
||||
|
||||
err := wails.Run(&options.App{
|
||||
Title: "sample-data-dir",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
},
|
||||
Bind: []interface{}{
|
||||
app,
|
||||
},
|
||||
Windows: &windows.Options{
|
||||
WebviewUserDataPath: webviewDir,
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
println("Error:", err.Error())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If you use a data directory accessible by both users but not the extended privileges, you will receive a WebView2 `80010108 The object invoked has disconnected from its clients` error.
|
||||
|
||||
Possible future solution #3: [run WebView2 using an in-memory mode if implemented](https://github.com/MicrosoftEdge/WebView2Feedback/issues/3637#issuecomment-1728300982).
|
||||
|
||||
## WebView2 installation succeeded, but the wails doctor command shows that it is not installed
|
||||
|
||||
If you have installed WebView2, but the `wails doctor` command shows that it is not installed, it is likely that the
|
||||
WebView2 runtime installed was for a different architecture. You can download the correct runtime from [here](https://developer.microsoft.com/en-us/microsoft-edge/webview2/).
|
||||
|
||||
Source: https://github.com/wailsapp/wails/issues/2917
|
||||
|
||||
## WebVie2wProcess failed with kind
|
||||
|
||||
If your Windows app generates this kind of error, you can check out what the error means [here](https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/winrt/microsoft_web_webview2_core/corewebview2processfailedkind?view=webview2-winrt-1.0.2045.28).
|
||||
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
|
||||
# Visual Studio Code
|
||||
|
||||
This page is for miscellaneous tips and tricks when using Visual Studio Code with Wails.
|
||||
|
||||
## Vetur Configuration
|
||||
|
||||
Many thanks to [@Lyimmi](https://github.com/Lyimmi) for this tip. Originally posted
|
||||
[here](https://github.com/wailsapp/wails/issues/1791#issuecomment-1228158349).
|
||||
|
||||
Vetur is a popular plugin for Visual Studio Code that provides syntax highlighting and code completion
|
||||
for Vue projects. When loading a Wails project in VSCode, Vetur will throw an error as it is expecting
|
||||
to find the frontend project in the root directory. To fix this, you can do the following:
|
||||
|
||||
Create a file named `vetur.config.js` in the project's root.
|
||||
|
||||
```javascript
|
||||
// vetur.config.js
|
||||
/** @type {import('vls').VeturConfig} */
|
||||
module.exports = {
|
||||
// **optional** default: `{}`
|
||||
// override vscode settings
|
||||
// Notice: It only affects the settings used by Vetur.
|
||||
settings: {
|
||||
"vetur.useWorkspaceDependencies": true,
|
||||
"vetur.experimental.templateInterpolationService": true
|
||||
},
|
||||
// **optional** default: `[{ root: './' }]`
|
||||
// support monorepos
|
||||
projects: [
|
||||
{
|
||||
// **required**
|
||||
// Where is your project?
|
||||
// It is relative to `vetur.config.js`.
|
||||
// root: './packages/repo1',
|
||||
root: './frontend',
|
||||
// **optional** default: `'package.json'`
|
||||
// Where is `package.json` in the project?
|
||||
// We use it to determine the version of vue.
|
||||
// It is relative to root property.
|
||||
package: './package.json',
|
||||
// **optional**
|
||||
// Where is TypeScript config file in the project?
|
||||
// It is relative to root property.
|
||||
tsconfig: './tsconfig.json',
|
||||
// **optional** default: `'./.vscode/vetur/snippets'`
|
||||
// Where is vetur custom snippets folders?
|
||||
snippetFolder: './.vscode/vetur/snippets',
|
||||
// **optional** default: `[]`
|
||||
// Register globally Vue component glob.
|
||||
// If you set it, you can get completion by that components.
|
||||
// It is relative to root property.
|
||||
// Notice: It won't actually do it. You need to use `require.context` or `Vue.component`
|
||||
globalComponents: [
|
||||
'./src/components/**/*.vue'
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Next, configure `frontend/tsconfig.json`:
|
||||
|
||||
```javascript
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "system",
|
||||
"noImplicitAny": true,
|
||||
"removeComments": true,
|
||||
"preserveConstEnums": true,
|
||||
"sourceMap": true,
|
||||
"outFile": "../../built/local/tsc.js",
|
||||
"allowJs": true
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"**/*.spec.ts"
|
||||
],
|
||||
"include": [
|
||||
"src/**/*",
|
||||
"wailsjs/**/*.ts"
|
||||
]
|
||||
}
|
||||
```
|
||||
This should enable you to now use Vetur as expected.
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
# NSIS installer
|
||||
|
||||
```mdx-code-block
|
||||
<p style={{ "text-align": "center" }}>
|
||||
<img
|
||||
src={require("@site/static/img/nsis.webp").default}
|
||||
style={{ "max-width": "50%" }}
|
||||
/>
|
||||
<br />
|
||||
</p>
|
||||
```
|
||||
|
||||
Wails supports generating Windows installers using the [NSIS installer](https://nsis.sourceforge.io/).
|
||||
|
||||
## Installing NSIS
|
||||
|
||||
### Windows
|
||||
|
||||
The installer is available on the [NSIS Download](https://nsis.sourceforge.io/Download) page.
|
||||
|
||||
If you use the chocolatey package manager, run the following script:
|
||||
|
||||
```
|
||||
choco install nsis
|
||||
```
|
||||
|
||||
If you install NSIS manually, you need to add the _Bin_ folder, which contains `makensis.exe`, in your NSIS installation to your path.
|
||||
[Here](https://www.architectryan.com/2018/03/17/add-to-the-path-on-windows-10/) is a good tutorial on how to add to path on Windows.
|
||||
|
||||
### Linux
|
||||
|
||||
The `nsis` package should be available through your distribution's package manager.
|
||||
|
||||
### MacOS
|
||||
|
||||
NSIS is available to install through homebrew: `brew install nsis`.
|
||||
|
||||
## Generating the installer
|
||||
|
||||
When a new project is created, Wails generates the NSIS configuration files in `build/windows/installer`. The config
|
||||
data is read from `installer/info.json` and that is configured to use the project's `wails.json` Info section:
|
||||
|
||||
```json
|
||||
// ...
|
||||
"Info": {
|
||||
"companyName": "My Company Name",
|
||||
"productName": "Wails Vite",
|
||||
"productVersion": "1.0.0",
|
||||
"copyright": "Copyright.........",
|
||||
"comments": "Built using Wails (https://wails.io)"
|
||||
},
|
||||
```
|
||||
|
||||
To generate an installer for your application, use the `-nsis` flag with `wails build`:
|
||||
|
||||
```
|
||||
wails build -nsis
|
||||
```
|
||||
|
||||
The installer will now be available in the `build/bin` directory.
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
# Windows
|
||||
|
||||
This page has miscellaneous guides related to developing Wails applications for Windows.
|
||||
|
||||
## Handling the WebView2 Runtime Dependency
|
||||
|
||||
Wails applications built for Windows have a runtime requirement on the Microsoft [WebView2 Runtime](https://developer.microsoft.com/en-us/microsoft-edge/webview2/).
|
||||
Windows 11 will have this installed by default, but some machines won't. Wails offers an easy approach to dealing with this dependency.
|
||||
|
||||
By using the `-webview2` flag when building, you can decide what your application will do when a suitable runtime is not detected (including if the installed runtime is too old).
|
||||
The four options are:
|
||||
|
||||
1. Download
|
||||
2. Embed
|
||||
3. Browser
|
||||
4. Error
|
||||
|
||||
### Download
|
||||
|
||||
This option will prompt the user that no suitable runtime has been found and then offer to download and run the official
|
||||
bootstrapper from Microsoft's WebView2 site. If the user proceeds, the official bootstrapper will be downloaded and run.
|
||||
|
||||
### Embed
|
||||
|
||||
This option embeds the official bootstrapper within the application. If no suitable runtime has been found, the
|
||||
application will offer to run the bootstrapper. This adds ~150k to the binary size.
|
||||
|
||||
### Browser
|
||||
|
||||
This option will prompt the user that no suitable runtime has been found and then offer to open a browser to the official
|
||||
WebView2 page where the bootstrapper can be downloaded and installed. The application will then exit, leaving the installation
|
||||
up to the user.
|
||||
|
||||
### Error
|
||||
|
||||
If no suitable runtime is found, an error is given to the user and no further action taken.
|
||||
|
||||
## Fixed version runtime
|
||||
|
||||
Another way of dealing with webview2 dependency is shipping it yourself.
|
||||
You can download [fixed version runtime](https://developer.microsoft.com/microsoft-edge/webview2/#download-section) and bundle or download it with your application.
|
||||
|
||||
Also, you should specify path to fixed version of webview2 runtime in the `windows.Options` structure when launching wails.
|
||||
|
||||
```go
|
||||
wails.Run(&options.App{
|
||||
Windows: &windows.Options{
|
||||
WebviewBrowserPath: "",
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Note: When `WebviewBrowserPath` is specified, `error` strategy will be forced in case of minimal required version
|
||||
mismatch or invalid path to a runtime.
|
||||
|
||||
## Spawning other programs
|
||||
|
||||
When spawning other programs, such as scripts, you will see the window appear on the screen. To hide the window,
|
||||
you can use the following code:
|
||||
|
||||
```go
|
||||
cmd := exec.Command("your_script.exe")
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
HideWindow: true,
|
||||
CreationFlags: 0x08000000,
|
||||
}
|
||||
cmd.Start()
|
||||
```
|
||||
|
||||
Solution provided by [sithembiso](https://github.com/sithembiso) on the
|
||||
[discussions board](https://github.com/wailsapp/wails/discussions/1734#discussioncomment-3386172).
|
||||
|
|
@ -1,469 +0,0 @@
|
|||
---
|
||||
sidebar_position: 20
|
||||
---
|
||||
|
||||
# How does it work?
|
||||
|
||||
A Wails application is a standard Go application, with a webkit frontend. The Go part of the application consists of the
|
||||
application code and a runtime library that provides a number of useful operations, like controlling the application
|
||||
window. The frontend is a webkit window that will display the frontend assets. Also available to the frontend is a JavaScript
|
||||
version of the runtime library. Finally, it is possible to bind Go methods to the frontend, and these will appear as
|
||||
JavaScript methods that can be called, just as if they were local JavaScript methods.
|
||||
|
||||
```mdx-code-block
|
||||
<div className="text--center">
|
||||
<img src={require("@site/static/img/architecture.webp").default} style={{"width":"75%", "max-width":"800px"}} />
|
||||
</div>
|
||||
```
|
||||
|
||||
## The Main Application
|
||||
|
||||
### Overview
|
||||
|
||||
The main application consists of a single call to `wails.Run()`. It accepts the
|
||||
application configuration which describes the size of the application window, the window title,
|
||||
what assets to use, etc. A basic application might look like this:
|
||||
|
||||
```go title="main.go"
|
||||
package main
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"log"
|
||||
|
||||
"github.com/wailsapp/wails/v2"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
||||
)
|
||||
|
||||
//go:embed all:frontend/dist
|
||||
var assets embed.FS
|
||||
|
||||
func main() {
|
||||
|
||||
app := &App{}
|
||||
|
||||
err := wails.Run(&options.App{
|
||||
Title: "Basic Demo",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
},
|
||||
OnStartup: app.startup,
|
||||
OnShutdown: app.shutdown,
|
||||
Bind: []interface{}{
|
||||
app,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
type App struct {
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func (b *App) startup(ctx context.Context) {
|
||||
b.ctx = ctx
|
||||
}
|
||||
|
||||
func (b *App) shutdown(ctx context.Context) {}
|
||||
|
||||
func (b *App) Greet(name string) string {
|
||||
return fmt.Sprintf("Hello %s!", name)
|
||||
}
|
||||
```
|
||||
|
||||
### Options rundown
|
||||
|
||||
This example has the following options set:
|
||||
|
||||
- `Title` - The text that should appear in the window's title bar
|
||||
- `Width` & `Height` - The dimensions of the window
|
||||
- `Assets` - The application's frontend assets
|
||||
- `OnStartup` - A callback for when the window is created and is about to start loading the frontend assets
|
||||
- `OnShutdown` - A callback for when the application is about to quit
|
||||
- `Bind` - A slice of struct instances that we wish to expose to the frontend
|
||||
|
||||
A full list of application options can be found in the [Options Reference](reference/options).
|
||||
|
||||
#### Assets
|
||||
|
||||
The `Assets` option is mandatory as you can't have a Wails application without frontend assets. Those assets can be
|
||||
any files you would expect to find in a web application - html, js, css, svg, png, etc. **There is no requirement to
|
||||
generate asset bundles** - plain files will do. When the application starts, it will attempt to load `index.html`
|
||||
from your assets and the frontend will essentially work as a browser from that point on. It is worth noting that
|
||||
there is no requirement on where in the `embed.FS` the files live. It is likely that the embed path uses a nested
|
||||
directory relative to your main application code, such as `frontend/dist`:
|
||||
|
||||
```go title="main.go"
|
||||
//go:embed all:frontend/dist
|
||||
var assets embed.FS
|
||||
```
|
||||
|
||||
At startup, Wails will iterate the embedded files looking for the directory containing `index.html`. All other assets will be loaded relative
|
||||
to this directory.
|
||||
|
||||
As production binaries use the files contained in `embed.FS`, there are no external files required to be shipped with
|
||||
the application.
|
||||
|
||||
When running in development mode using the `wails dev` command, the assets are loaded off disk, and any changes result
|
||||
in a "live reload". The location of the assets will be inferred from the `embed.FS`.
|
||||
|
||||
More details can be found in the [Application Development Guide](guides/application-development.mdx).
|
||||
|
||||
#### Application Lifecycle Callbacks
|
||||
|
||||
Just before the frontend is about to load `index.html`, a callback is made to the function provided in [OnStartup](reference/options.mdx#onstartup).
|
||||
A standard Go context is passed to this method. This context is required when calling the runtime so a standard pattern is to save
|
||||
a reference to in this method. Just before the application shuts down, the [OnShutdown](reference/options.mdx#onshutdown) callback is called in the same way,
|
||||
again with the context. There is also an [OnDomReady](reference/options.mdx#ondomready) callback for when the frontend
|
||||
has completed loading all assets in `index.html` and is equivalent of the [`body onload`](https://www.w3schools.com/jsref/event_onload.asp) event in JavaScript.
|
||||
It is also possible to hook into the window close (or application quit) event by setting the
|
||||
option [OnBeforeClose](reference/options.mdx#onbeforeclose).
|
||||
|
||||
#### Method Binding
|
||||
|
||||
The `Bind` option is one of the most important options in a Wails application. It specifies which struct methods
|
||||
to expose to the frontend. Think of structs like "controllers" in a traditional web application. When the application
|
||||
starts, it examines the struct instances listed in the `Bind` field in the options, determines which methods are
|
||||
public (starts with an uppercase letter) and will generate JavaScript versions of those methods that can be called
|
||||
by the frontend code.
|
||||
|
||||
:::info Note
|
||||
|
||||
Wails requires that you pass in an _instance_ of the struct for it to bind it correctly
|
||||
|
||||
:::
|
||||
|
||||
In this example, we create a new `App` instance and then add this instance to the `Bind` option in `wails.Run`:
|
||||
|
||||
```go {17,27} title="main.go"
|
||||
package main
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"log"
|
||||
|
||||
"github.com/wailsapp/wails/v2"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
||||
)
|
||||
|
||||
//go:embed all:frontend/dist
|
||||
var assets embed.FS
|
||||
|
||||
func main() {
|
||||
|
||||
app := &App{}
|
||||
|
||||
err := wails.Run(&options.App{
|
||||
Title: "Basic Demo",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
},
|
||||
Bind: []interface{}{
|
||||
app,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
type App struct {
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func (a *App) Greet(name string) string {
|
||||
return fmt.Sprintf("Hello %s!", name)
|
||||
}
|
||||
```
|
||||
|
||||
You may bind as many structs as you like. Just make sure you create an instance of it and pass it in `Bind`:
|
||||
|
||||
```go {10-12}
|
||||
//...
|
||||
err := wails.Run(&options.App{
|
||||
Title: "Basic Demo",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
},
|
||||
Bind: []interface{}{
|
||||
app,
|
||||
&mystruct1{},
|
||||
&mystruct2{},
|
||||
},
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
You may bind enums types as well.
|
||||
In that case you should create array that will contain all possible enum values, instrument enum type and bind it to the app via `EnumBind`:
|
||||
|
||||
```go {16-18} title="app.go"
|
||||
type Weekday string
|
||||
|
||||
const (
|
||||
Sunday Weekday = "Sunday"
|
||||
Monday Weekday = "Monday"
|
||||
Tuesday Weekday = "Tuesday"
|
||||
Wednesday Weekday = "Wednesday"
|
||||
Thursday Weekday = "Thursday"
|
||||
Friday Weekday = "Friday"
|
||||
Saturday Weekday = "Saturday"
|
||||
)
|
||||
|
||||
var AllWeekdays = []struct {
|
||||
Value Weekday
|
||||
TSName string
|
||||
}{
|
||||
{Sunday, "SUNDAY"},
|
||||
{Monday, "MONDAY"},
|
||||
{Tuesday, "TUESDAY"},
|
||||
{Wednesday, "WEDNESDAY"},
|
||||
{Thursday, "THURSDAY"},
|
||||
{Friday, "FRIDAY"},
|
||||
{Saturday, "SATURDAY"},
|
||||
}
|
||||
```
|
||||
|
||||
```go {10-12}
|
||||
//...
|
||||
err := wails.Run(&options.App{
|
||||
Title: "Basic Demo",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
},
|
||||
Bind: []interface{}{
|
||||
app,
|
||||
&mystruct1{},
|
||||
&mystruct2{},
|
||||
},
|
||||
EnumBind: []interface{}{
|
||||
AllWeekdays,
|
||||
},
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
When you run `wails dev` (or `wails generate module`), a frontend module will be generated containing the following:
|
||||
|
||||
- JavaScript bindings for all bound methods
|
||||
- TypeScript declarations for all bound methods
|
||||
- TypeScript definitions for all Go structs used as inputs or outputs by the bound methods
|
||||
|
||||
This makes it incredibly simple to call Go code from the frontend, using the same strongly typed datastructures.
|
||||
|
||||
## The Frontend
|
||||
|
||||
### Overview
|
||||
|
||||
The frontend is a collection of files rendered by webkit. It's like a browser and webserver in one.
|
||||
There is virtually[^1] no limit to which frameworks or libraries you can use. The main points of interaction between
|
||||
the frontend and your Go code are:
|
||||
|
||||
- Calling bound Go methods
|
||||
- Calling runtime methods
|
||||
|
||||
[^1]:
|
||||
There is a very small subset of libraries that use features unsupported in WebViews. There are often alternatives and
|
||||
workarounds for such cases.
|
||||
|
||||
### Calling bound Go methods
|
||||
|
||||
When you run your application with `wails dev`, it will automatically generate JavaScript bindings for your structs in a
|
||||
directory called `wailsjs/go` (You can also do this by running `wails generate module`). The generated files mirror the
|
||||
package names in your application. In the example above, we bind `app`, which has one public method `Greet`. This will
|
||||
lead to the generation of the following files:
|
||||
|
||||
```bash
|
||||
wailsjs
|
||||
└─go
|
||||
└─main
|
||||
├─App.d.ts
|
||||
└─App.js
|
||||
```
|
||||
|
||||
Here we can see that there is a `main` package that contains the JavaScript bindings for the bound `App` struct, as well
|
||||
as the TypeScript declaration file for those methods. To call `Greet` from our frontend, we simply import the method and
|
||||
call it like a regular JavaScript function:
|
||||
|
||||
```javascript
|
||||
// ...
|
||||
import { Greet } from "../wailsjs/go/main/App";
|
||||
|
||||
function doGreeting(name) {
|
||||
Greet(name).then((result) => {
|
||||
// Do something with result
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
The TypeScript declaration file gives you the correct types for the bound methods:
|
||||
|
||||
```ts
|
||||
export function Greet(arg1: string): Promise<string>;
|
||||
```
|
||||
|
||||
The generated methods return a Promise. A successful call will result in the first return value from the Go call to be passed
|
||||
to the `resolve` handler. An unsuccessful call is when a Go method that has an error type as it's second return value,
|
||||
passes an error instance back to the caller. This is passed back via the `reject` handler.
|
||||
In the example above, `Greet` only returns a `string` so the JavaScript call will never reject - unless invalid data
|
||||
is passed to it.
|
||||
|
||||
All data types are correctly translated between Go and JavaScript. Even structs. If you return a struct from a Go call,
|
||||
it will be returned to your frontend as a JavaScript class.
|
||||
|
||||
:::info Note
|
||||
|
||||
Struct fields _must_ have a valid `json` tag to be included in the generated TypeScript.
|
||||
|
||||
Anonymous nested structs are not supported at this time.
|
||||
|
||||
:::
|
||||
|
||||
It is possible to send structs back to Go. Any JavaScript map/class passed as an argument that
|
||||
is expecting a struct, will be converted to that struct type. To make this process a lot easier, in `dev` mode,
|
||||
a TypeScript module is generated, defining all the struct types used in bound methods. Using this module, it's possible
|
||||
to construct and send native JavaScript objects to the Go code.
|
||||
|
||||
There is also support for Go methods that use structs in their signature. All Go structs
|
||||
specified by a bound method (either as parameters or return types) will have TypeScript versions auto
|
||||
generated as part of the Go code wrapper module. Using these, it's possible to share the same data
|
||||
model between Go and JavaScript.
|
||||
|
||||
Example: We update our `Greet` method to accept a `Person` instead of a string:
|
||||
|
||||
```go title="main.go"
|
||||
type Person struct {
|
||||
Name string `json:"name"`
|
||||
Age uint8 `json:"age"`
|
||||
Address *Address `json:"address"`
|
||||
}
|
||||
|
||||
type Address struct {
|
||||
Street string `json:"street"`
|
||||
Postcode string `json:"postcode"`
|
||||
}
|
||||
|
||||
func (a *App) Greet(p Person) string {
|
||||
return fmt.Sprintf("Hello %s (Age: %d)!", p.Name, p.Age)
|
||||
}
|
||||
```
|
||||
|
||||
The `wailsjs/go/main/App.js` file will still have the following code:
|
||||
|
||||
```js title="App.js"
|
||||
export function Greet(arg1) {
|
||||
return window["go"]["main"]["App"]["Greet"](arg1);
|
||||
}
|
||||
```
|
||||
|
||||
But the `wailsjs/go/main/App.d.ts` file will be updated with the following code:
|
||||
|
||||
```ts title="App.d.ts"
|
||||
import { main } from "../models";
|
||||
|
||||
export function Greet(arg1: main.Person): Promise<string>;
|
||||
```
|
||||
|
||||
As we can see, the "main" namespace is imported from a new "models.ts" file. This file contains all the struct definitions
|
||||
used by our bound methods. In this example, this is a `Person` struct. If we look at `models.ts`, we can see how the models
|
||||
are defined:
|
||||
|
||||
```ts title="models.ts"
|
||||
export namespace main {
|
||||
export class Address {
|
||||
street: string;
|
||||
postcode: string;
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new Address(source);
|
||||
}
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ("string" === typeof source) source = JSON.parse(source);
|
||||
this.street = source["street"];
|
||||
this.postcode = source["postcode"];
|
||||
}
|
||||
}
|
||||
export class Person {
|
||||
name: string;
|
||||
age: number;
|
||||
address?: Address;
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new Person(source);
|
||||
}
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ("string" === typeof source) source = JSON.parse(source);
|
||||
this.name = source["name"];
|
||||
this.age = source["age"];
|
||||
this.address = this.convertValues(source["address"], Address);
|
||||
}
|
||||
|
||||
convertValues(a: any, classs: any, asMap: boolean = false): any {
|
||||
if (!a) {
|
||||
return a;
|
||||
}
|
||||
if (a.slice) {
|
||||
return (a as any[]).map((elem) => this.convertValues(elem, classs));
|
||||
} else if ("object" === typeof a) {
|
||||
if (asMap) {
|
||||
for (const key of Object.keys(a)) {
|
||||
a[key] = new classs(a[key]);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
return new classs(a);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
So long as you have TypeScript as part of your frontend build configuration, you can use these models in
|
||||
the following way:
|
||||
|
||||
```js title="mycode.js"
|
||||
import { Greet } from "../wailsjs/go/main/App";
|
||||
import { main } from "../wailsjs/go/models";
|
||||
|
||||
function generate() {
|
||||
let person = new main.Person();
|
||||
person.name = "Peter";
|
||||
person.age = 27;
|
||||
Greet(person).then((result) => {
|
||||
console.log(result);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
The combination of generated bindings and TypeScript models makes for a powerful development environment.
|
||||
|
||||
More information on Binding can be found in the [Binding Methods](guides/application-development.mdx#binding-methods)
|
||||
section of the [Application Development Guide](guides/application-development.mdx).
|
||||
|
||||
### Calling runtime methods
|
||||
|
||||
The JavaScript runtime is located at `window.runtime` and contains many methods to do various
|
||||
tasks such as emit an event or perform logging operations:
|
||||
|
||||
```js title="mycode.js"
|
||||
window.runtime.EventsEmit("my-event", 1);
|
||||
```
|
||||
|
||||
More details about the JS runtime can be found in the [Runtime Reference](reference/runtime/intro).
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Introduction
|
||||
|
||||
Wails is a project that enables you to write desktop apps using Go and web technologies.
|
||||
|
||||
Consider it a lightweight and fast Electron alternative for Go. You can easily build applications with the flexibility
|
||||
and power of Go, combined with a rich, modern frontend.
|
||||
|
||||
### Features
|
||||
|
||||
- Native Menus, Dialogs, Theming and Translucency
|
||||
- Windows, macOS and linux support
|
||||
- Built in templates for Svelte, React, Preact, Vue, Lit and Vanilla JS
|
||||
- Easily call Go methods from JavaScript
|
||||
- Automatic Go struct to TypeScript model generation
|
||||
- No CGO or external DLLs required on Windows
|
||||
- Live development mode using the power of [Vite](https://vitejs.dev/)
|
||||
- Powerful CLI to easily Create, Build and Package applications
|
||||
- A rich [runtime library](/docs/reference/runtime/intro)
|
||||
- Applications built with Wails are Apple & Microsoft Store compliant
|
||||
|
||||
This is varly - a desktop application for
|
||||
MacOS & Windows written using Wails. Not only does it look great, it uses native menus and translucency - everything
|
||||
you'd expect from a modern native app.
|
||||
|
||||
```mdx-code-block
|
||||
<p class="text--center">
|
||||
<img
|
||||
src={require("@site/static/img/showcase/varly2.webp").default}
|
||||
style={{ width: "75%", "max-width": "800px" }}
|
||||
/>
|
||||
</p>
|
||||
```
|
||||
|
||||
### Quick Start Templates
|
||||
|
||||
Wails comes with a number of pre-configured templates that allow you to get your application up and running quickly.
|
||||
There are templates for the following frameworks: Svelte, React, Vue, Preact, Lit and Vanilla. There are both JavaScript
|
||||
and TypeScript versions for each template.
|
||||
|
||||
### Native Elements
|
||||
|
||||
Wails uses a purpose built library for handling native elements such as Window, Menus, Dialogs, etc, so you can build
|
||||
good-looking, feature rich desktop applications.
|
||||
|
||||
**It does not embed a browser**, so it delivers a small runtime. Instead, it reuses the native rendering engine for the
|
||||
platform. On Windows, this is the new Microsoft Webview2 library, built on Chromium.
|
||||
|
||||
### Go & JavaScript Interoperability
|
||||
|
||||
Wails automatically makes your Go methods available to JavaScript, so you can call them by name from your frontend!
|
||||
It even generates TypeScript models for the structs used by your Go methods, so you can pass the same data structures
|
||||
between Go and JavaScript.
|
||||
|
||||
### Runtime Library
|
||||
|
||||
Wails provides a runtime library, for both Go and JavaScript, that handles a lot of the things modern applications need,
|
||||
like Eventing, Logging, Dialogs, etc.
|
||||
|
||||
### Live Development Experience
|
||||
|
||||
#### Automatic Rebuilds
|
||||
|
||||
When you run your application in "dev" mode, Wails will build your application as a native desktop application, but will
|
||||
read your assets from disk. It will detect any changes to your Go code and automatically rebuild and relaunch your
|
||||
application.
|
||||
|
||||
#### Automatic Reloads
|
||||
|
||||
When changes to your application assets are detected, your running application will "reload", reflecting your changes
|
||||
almost immediately.
|
||||
|
||||
#### Develop your application in a Browser
|
||||
|
||||
If you prefer to debug and develop in a browser then Wails has you covered. The running application also has a webserver
|
||||
that will run your application in any browser that connects to it. It will even refresh when your assets change on disk.
|
||||
|
||||
### Production-ready Native Binaries
|
||||
|
||||
When you're ready to do the final build of your application, the CLI will compile it down to a single executable, with
|
||||
all the assets bundled into it. On Windows and MacOS, it is possible to create a native package for distribution. The
|
||||
assets used in packaging (icon, info.plist, manifest file, etc) are part of your project and may be customised, giving
|
||||
you total control over how your applications are built.
|
||||
|
||||
### Tooling
|
||||
|
||||
The Wails CLI provides a hassle-free way to generate, build and bundle your applications. It will do the heavy lifting
|
||||
of creating icons, compiling your application with optimal settings and delivering a distributable, production ready
|
||||
binary. Choose from a number of starter templates to get up and running quickly!
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"label": "Reference",
|
||||
"position": 40
|
||||
}
|
||||
|
|
@ -1,245 +0,0 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# CLI
|
||||
|
||||
The Wails CLI has a number of commands that are used for managing your projects. All commands are run in the following way:
|
||||
|
||||
`wails <command> <flags>`
|
||||
|
||||
## init
|
||||
|
||||
`wails init` is used for generating projects.
|
||||
|
||||
| Flag | Description | Default |
|
||||
| :----------------- | :---------------------------------------------------------------------------------------------------------------------- | :-----------------: |
|
||||
| -n "project name" | Name of the project. **Mandatory**. | |
|
||||
| -d "project dir" | Project directory to create | Name of the project |
|
||||
| -g | Initialise git repository | |
|
||||
| -l | List available project templates | |
|
||||
| -q | Suppress output to console | |
|
||||
| -t "template name" | The project template to use. This can be the name of a default template or a URL to a remote template hosted on github. | vanilla |
|
||||
| -ide | Generate IDE project files | |
|
||||
| -f | Force build application | false |
|
||||
|
||||
Example:
|
||||
`wails init -n test -d mytestproject -g -ide vscode -q`
|
||||
|
||||
This will generate a a project called "test" in the "mytestproject" directory, initialise git,
|
||||
generate vscode project files and do so silently.
|
||||
|
||||
More information on using IDEs with Wails can be found [here](../guides/ides.mdx).
|
||||
|
||||
### Remote Templates
|
||||
|
||||
Remote templates (hosted on GitHub) are supported and can be installed by using the template's project URL.
|
||||
|
||||
Example:
|
||||
`wails init -n test -t https://github.com/leaanthony/testtemplate[@v1.0.0]`
|
||||
|
||||
A list of community maintained templates can be found [here](../community/templates.mdx)
|
||||
|
||||
:::warning Attention
|
||||
|
||||
**The Wails project does not maintain, is not responsible nor liable for 3rd party templates!**
|
||||
|
||||
If you are unsure about a template, inspect `package.json` and `wails.json` for what scripts are run and what packages are installed.
|
||||
|
||||
:::
|
||||
|
||||
## build
|
||||
|
||||
`wails build` is used for compiling your project to a production-ready binary.
|
||||
|
||||
| Flag | Description | Default |
|
||||
|:---------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| -clean | Cleans the `build/bin` directory | |
|
||||
| -compiler "compiler" | Use a different go compiler to build, eg go1.15beta1 | go |
|
||||
| -debug | Retains debug information in the application and shows the debug console. Allows the use of the devtools in the application window | |
|
||||
| -devtools | Allows the use of the devtools in the application window in production (when -debug is not used). Ctrl/Cmd+Shift+F12 may be used to open the devtools window. *NOTE*: This option will make your application FAIL Mac appstore guidelines. Use for debugging only. | |
|
||||
| -dryrun | Prints the build command without executing it | |
|
||||
| -f | Force build application | |
|
||||
| -garbleargs | Arguments to pass to garble | `-literals -tiny -seed=random` |
|
||||
| -ldflags "flags" | Additional ldflags to pass to the compiler | |
|
||||
| -m | Skip mod tidy before compile | |
|
||||
| -nopackage | Do not package application | |
|
||||
| -nocolour | Disable colour in output | |
|
||||
| -nosyncgomod | Do not sync go.mod with the Wails version | |
|
||||
| -nsis | Generate NSIS installer for Windows | |
|
||||
| -o filename | Output filename | |
|
||||
| -obfuscated | Obfuscate the application using [garble](https://github.com/burrowers/garble) | |
|
||||
| -platform | Build for the given (comma delimited) [platforms](../reference/cli.mdx#platforms) eg. `windows/arm64`. Note, if you do not give the architecture, `runtime.GOARCH` is used. | platform = `GOOS` environment variable if given else `runtime.GOOS`.<br/>arch = `GOARCH` envrionment variable if given else `runtime.GOARCH`. |
|
||||
| -race | Build with Go's race detector | |
|
||||
| -s | Skip building the frontend | |
|
||||
| -skipbindings | Skip bindings generation | |
|
||||
| -tags "extra tags" | Build tags to pass to Go compiler. Must be quoted. Space or comma (but not both) separated | |
|
||||
| -trimpath | Remove all file system paths from the resulting executable. | |
|
||||
| -u | Updates your project's `go.mod` to use the same version of Wails as the CLI | |
|
||||
| -upx | Compress final binary using "upx" | |
|
||||
| -upxflags | Flags to pass to upx | |
|
||||
| -v int | Verbosity level (0 - silent, 1 - default, 2 - verbose) | 1 |
|
||||
| -webview2 | WebView2 installer strategy: download,embed,browser,error | download |
|
||||
| -windowsconsole | Keep the console window for Windows builds | |
|
||||
|
||||
For a detailed description of the `webview2` flag, please refer to the [Windows](../guides/windows.mdx) Guide.
|
||||
|
||||
If you prefer to build using standard Go tooling, please consult the [Manual Builds](../guides/manual-builds.mdx)
|
||||
guide.
|
||||
|
||||
Example:
|
||||
|
||||
`wails build -clean -o myproject.exe`
|
||||
|
||||
:::info
|
||||
|
||||
On Mac, the application will be bundled with `Info.plist`, not `Info.dev.plist`.
|
||||
|
||||
:::
|
||||
|
||||
:::info UPX on Apple Silicon
|
||||
|
||||
There are [issues](https://github.com/upx/upx/issues/446) with using UPX with Apple Silicon.
|
||||
|
||||
:::
|
||||
|
||||
:::info UPX on Windows
|
||||
|
||||
Some Antivirus vendors false positively mark `upx` compressed binaries as virus, see [issue](https://github.com/upx/upx/issues/437).
|
||||
|
||||
:::
|
||||
|
||||
### Platforms
|
||||
|
||||
Supported platforms are:
|
||||
|
||||
| Platform | Description |
|
||||
| :--------------- | :-------------------------------------------- |
|
||||
| darwin | MacOS + architecture of build machine |
|
||||
| darwin/amd64 | MacOS 10.13+ AMD64 |
|
||||
| darwin/arm64 | MacOS 11.0+ ARM64 |
|
||||
| darwin/universal | MacOS AMD64+ARM64 universal application |
|
||||
| windows | Windows 10/11 + architecture of build machine |
|
||||
| windows/amd64 | Windows 10/11 AMD64 |
|
||||
| windows/arm64 | Windows 10/11 ARM64 |
|
||||
| linux | Linux + architecture of build machine |
|
||||
| linux/amd64 | Linux AMD64 |
|
||||
| linux/arm64 | Linux ARM64 |
|
||||
|
||||
## doctor
|
||||
|
||||
`wails doctor` will run diagnostics to ensure that your system is ready for development.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
Wails CLI v2.0.0-beta
|
||||
|
||||
Scanning system - Please wait (this may take a long time)...Done.
|
||||
|
||||
System
|
||||
------
|
||||
OS: Windows 10 Pro
|
||||
Version: 2009 (Build: 19043)
|
||||
ID: 21H1
|
||||
Go Version: go1.18
|
||||
Platform: windows
|
||||
Architecture: amd64
|
||||
|
||||
Dependency Package Name Status Version
|
||||
---------- ------------ ------ -------
|
||||
WebView2 N/A Installed 93.0.961.52
|
||||
npm N/A Installed 6.14.15
|
||||
*upx N/A Installed upx 3.96
|
||||
|
||||
* - Optional Dependency
|
||||
|
||||
Diagnosis
|
||||
---------
|
||||
Your system is ready for Wails development!
|
||||
|
||||
```
|
||||
|
||||
## dev
|
||||
|
||||
`wails dev` is used to run your application in a "live development" mode. This means:
|
||||
|
||||
- The application's `go.mod` will be updated to use the same version of Wails as the CLI
|
||||
- The application is compiled and run automatically
|
||||
- A watcher is started and will trigger a rebuild of your dev app if it detects changes to your go files
|
||||
- A webserver is started on `http://localhost:34115` which serves your application (not just frontend) over http. This allows you to use your favourite browser development extensions
|
||||
- All application assets are loaded from disk. If they are changed, the application will automatically reload (not rebuild). All connected browsers will also reload
|
||||
- A JS module is generated that provides the following:
|
||||
- JavaScript wrappers of your Go methods with autogenerated JSDoc, providing code hinting
|
||||
- TypeScript versions of your Go structs, that can be constructed and passed to your go methods
|
||||
- A second JS module is generated that provides a wrapper + TS declaration for the runtime
|
||||
- On macOS, it will bundle the application into a `.app` file and run it. It will use a `build/darwin/Info.dev.plist` for development.
|
||||
|
||||
| Flag | Description | Default |
|
||||
|:-----------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------------|
|
||||
| -appargs "args" | Arguments passed to the application in shell style | |
|
||||
| -assetdir "./path/to/assets" | Serve assets from the given directory instead of using the provided asset FS | Value in `wails.json` |
|
||||
| -browser | Opens a browser to `http://localhost:34115` on startup | |
|
||||
| -compiler "compiler" | Use a different go compiler to build, eg go1.15beta1 | go |
|
||||
| -debounce | The time to wait for reload after an asset change is detected | 100 (milliseconds) |
|
||||
| -devserver "host:port" | The address to bind the wails dev server to | "localhost:34115" |
|
||||
| -extensions | Extensions to trigger rebuilds (comma separated) | go |
|
||||
| -forcebuild | Force build of application | |
|
||||
| -frontenddevserverurl "url" | Use 3rd party dev server url to serve assets, EG Vite | "" |
|
||||
| -ldflags "flags" | Additional ldflags to pass to the compiler | |
|
||||
| -loglevel "loglevel" | Loglevel to use - Trace, Debug, Info, Warning, Error | Debug |
|
||||
| -nocolour | Turn off colour cli output | false |
|
||||
| -noreload | Disable automatic reload when assets change | |
|
||||
| -nosyncgomod | Do not sync go.mod with the Wails version | false |
|
||||
| -race | Build with Go's race detector | false |
|
||||
| -reloaddirs | Additional directories to trigger reloads (comma separated) | Value in `wails.json` |
|
||||
| -s | Skip building the frontend | false |
|
||||
| -save | Saves the given `assetdir`, `reloaddirs`, `wailsjsdir`, `debounce`, `devserver` and `frontenddevserverurl` flags in `wails.json` to become the defaults for subsequent invocations. | |
|
||||
| -skipbindings | Skip bindings generation | |
|
||||
| -tags "extra tags" | Build tags to pass to compiler (quoted and space separated) | |
|
||||
| -v | Verbosity level (0 - silent, 1 - standard, 2 - verbose) | 1 |
|
||||
| -wailsjsdir | The directory to generate the generated Wails JS modules | Value in `wails.json` |
|
||||
|
||||
Example:
|
||||
|
||||
`wails dev -assetdir ./frontend/dist -wailsjsdir ./frontend/src -browser`
|
||||
|
||||
This command will do the following:
|
||||
|
||||
- Build the application and run it (more details [here](../guides/manual-builds.mdx)
|
||||
- Generate the Wails JS modules in `./frontend/src`
|
||||
- Watch for updates to files in `./frontend/dist` and reload on any change
|
||||
- Open a browser and connect to the application
|
||||
|
||||
There is more information on using this feature with existing framework scripts [here](../guides/application-development.mdx#live-reloading).
|
||||
|
||||
## generate
|
||||
|
||||
### template
|
||||
|
||||
Wails uses templates for project generation. The `wails generate template` command helps scaffold a template so that
|
||||
it may be used for generating projects.
|
||||
|
||||
| Flag | Description |
|
||||
|:-----------------|:--------------------------------------------|
|
||||
| -name | The template name (Mandatory) |
|
||||
| -frontend "path" | Path to frontend project to use in template |
|
||||
|
||||
For more details on creating templates, consult the [Templates guide](../guides/templates.mdx).
|
||||
|
||||
### module
|
||||
|
||||
The `wails generate module` command allows you to manually generate the `wailsjs` directory for your application.
|
||||
|
||||
## update
|
||||
|
||||
`wails update` will update the version of the Wails CLI.
|
||||
|
||||
| Flag | Description |
|
||||
|:-------------------|:--------------------------------------|
|
||||
| -pre | Update to latest pre-release version |
|
||||
| -version "version" | Install a specific version of the CLI |
|
||||
|
||||
## version
|
||||
|
||||
`wails version` will simply output the current CLI version.
|
||||
|
|
@ -1,240 +0,0 @@
|
|||
---
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
# Menus
|
||||
|
||||
It is possible to add an application menu to Wails projects. This is achieved by defining a [Menu](#menu) struct and
|
||||
setting it in the [`Menu`](../reference/options.mdx#menu) application config, or by calling the runtime method
|
||||
[MenuSetApplicationMenu](../reference/runtime/menu.mdx#menusetapplicationmenu).
|
||||
|
||||
An example of how to create a menu:
|
||||
|
||||
```go
|
||||
|
||||
app := NewApp()
|
||||
|
||||
AppMenu := menu.NewMenu()
|
||||
FileMenu := AppMenu.AddSubmenu("File")
|
||||
FileMenu.AddText("&Open", keys.CmdOrCtrl("o"), openFile)
|
||||
FileMenu.AddSeparator()
|
||||
FileMenu.AddText("Quit", keys.CmdOrCtrl("q"), func(_ *menu.CallbackData) {
|
||||
runtime.Quit(app.ctx)
|
||||
})
|
||||
|
||||
if runtime.GOOS == "darwin" {
|
||||
AppMenu.Append(menu.EditMenu()) // on macos platform, we should append EditMenu to enable Cmd+C,Cmd+V,Cmd+Z... shortcut
|
||||
}
|
||||
|
||||
err := wails.Run(&options.App{
|
||||
Title: "Menus Demo",
|
||||
Width: 800,
|
||||
Height: 600,
|
||||
Menu: AppMenu, // reference the menu above
|
||||
Bind: []interface{}{
|
||||
app,
|
||||
},
|
||||
)
|
||||
// ...
|
||||
```
|
||||
|
||||
It is also possible to dynamically update the menu, by updating the menu struct and calling
|
||||
[MenuUpdateApplicationMenu](../reference/runtime/menu.mdx#menuupdateapplicationmenu).
|
||||
|
||||
The example above uses helper methods, however it's possible to build the menu structs manually.
|
||||
|
||||
## Menu
|
||||
|
||||
A Menu is a collection of MenuItems:
|
||||
|
||||
```go title="Package: github.com/wailsapp/wails/v2/pkg/menu"
|
||||
type Menu struct {
|
||||
Items []*MenuItem
|
||||
}
|
||||
```
|
||||
|
||||
For the Application menu, each MenuItem represents a single menu such as "Edit".
|
||||
|
||||
A simple helper method is provided for building menus:
|
||||
|
||||
```go title="Package: github.com/wailsapp/wails/v2/pkg/menu"
|
||||
func NewMenuFromItems(first *MenuItem, rest ...*MenuItem) *Menu
|
||||
```
|
||||
|
||||
This makes the layout of the code more like that of a menu without the need to add the menu items manually after creating them.
|
||||
Alternatively, you can just create the menu items and add them to the menu manually.
|
||||
|
||||
## MenuItem
|
||||
|
||||
A MenuItem represents an item within a Menu.
|
||||
|
||||
```go title="Package: github.com/wailsapp/wails/v2/pkg/menu"
|
||||
// MenuItem represents a menu item contained in a menu
|
||||
type MenuItem struct {
|
||||
Label string
|
||||
Role Role
|
||||
Accelerator *keys.Accelerator
|
||||
Type Type
|
||||
Disabled bool
|
||||
Hidden bool
|
||||
Checked bool
|
||||
SubMenu *Menu
|
||||
Click Callback
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Notes |
|
||||
| ----------- | ---------------------------------- | ------------------------------------------------------------- |
|
||||
| Label | string | The menu text |
|
||||
| Accelerator | [\*keys.Accelerator](#accelerator) | Key binding for this menu item |
|
||||
| Type | [Type](#type) | Type of MenuItem |
|
||||
| Disabled | bool | Disables the menu item |
|
||||
| Hidden | bool | Hides this menu item |
|
||||
| Checked | bool | Adds check to item (Checkbox & Radio types) |
|
||||
| SubMenu | [\*Menu](#menu) | Sets the submenu |
|
||||
| Click | [Callback](#callback) | Callback function when menu clicked |
|
||||
| Role | string | Defines a [role](#role) for this menu item. Mac only for now. |
|
||||
|
||||
### Accelerator
|
||||
|
||||
Accelerators (sometimes called keyboard shortcuts) define a binding between a keystroke and a menu item. Wails defines
|
||||
an Accelerator as a combination or key + [Modifier](#modifier). They are available in the `"github.com/wailsapp/wails/v2/pkg/menu/keys"` package.
|
||||
|
||||
Example:
|
||||
|
||||
```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys"
|
||||
// Defines cmd+o on Mac and ctrl-o on Window/Linux
|
||||
myShortcut := keys.CmdOrCtrl("o")
|
||||
```
|
||||
|
||||
Keys are any single character on a keyboard with the exception of `+`, which is defined as `plus`.
|
||||
Some keys cannot be represented as characters so there are a set of named characters that may be used:
|
||||
|
||||
| | | | |
|
||||
| :---------: | :---: | :---: | :-------: |
|
||||
| `backspace` | `f1` | `f16` | `f31` |
|
||||
| `tab` | `f2` | `f17` | `f32` |
|
||||
| `return` | `f3` | `f18` | `f33` |
|
||||
| `enter` | `f4` | `f19` | `f34` |
|
||||
| `escape` | `f5` | `f20` | `f35` |
|
||||
| `left` | `f6` | `f21` | `numlock` |
|
||||
| `right` | `f7` | `f22` | |
|
||||
| `up` | `f8` | `f23` | |
|
||||
| `down` | `f9` | `f24` | |
|
||||
| `space` | `f10` | `f25` | |
|
||||
| `delete` | `f11` | `f36` | |
|
||||
| `home` | `f12` | `f37` | |
|
||||
| `end` | `f13` | `f38` | |
|
||||
| `page up` | `f14` | `f39` | |
|
||||
| `page down` | `f15` | `f30` | |
|
||||
|
||||
Wails also supports parsing accelerators using the same syntax as Electron. This is useful for storing accelerators in
|
||||
config files.
|
||||
|
||||
Example:
|
||||
|
||||
```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys"
|
||||
// Defines cmd+o on Mac and ctrl-o on Window/Linux
|
||||
myShortcut, err := keys.Parse("Ctrl+Option+A")
|
||||
```
|
||||
|
||||
#### Modifier
|
||||
|
||||
The following modifiers are keys that may be used in combination with the accelerator key:
|
||||
|
||||
```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys"
|
||||
const (
|
||||
// CmdOrCtrlKey represents Command on Mac and Control on other platforms
|
||||
CmdOrCtrlKey Modifier = "cmdorctrl"
|
||||
// OptionOrAltKey represents Option on Mac and Alt on other platforms
|
||||
OptionOrAltKey Modifier = "optionoralt"
|
||||
// ShiftKey represents the shift key on all systems
|
||||
ShiftKey Modifier = "shift"
|
||||
// ControlKey represents the control key on all systems
|
||||
ControlKey Modifier = "ctrl"
|
||||
)
|
||||
```
|
||||
|
||||
A number of helper methods are available to create Accelerators using modifiers:
|
||||
|
||||
```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys"
|
||||
func CmdOrCtrl(key string) *Accelerator
|
||||
func OptionOrAlt(key string) *Accelerator
|
||||
func Shift(key string) *Accelerator
|
||||
func Control(key string) *Accelerator
|
||||
```
|
||||
|
||||
Modifiers can be combined using `keys.Combo(key string, modifier1 Modifier, modifier2 Modifier, rest ...Modifier)`:
|
||||
|
||||
```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys"
|
||||
// Defines "Ctrl+Option+A" on Mac and "Ctrl+Alt+A" on Window/Linux
|
||||
myShortcut := keys.Combo("a", ControlKey, OptionOrAltKey)
|
||||
```
|
||||
|
||||
### Type
|
||||
|
||||
Each menu item must have a type and there are 5 types available:
|
||||
|
||||
```go title="Package: github.com/wailsapp/wails/v2/pkg/menu"
|
||||
const (
|
||||
TextType Type = "Text"
|
||||
SeparatorType Type = "Separator"
|
||||
SubmenuType Type = "Submenu"
|
||||
CheckboxType Type = "Checkbox"
|
||||
RadioType Type = "Radio"
|
||||
)
|
||||
```
|
||||
|
||||
For convenience, helper methods are provided to quickly create a menu item:
|
||||
|
||||
```go title="Package: github.com/wailsapp/wails/v2/pkg/menu"
|
||||
func Text(label string, accelerator *keys.Accelerator, click Callback) *MenuItem
|
||||
func Separator() *MenuItem
|
||||
func Radio(label string, selected bool, accelerator *keys.Accelerator, click Callback) *MenuItem
|
||||
func Checkbox(label string, checked bool, accelerator *keys.Accelerator, click Callback) *MenuItem
|
||||
func SubMenu(label string, menu *Menu) *Menu
|
||||
```
|
||||
|
||||
You can also create menu items directly on a menu by using the "Add" helpers:
|
||||
|
||||
```go title="Package: github.com/wailsapp/wails/v2/pkg/menu"
|
||||
func (m *Menu) AddText(label string, accelerator *keys.Accelerator, click Callback) *MenuItem
|
||||
func (m *Menu) AddSeparator() *MenuItem
|
||||
func (m *Menu) AddRadio(label string, selected bool, accelerator *keys.Accelerator, click Callback) *MenuItem
|
||||
func (m *Menu) AddCheckbox(label string, checked bool, accelerator *keys.Accelerator, click Callback) *MenuItem
|
||||
func (m *Menu) AddSubMenu(label string, menu *Menu) *MenuI
|
||||
```
|
||||
|
||||
A note on radio groups: A radio group is defined as a number of radio menu items that are next to each other in the menu.
|
||||
This means that you do not need to group items together as it is automatic. However, that also means you cannot have 2
|
||||
radio groups next to each other - there must be a non-radio item between them.
|
||||
|
||||
### Callback
|
||||
|
||||
Each menu item may have a callback that is executed when the item is clicked:
|
||||
|
||||
```go title="Package: github.com/wailsapp/wails/v2/pkg/menu"
|
||||
type Callback func(*CallbackData)
|
||||
|
||||
type CallbackData struct {
|
||||
MenuItem *MenuItem
|
||||
}
|
||||
```
|
||||
|
||||
The function is given a `CallbackData` struct which indicates which menu item triggered the callback. This is useful when
|
||||
using radio groups that may share a callback.
|
||||
|
||||
### Role
|
||||
|
||||
:::info Roles
|
||||
|
||||
Roles are currently supported on Mac only.
|
||||
|
||||
:::
|
||||
|
||||
A menu item may have a role, which is essentially a pre-defined menu item. We currently support the following roles:
|
||||
|
||||
| Role | Description |
|
||||
| ------------ | ------------------------------------------------------------------------ |
|
||||
| AppMenuRole | The standard Mac application menu. Can be created using `menu.AppMenu()` |
|
||||
| EditMenuRole | The standard Mac edit menu. Can be created using `menu.EditMenu()` |
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,130 +0,0 @@
|
|||
---
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
# Project Config
|
||||
|
||||
The project config resides in the `wails.json` file in the project directory. The structure of the config is:
|
||||
|
||||
```json5
|
||||
{
|
||||
// Project config version
|
||||
"version": "",
|
||||
// The project name
|
||||
"name": "",
|
||||
// Relative path to the directory containing the compiled assets, this is normally inferred and could be left empty
|
||||
"assetdir": "",
|
||||
// Additional directories to trigger reloads (comma separated), this is only used for some advanced asset configurations
|
||||
"reloaddirs": "",
|
||||
// The directory where the build files reside. Defaults to 'build'
|
||||
"build:dir": "",
|
||||
// Relative path to the frontend directory. Defaults to 'frontend'
|
||||
"frontend:dir": "",
|
||||
// The command to install node dependencies, run in the frontend directory - often `npm install`
|
||||
"frontend:install": "",
|
||||
// The command to build the assets, run in the frontend directory - often `npm run build`
|
||||
"frontend:build": "",
|
||||
// This command has been replaced by frontend:dev:build. If frontend:dev:build is not specified will falls back to this command. \nIf this command is also not specified will falls back to frontend:build
|
||||
"frontend:dev": "",
|
||||
// This command is the dev equivalent of frontend:build. If not specified falls back to frontend:dev
|
||||
"frontend:dev:build": "",
|
||||
// This command is the dev equivalent of frontend:install. If not specified falls back to frontend:install
|
||||
"frontend:dev:install": "",
|
||||
// This command is run in a separate process on `wails dev`. Useful for 3rd party watchers or starting 3d party dev servers
|
||||
"frontend:dev:watcher": "",
|
||||
// URL to a 3rd party dev server to be used to serve assets, EG Vite. \nIf this is set to 'auto' then the devServerUrl will be inferred from the Vite output
|
||||
"frontend:dev:serverUrl": "",
|
||||
// Relative path to the directory that the auto-generated JS modules will be created
|
||||
"wailsjsdir": "",
|
||||
// The name of the binary
|
||||
"outputfilename": "",
|
||||
// The default time the dev server waits to reload when it detects a change in assets
|
||||
"debounceMS": 100,
|
||||
// Address to bind the wails dev sever to. Default: localhost:34115
|
||||
"devServer": "",
|
||||
// Arguments passed to the application in shell style when in dev mode
|
||||
"appargs": "",
|
||||
// Defines if build hooks should be run though they are defined for an OS other than the host OS.
|
||||
"runNonNativeBuildHooks": false,
|
||||
"preBuildHooks": {
|
||||
// The command that will be executed before a build of the specified GOOS/GOARCH: ${platform} is replaced with the "GOOS/GOARCH". The "GOOS/GOARCH" hook is executed before the "GOOS/*" and "*/*" hook.
|
||||
"GOOS/GOARCH": "",
|
||||
// The command that will be executed before a build of the specified GOOS: ${platform} is replaced with the "GOOS/GOARCH". The "GOOS/*" hook is executed before the "*/*" hook.
|
||||
"GOOS/*": "",
|
||||
// The command that will be executed before every build: ${platform} is replaced with the "GOOS/GOARCH".
|
||||
"*/*": ""
|
||||
},
|
||||
"postBuildHooks": {
|
||||
// The command that will be executed after a build of the specified GOOS/GOARCH: ${platform} is replaced with the "GOOS/GOARCH" and ${bin} with the path to the compiled binary. The "GOOS/GOARCH" hook is executed before the "GOOS/*" and "*/*" hook.
|
||||
"GOOS/GOARCH": "",
|
||||
// The command that will be executed after a build of the specified GOOS: ${platform} is replaced with the "GOOS/GOARCH" and ${bin} with the path to the compiled binary. The "GOOS/*" hook is executed before the "*/*" hook.
|
||||
"GOOS/*": "",
|
||||
// The command that will be executed after every build: ${platform} is replaced with the "GOOS/GOARCH" and ${bin} with the path to the compiled binary.
|
||||
"*/*": ""
|
||||
},
|
||||
// Data used to populate manifests and version info.
|
||||
"info": {
|
||||
// The company name. Default: [The project name]
|
||||
"companyName": "",
|
||||
// The product name. Default: [The project name]
|
||||
"productName": "",
|
||||
// The version of the product. Default: '1.0.0'
|
||||
"productVersion": "",
|
||||
// The copyright of the product. Default: 'Copyright.........'
|
||||
"copyright": "",
|
||||
// A short comment of the app. Default: 'Built using Wails (https://wails.app)'
|
||||
"comments": "",
|
||||
// File associations for the app
|
||||
"fileAssociations": [
|
||||
{
|
||||
// The extension (minus the leading period). e.g. png
|
||||
"ext": "wails",
|
||||
// The name. e.g. PNG File
|
||||
"name": "Wails",
|
||||
// Windows-only. The description. It is displayed on the `Type` column on Windows Explorer.
|
||||
"description": "Wails file",
|
||||
// The icon name without extension. Icons should be located in build folder. Proper icons will be generated from .png file for both macOS and Windows)
|
||||
"iconName": "fileIcon",
|
||||
// macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole.
|
||||
"role": "Editor"
|
||||
},
|
||||
],
|
||||
// Custom URI protocols that should be opened by the application
|
||||
"protocols": [
|
||||
{
|
||||
// protocol scheme. e.g. myapp
|
||||
"scheme": "myapp",
|
||||
// Windows-only. The description. It is displayed on the `Type` column on Windows Explorer.
|
||||
"description": "Myapp protocol",
|
||||
// macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole.
|
||||
"role": "Editor"
|
||||
}
|
||||
]
|
||||
},
|
||||
// 'multiple': One installer per architecture. 'single': Single universal installer for all architectures being built. Default: 'multiple'
|
||||
"nsisType": "",
|
||||
// Whether the app should be obfuscated. Default: false
|
||||
"obfuscated": "",
|
||||
// The arguments to pass to the garble command when using the obfuscated flag
|
||||
"garbleargs": "",
|
||||
// Bindings configurations
|
||||
"bindings": {
|
||||
// model.ts file generation config
|
||||
"ts_generation": {
|
||||
// All generated JavaScript entities will be prefixed with this value
|
||||
"prefix": "",
|
||||
// All generated JavaScript entities will be suffixed with this value
|
||||
"suffix": "",
|
||||
// Type of output to generate (classes|interfaces)
|
||||
"outputType": "classes",
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This file is read by the Wails CLI when running `wails build` or `wails dev`.
|
||||
|
||||
The `assetdir`, `reloaddirs`, `wailsjsdir`, `debounceMS`, `devserver` and `frontenddevserverurl` flags in `wails build/dev` will update the project config
|
||||
and thus become defaults for subsequent runs.
|
||||
|
||||
The JSON Schema for this file is located [here](https://wails.io/schemas/config.v2.json).
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"label": "Runtime",
|
||||
"position": 1
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
---
|
||||
sidebar_position: 7
|
||||
---
|
||||
|
||||
# Browser
|
||||
|
||||
These methods are related to the system browser.
|
||||
|
||||
### BrowserOpenURL
|
||||
|
||||
Opens the given URL in the system browser.
|
||||
|
||||
Go: `BrowserOpenURL(ctx context.Context, url string)`<br/>
|
||||
JS: `BrowserOpenURL(url string)`
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
---
|
||||
sidebar_position: 8
|
||||
---
|
||||
|
||||
# Clipboard
|
||||
|
||||
This part of the runtime provides access to the operating system's clipboard.<br/>
|
||||
The current implementation only handles text.
|
||||
|
||||
### ClipboardGetText
|
||||
|
||||
This method reads the currently stored text from the clipboard.
|
||||
|
||||
Go: `ClipboardGetText(ctx context.Context) (string, error)`<br/>
|
||||
Returns: a string (if the clipboard is empty an empty string will be returned) or an error.
|
||||
|
||||
JS: `ClipboardGetText(): Promise<string>`<br/>
|
||||
Returns: a promise with a string result (if the clipboard is empty an empty string will be returned).
|
||||
|
||||
### ClipboardSetText
|
||||
|
||||
This method writes a text to the clipboard.
|
||||
|
||||
Go: `ClipboardSetText(ctx context.Context, text string) error`<br/>
|
||||
Returns: an error if there is any.
|
||||
|
||||
JS: `ClipboardSetText(text: string): Promise<boolean>`<br/>
|
||||
Returns: a promise with true result if the text was successfully set on the clipboard, false otherwise.
|
||||
|
|
@ -1,309 +0,0 @@
|
|||
---
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
# Dialog
|
||||
|
||||
This part of the runtime provides access to native dialogs, such as File Selectors and Message boxes.
|
||||
|
||||
:::info JavaScript
|
||||
|
||||
Dialog is currently unsupported in the JS runtime.
|
||||
|
||||
:::
|
||||
|
||||
### OpenDirectoryDialog
|
||||
|
||||
Opens a dialog that prompts the user to select a directory. Can be customised using [OpenDialogOptions](#opendialogoptions).
|
||||
|
||||
Go: `OpenDirectoryDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error)`
|
||||
|
||||
Returns: Selected directory (blank if the user cancelled) or an error
|
||||
|
||||
### OpenFileDialog
|
||||
|
||||
Opens a dialog that prompts the user to select a file. Can be customised using [OpenDialogOptions](#opendialogoptions).
|
||||
|
||||
Go: `OpenFileDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error)`
|
||||
|
||||
Returns: Selected file (blank if the user cancelled) or an error
|
||||
|
||||
### OpenMultipleFilesDialog
|
||||
|
||||
Opens a dialog that prompts the user to select multiple files. Can be customised using [OpenDialogOptions](#opendialogoptions).
|
||||
|
||||
Go: `OpenMultipleFilesDialog(ctx context.Context, dialogOptions OpenDialogOptions) ([]string, error)`
|
||||
|
||||
Returns: Selected files (nil if the user cancelled) or an error
|
||||
|
||||
### SaveFileDialog
|
||||
|
||||
Opens a dialog that prompts the user to select a filename for the purposes of saving. Can be customised using [SaveDialogOptions](#savedialogoptions).
|
||||
|
||||
Go: `SaveFileDialog(ctx context.Context, dialogOptions SaveDialogOptions) (string, error)`
|
||||
|
||||
Returns: The selected file (blank if the user cancelled) or an error
|
||||
|
||||
### MessageDialog
|
||||
|
||||
Displays a message using a message dialog. Can be customised using [MessageDialogOptions](#messagedialogoptions).
|
||||
|
||||
Go: `MessageDialog(ctx context.Context, dialogOptions MessageDialogOptions) (string, error)`
|
||||
|
||||
Returns: The text of the selected button or an error
|
||||
|
||||
## Options
|
||||
|
||||
### OpenDialogOptions
|
||||
|
||||
```go
|
||||
type OpenDialogOptions struct {
|
||||
DefaultDirectory string
|
||||
DefaultFilename string
|
||||
Title string
|
||||
Filters []FileFilter
|
||||
ShowHiddenFiles bool
|
||||
CanCreateDirectories bool
|
||||
ResolvesAliases bool
|
||||
TreatPackagesAsDirectories bool
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Description | Win | Mac | Lin |
|
||||
| -------------------------- | ---------------------------------------------- | --- | --- | --- |
|
||||
| DefaultDirectory | The directory the dialog will show when opened | ✅ | ✅ | ✅ |
|
||||
| DefaultFilename | The default filename | ✅ | ✅ | ✅ |
|
||||
| Title | Title for the dialog | ✅ | ✅ | ✅ |
|
||||
| [Filters](#filefilter) | A list of file filters | ✅ | ✅ | ✅ |
|
||||
| ShowHiddenFiles | Show files hidden by the system | | ✅ | ✅ |
|
||||
| CanCreateDirectories | Allow user to create directories | | ✅ | |
|
||||
| ResolvesAliases | If true, returns the file not the alias | | ✅ | |
|
||||
| TreatPackagesAsDirectories | Allow navigating into packages | | ✅ | |
|
||||
|
||||
### SaveDialogOptions
|
||||
|
||||
```go
|
||||
type SaveDialogOptions struct {
|
||||
DefaultDirectory string
|
||||
DefaultFilename string
|
||||
Title string
|
||||
Filters []FileFilter
|
||||
ShowHiddenFiles bool
|
||||
CanCreateDirectories bool
|
||||
TreatPackagesAsDirectories bool
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Description | Win | Mac | Lin |
|
||||
| -------------------------- | ---------------------------------------------- | --- | --- | --- |
|
||||
| DefaultDirectory | The directory the dialog will show when opened | ✅ | ✅ | ✅ |
|
||||
| DefaultFilename | The default filename | ✅ | ✅ | ✅ |
|
||||
| Title | Title for the dialog | ✅ | ✅ | ✅ |
|
||||
| [Filters](#filefilter) | A list of file filters | ✅ | ✅ | ✅ |
|
||||
| ShowHiddenFiles | Show files hidden by the system | | ✅ | ✅ |
|
||||
| CanCreateDirectories | Allow user to create directories | | ✅ | |
|
||||
| TreatPackagesAsDirectories | Allow navigating into packages | | ✅ | |
|
||||
|
||||
### MessageDialogOptions
|
||||
|
||||
```go
|
||||
type MessageDialogOptions struct {
|
||||
Type DialogType
|
||||
Title string
|
||||
Message string
|
||||
Buttons []string
|
||||
DefaultButton string
|
||||
CancelButton string
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Description | Win | Mac | Lin |
|
||||
|---------------|----------------------------------------------------------------------------|----------------|-----|-----|
|
||||
| Type | The type of message dialog, eg question, info... | ✅ | ✅ | ✅ |
|
||||
| Title | Title for the dialog | ✅ | ✅ | ✅ |
|
||||
| Message | The message to show the user | ✅ | ✅ | ✅ |
|
||||
| Buttons | A list of button titles | | ✅ | |
|
||||
| DefaultButton | The button with this text should be treated as default. Bound to `return`. | ✅[*](#windows) | ✅ | |
|
||||
| CancelButton | The button with this text should be treated as cancel. Bound to `escape` | | ✅ | |
|
||||
|
||||
#### Windows
|
||||
|
||||
Windows has standard dialog types in which the buttons are not customisable.
|
||||
The value returned will be one of: "Ok", "Cancel", "Abort", "Retry", "Ignore", "Yes", "No", "Try Again" or "Continue".
|
||||
|
||||
For Question dialogs, the default button is "Yes" and the cancel button is "No".
|
||||
This can be changed by setting the `DefaultButton` value to `"No"`.
|
||||
|
||||
Example:
|
||||
```go
|
||||
result, err := runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{
|
||||
Type: runtime.QuestionDialog,
|
||||
Title: "Question",
|
||||
Message: "Do you want to continue?",
|
||||
DefaultButton: "No",
|
||||
})
|
||||
```
|
||||
|
||||
#### Linux
|
||||
|
||||
Linux has standard dialog types in which the buttons are not customisable.
|
||||
The value returned will be one of: "Ok", "Cancel", "Yes", "No"
|
||||
|
||||
#### Mac
|
||||
|
||||
A message dialog on Mac may specify up to 4 buttons. If no `DefaultButton` or `CancelButton` is given, the first button
|
||||
is considered default and is bound to the `return` key.
|
||||
|
||||
For the following code:
|
||||
|
||||
```go
|
||||
selection, err := runtime.MessageDialog(b.ctx, runtime.MessageDialogOptions{
|
||||
Title: "It's your turn!",
|
||||
Message: "Select a number",
|
||||
Buttons: []string{"one", "two", "three", "four"},
|
||||
})
|
||||
```
|
||||
|
||||
the first button is shown as default:
|
||||
|
||||
```mdx-code-block
|
||||
<div class="text--center">
|
||||
<img
|
||||
src={require("@site/static/img/runtime/dialog_no_defaults.png").default}
|
||||
width="30%"
|
||||
class="screenshot"
|
||||
/>
|
||||
</div>
|
||||
<br />
|
||||
```
|
||||
|
||||
And if we specify `DefaultButton` to be "two":
|
||||
|
||||
```go
|
||||
selection, err := runtime.MessageDialog(b.ctx, runtime.MessageDialogOptions{
|
||||
Title: "It's your turn!",
|
||||
Message: "Select a number",
|
||||
Buttons: []string{"one", "two", "three", "four"},
|
||||
DefaultButton: "two",
|
||||
})
|
||||
```
|
||||
|
||||
the second button is shown as default. When `return` is pressed, the value "two" is returned.
|
||||
|
||||
```mdx-code-block
|
||||
<div class="text--center">
|
||||
<img
|
||||
src={require("@site/static/img/runtime/dialog_default_button.png").default}
|
||||
width="30%"
|
||||
class="screenshot"
|
||||
/>
|
||||
</div>
|
||||
<br />
|
||||
```
|
||||
|
||||
If we now specify `CancelButton` to be "three":
|
||||
|
||||
```go
|
||||
selection, err := runtime.MessageDialog(b.ctx, runtime.MessageDialogOptions{
|
||||
Title: "It's your turn!",
|
||||
Message: "Select a number",
|
||||
Buttons: []string{"one", "two", "three", "four"},
|
||||
DefaultButton: "two",
|
||||
CancelButton: "three",
|
||||
})
|
||||
```
|
||||
|
||||
the button with "three" is shown at the bottom of the dialog. When `escape` is pressed, the value "three" is returned:
|
||||
|
||||
```mdx-code-block
|
||||
<div class="text--center">
|
||||
<img
|
||||
src={require("@site/static/img/runtime/dialog_default_cancel.png").default}
|
||||
width="30%"
|
||||
class="screenshot"
|
||||
/>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
```
|
||||
|
||||
#### DialogType
|
||||
|
||||
```go
|
||||
const (
|
||||
InfoDialog DialogType = "info"
|
||||
WarningDialog DialogType = "warning"
|
||||
ErrorDialog DialogType = "error"
|
||||
QuestionDialog DialogType = "question"
|
||||
)
|
||||
```
|
||||
|
||||
### FileFilter
|
||||
|
||||
```go
|
||||
type FileFilter struct {
|
||||
DisplayName string // Filter information EG: "Image Files (*.jpg, *.png)"
|
||||
Pattern string // semi-colon separated list of extensions, EG: "*.jpg;*.png"
|
||||
}
|
||||
```
|
||||
|
||||
#### Windows
|
||||
|
||||
Windows allows you to use multiple file filters in dialog boxes. Each FileFilter will show up as a separate entry in the
|
||||
dialog:
|
||||
|
||||
```mdx-code-block
|
||||
<div class="text--center">
|
||||
<img
|
||||
src={require("@site/static/img/runtime/dialog_win_filters.png").default}
|
||||
width="50%"
|
||||
class="screenshot"
|
||||
/>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
```
|
||||
|
||||
#### Linux
|
||||
|
||||
Linux allows you to use multiple file filters in dialog boxes. Each FileFilter will show up as a separate entry in the
|
||||
dialog:
|
||||
|
||||
```mdx-code-block
|
||||
<div class="text--center">
|
||||
<img
|
||||
src={require("@site/static/img/runtime/dialog_lin_filters.png").default}
|
||||
width="50%"
|
||||
class="screenshot"
|
||||
/>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
```
|
||||
|
||||
#### Mac
|
||||
|
||||
Mac dialogs only have the concept of a single set of patterns to filter files. If multiple FileFilters are provided,
|
||||
Wails will use all the Patterns defined.
|
||||
|
||||
Example:
|
||||
|
||||
```go
|
||||
selection, err := runtime.OpenFileDialog(b.ctx, runtime.OpenDialogOptions{
|
||||
Title: "Select File",
|
||||
Filters: []runtime.FileFilter{
|
||||
{
|
||||
DisplayName: "Images (*.png;*.jpg)",
|
||||
Pattern: "*.png;*.jpg",
|
||||
}, {
|
||||
DisplayName: "Videos (*.mov;*.mp4)",
|
||||
Pattern: "*.mov;*.mp4",
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
This will result in the Open File dialog using `*.png,*.jpg,*.mov,*.mp4` as a filter.
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Events
|
||||
|
||||
The Wails runtime provides a unified events system, where events can be emitted or received by either Go or JavaScript.
|
||||
Optionally, data may be passed with the events. Listeners will receive the data in the local data types.
|
||||
|
||||
### EventsOn
|
||||
|
||||
This method sets up a listener for the given event name. When an event of type `eventName` is [emitted](#EventsEmit),
|
||||
the callback is triggered. Any additional data sent with the emitted event will be passed to the callback. It returns
|
||||
a function to cancel the listener.
|
||||
|
||||
Go: `EventsOn(ctx context.Context, eventName string, callback func(optionalData ...interface{})) func()`<br/>
|
||||
JS: `EventsOn(eventName string, callback function(optionalData?: any)): () => void`
|
||||
|
||||
### EventsOff
|
||||
|
||||
This method unregisters the listener for the given event name, optionally multiple listeneres can be unregistered via `additionalEventNames`.
|
||||
|
||||
Go: `EventsOff(ctx context.Context, eventName string, additionalEventNames ...string)`<br/>
|
||||
JS: `EventsOff(eventName string, ...additionalEventNames)`
|
||||
|
||||
### EventsOnce
|
||||
|
||||
This method sets up a listener for the given event name, but will only trigger once. It returns a function to cancel
|
||||
the listener.
|
||||
|
||||
Go: `EventsOnce(ctx context.Context, eventName string, callback func(optionalData ...interface{})) func()`<br/>
|
||||
JS: `EventsOnce(eventName string, callback function(optionalData?: any)): () => void`
|
||||
|
||||
### EventsOnMultiple
|
||||
|
||||
This method sets up a listener for the given event name, but will only trigger a maximum of `counter` times. It returns
|
||||
a function to cancel the listener.
|
||||
|
||||
Go: `EventsOnMultiple(ctx context.Context, eventName string, callback func(optionalData ...interface{}), counter int) func()`<br/>
|
||||
JS: `EventsOnMultiple(eventName string, callback function(optionalData?: any), counter int): () => void`
|
||||
|
||||
### EventsEmit
|
||||
|
||||
This method emits the given event. Optional data may be passed with the event. This will trigger any event listeners.
|
||||
|
||||
Go: `EventsEmit(ctx context.Context, eventName string, optionalData ...interface{})`<br/>
|
||||
JS: `EventsEmit(eventName: string, ...optionalData: any)`
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Introduction
|
||||
|
||||
The runtime is a library that provides utility methods for your application. There is both a Go and JavaScript runtime
|
||||
and the aim is to try and keep them at parity where possible.
|
||||
|
||||
It has utility methods for:
|
||||
|
||||
- [Window](window.mdx)
|
||||
- [Menu](menu.mdx)
|
||||
- [Dialog](dialog.mdx)
|
||||
- [Events](events.mdx)
|
||||
- [Browser](browser.mdx)
|
||||
- [Log](log.mdx)
|
||||
- [Clipboard](clipboard.mdx)
|
||||
|
||||
The Go Runtime is available through importing `github.com/wailsapp/wails/v2/pkg/runtime`. All methods in this package
|
||||
take a context as the first parameter. This context should be obtained from the [OnStartup](../options.mdx#onstartup)
|
||||
or [OnDomReady](../options.mdx#ondomready) hooks.
|
||||
|
||||
:::info Note
|
||||
|
||||
Whilst the context will be provided to the
|
||||
[OnStartup](../options.mdx#onstartup) method, there's no guarantee the runtime will work in this method as
|
||||
the window is initialising in a different thread. If
|
||||
you wish to call runtime methods at startup, use [OnDomReady](../options.mdx#ondomready).
|
||||
|
||||
:::
|
||||
|
||||
The JavaScript library is available to the frontend via the `window.runtime` map. There is a runtime package generated when using `dev`
|
||||
mode that provides TypeScript declarations for the runtime. This should be located in the `wailsjs` directory in your
|
||||
frontend directory.
|
||||
|
||||
e.g. if you wanted to import the [EventsOn](./events/#eventson) function in your frontend, you can do the following:
|
||||
|
||||
```ts
|
||||
// src/index.js (for example)
|
||||
import { EventsOn } from '../wailsjs/runtime'
|
||||
```
|
||||
|
||||
### Hide
|
||||
|
||||
Go: `Hide(ctx context.Context)`<br/>
|
||||
JS: `Hide()`
|
||||
|
||||
Hides the application.
|
||||
|
||||
:::info Note
|
||||
|
||||
On Mac, this will hide the application in the same way as the `Hide` menu item in standard Mac applications.
|
||||
This is different to hiding the window, but the application still being in the foreground.
|
||||
For Windows and Linux, this is currently the same as `WindowHide`.
|
||||
|
||||
:::
|
||||
|
||||
### Show
|
||||
|
||||
Shows the application.
|
||||
|
||||
:::info Note
|
||||
|
||||
On Mac, this will bring the application back into the foreground.
|
||||
For Windows and Linux, this is currently the same as `WindowShow`.
|
||||
|
||||
:::
|
||||
|
||||
Go: `Show(ctx context.Context)`<br/>
|
||||
JS: `Show()`
|
||||
|
||||
### Quit
|
||||
|
||||
Quits the application.
|
||||
|
||||
Go: `Quit(ctx context.Context)`<br/>
|
||||
JS: `Quit()`
|
||||
|
||||
### Environment
|
||||
|
||||
Returns details of the current environment.
|
||||
|
||||
Go: `Environment(ctx context.Context) EnvironmentInfo`<br/>
|
||||
JS: `Environment(): Promise<EnvironmentInfo>`
|
||||
|
||||
#### EnvironmentInfo
|
||||
|
||||
Go:
|
||||
|
||||
```go
|
||||
type EnvironmentInfo struct {
|
||||
BuildType string
|
||||
Platform string
|
||||
Arch string
|
||||
}
|
||||
```
|
||||
|
||||
JS:
|
||||
|
||||
```ts
|
||||
interface EnvironmentInfo {
|
||||
buildType: string;
|
||||
platform: string;
|
||||
arch: string;
|
||||
}
|
||||
```
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# Log
|
||||
|
||||
The Wails runtime provides a logging mechanism that may be called from Go or JavaScript. Like most
|
||||
loggers, there are a number of log levels:
|
||||
|
||||
- Trace
|
||||
- Debug
|
||||
- Info
|
||||
- Warning
|
||||
- Error
|
||||
- Fatal
|
||||
|
||||
The logger will output any log message at the current, or higher, log level. Example: The `Debug` log
|
||||
level will output all messages except `Trace` messages.
|
||||
|
||||
### LogPrint
|
||||
|
||||
Logs the given message as a raw message.
|
||||
|
||||
Go: `LogPrint(ctx context.Context, message string)`<br/>
|
||||
JS: `LogPrint(message: string)`
|
||||
|
||||
### LogPrintf
|
||||
|
||||
Logs the given message as a raw message.
|
||||
|
||||
Go: `LogPrintf(ctx context.Context, format string, args ...interface{})`<br/>
|
||||
|
||||
### LogTrace
|
||||
|
||||
Logs the given message at the `Trace` log level.
|
||||
|
||||
Go: `LogTrace(ctx context.Context, message string)`<br/>
|
||||
JS: `LogTrace(message: string)`
|
||||
|
||||
### LogTracef
|
||||
|
||||
Logs the given message at the `Trace` log level.
|
||||
|
||||
Go: `LogTracef(ctx context.Context, format string, args ...interface{})`<br/>
|
||||
|
||||
### LogDebug
|
||||
|
||||
Logs the given message at the `Debug` log level.
|
||||
|
||||
Go: `LogDebug(ctx context.Context, message string)`<br/>
|
||||
JS: `LogDebug(message: string)`
|
||||
|
||||
### LogDebugf
|
||||
|
||||
Logs the given message at the `Debug` log level.
|
||||
|
||||
Go: `LogDebugf(ctx context.Context, format string, args ...interface{})`<br/>
|
||||
|
||||
### LogInfo
|
||||
|
||||
Logs the given message at the `Info` log level.
|
||||
|
||||
Go: `LogInfo(ctx context.Context, message string)`<br/>
|
||||
JS: `LogInfo(message: string)`
|
||||
|
||||
### LogInfof
|
||||
|
||||
Logs the given message at the `Info` log level.
|
||||
|
||||
Go: `LogInfof(ctx context.Context, format string, args ...interface{})`<br/>
|
||||
|
||||
### LogWarning
|
||||
|
||||
Logs the given message at the `Warning` log level.
|
||||
|
||||
Go: `LogWarning(ctx context.Context, message string)`<br/>
|
||||
JS: `LogWarning(message: string)`
|
||||
|
||||
### LogWarningf
|
||||
|
||||
Logs the given message at the `Warning` log level.
|
||||
|
||||
Go: `LogWarningf(ctx context.Context, format string, args ...interface{})`<br/>
|
||||
|
||||
### LogError
|
||||
|
||||
Logs the given message at the `Error` log level.
|
||||
|
||||
Go: `LogError(ctx context.Context, message string)`<br/>
|
||||
JS: `LogError(message: string)`
|
||||
|
||||
### LogErrorf
|
||||
|
||||
Logs the given message at the `Error` log level.
|
||||
|
||||
Go: `LogErrorf(ctx context.Context, format string, args ...interface{})`<br/>
|
||||
|
||||
### LogFatal
|
||||
|
||||
Logs the given message at the `Fatal` log level.
|
||||
|
||||
Go: `LogFatal(ctx context.Context, message string)`<br/>
|
||||
JS: `LogFatal(message: string)`
|
||||
|
||||
### LogFatalf
|
||||
|
||||
Logs the given message at the `Fatal` log level.
|
||||
|
||||
Go: `LogFatalf(ctx context.Context, format string, args ...interface{})`<br/>
|
||||
|
||||
### LogSetLogLevel
|
||||
|
||||
Sets the log level. In JavaScript, the number relates to the following log levels:
|
||||
|
||||
| Value | Log Level |
|
||||
| ----- | --------- |
|
||||
| 1 | Trace |
|
||||
| 2 | Debug |
|
||||
| 3 | Info |
|
||||
| 4 | Warning |
|
||||
| 5 | Error |
|
||||
|
||||
Go: `LogSetLogLevel(ctx context.Context, level logger.LogLevel)`<br/>
|
||||
JS: `LogSetLogLevel(level: number)`
|
||||
|
||||
## Using a Custom Logger
|
||||
|
||||
A custom logger may be used by providing it using the [Logger](../options.mdx#logger)
|
||||
application option. The only requirement is that the logger implements the `logger.Logger` interface
|
||||
defined in `github.com/wailsapp/wails/v2/pkg/logger`:
|
||||
|
||||
```go title="logger.go"
|
||||
type Logger interface {
|
||||
Print(message string)
|
||||
Trace(message string)
|
||||
Debug(message string)
|
||||
Info(message string)
|
||||
Warning(message string)
|
||||
Error(message string)
|
||||
Fatal(message string)
|
||||
}
|
||||
```
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
---
|
||||
sidebar_position: 6
|
||||
---
|
||||
|
||||
# Menu
|
||||
|
||||
These methods are related to the application menu.
|
||||
|
||||
:::info JavaScript
|
||||
|
||||
Menu is currently unsupported in the JS runtime.
|
||||
|
||||
:::
|
||||
|
||||
### MenuSetApplicationMenu
|
||||
|
||||
Sets the application menu to the given [menu](../menus.mdx).
|
||||
|
||||
Go: `MenuSetApplicationMenu(ctx context.Context, menu *menu.Menu)`
|
||||
|
||||
### MenuUpdateApplicationMenu
|
||||
|
||||
Updates the application menu, picking up any changes to the menu passed to `MenuSetApplicationMenu`.
|
||||
|
||||
Go: `MenuUpdateApplicationMenu(ctx context.Context)`
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
---
|
||||
sidebar_position: 9
|
||||
---
|
||||
|
||||
# Screen
|
||||
|
||||
These methods provide information about the currently connected screens.
|
||||
|
||||
### ScreenGetAll
|
||||
|
||||
Returns a list of currently connected screens.
|
||||
|
||||
Go: `ScreenGetAll(ctx context.Context) []screen`<br/>
|
||||
JS: `ScreenGetAll()`
|
||||
|
||||
|
||||
#### Screen
|
||||
|
||||
Go struct:
|
||||
```go
|
||||
type Screen struct {
|
||||
IsCurrent bool
|
||||
IsPrimary bool
|
||||
Width int
|
||||
Height int
|
||||
}
|
||||
```
|
||||
|
||||
Typescript interface:
|
||||
```ts
|
||||
interface Screen {
|
||||
isCurrent: boolean;
|
||||
isPrimary: boolean;
|
||||
width : number
|
||||
height : number
|
||||
}
|
||||
```
|
||||
|
|
@ -1,261 +0,0 @@
|
|||
---
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
# Window
|
||||
|
||||
These methods give control of the application window.
|
||||
|
||||
### WindowSetTitle
|
||||
|
||||
Sets the text in the window title bar.
|
||||
|
||||
Go: `WindowSetTitle(ctx context.Context, title string)`<br/>
|
||||
JS: `WindowSetTitle(title: string)`
|
||||
|
||||
### WindowFullscreen
|
||||
|
||||
Makes the window full screen.
|
||||
|
||||
Go: `WindowFullscreen(ctx context.Context)`<br/>
|
||||
JS: `WindowFullscreen()`
|
||||
|
||||
### WindowUnfullscreen
|
||||
|
||||
Restores the previous window dimensions and position prior to full screen.
|
||||
|
||||
Go: `WindowUnfullscreen(ctx context.Context)`<br/>
|
||||
JS: `WindowUnfullscreen()`
|
||||
|
||||
### WindowIsFullscreen
|
||||
|
||||
Returns true if the window is full screen.
|
||||
|
||||
Go: `WindowIsFullscreen(ctx context.Context) bool`<br/>
|
||||
JS: `WindowIsFullscreen() Promise<boolean>`
|
||||
|
||||
### WindowCenter
|
||||
|
||||
Centers the window on the monitor the window is currently on.
|
||||
|
||||
Go: `WindowCenter(ctx context.Context)`<br/>
|
||||
JS: `WindowCenter()`
|
||||
|
||||
### WindowExecJS
|
||||
|
||||
Executes arbitrary JS code in the window.
|
||||
|
||||
This method runs the code in the browser asynchronously and returns immediately.
|
||||
If the script causes any errors, they will only be available in the browser console.
|
||||
|
||||
Go: `WindowExecJS(ctx context.Context, js string)`
|
||||
|
||||
### WindowReload
|
||||
|
||||
Performs a "reload" (Reloads current page).
|
||||
|
||||
Go: `WindowReload(ctx context.Context)`<br/>
|
||||
JS: `WindowReload()`
|
||||
|
||||
### WindowReloadApp
|
||||
|
||||
Reloads the application frontend.
|
||||
|
||||
Go: `WindowReloadApp(ctx context.Context)`<br/>
|
||||
JS: `WindowReloadApp()`
|
||||
|
||||
### WindowSetSystemDefaultTheme
|
||||
|
||||
Windows only.
|
||||
|
||||
Go: `WindowSetSystemDefaultTheme(ctx context.Context)`<br/>
|
||||
JS: `WindowSetSystemDefaultTheme()`
|
||||
|
||||
Sets window theme to system default (dark/light).
|
||||
|
||||
### WindowSetLightTheme
|
||||
|
||||
Windows only.
|
||||
|
||||
Go: `WindowSetLightTheme(ctx context.Context)`<br/>
|
||||
JS: `WindowSetLightTheme()`
|
||||
|
||||
Sets window theme to light.
|
||||
|
||||
### WindowSetDarkTheme
|
||||
|
||||
Windows only.
|
||||
|
||||
Go: `WindowSetDarkTheme(ctx context.Context)`<br/>
|
||||
JS: `WindowSetDarkTheme()`
|
||||
|
||||
Sets window theme to dark.
|
||||
|
||||
### WindowShow
|
||||
|
||||
Shows the window, if it is currently hidden.
|
||||
|
||||
Go: `WindowShow(ctx context.Context)`<br/>
|
||||
JS: `WindowShow()`
|
||||
|
||||
### WindowHide
|
||||
|
||||
Hides the window, if it is currently visible.
|
||||
|
||||
Go: `WindowHide(ctx context.Context)`<br/>
|
||||
JS: `WindowHide()`
|
||||
|
||||
### WindowIsNormal
|
||||
|
||||
Returns true if the window not minimised, maximised or fullscreen.
|
||||
|
||||
Go: `WindowIsNormal(ctx context.Context) bool`<br/>
|
||||
JS: `WindowIsNormal() Promise<boolean>`
|
||||
|
||||
### WindowSetSize
|
||||
|
||||
Sets the width and height of the window.
|
||||
|
||||
Go: `WindowSetSize(ctx context.Context, width int, height int)`<br/>
|
||||
JS: `WindowSetSize(width: number, height: number)`
|
||||
|
||||
### WindowGetSize
|
||||
|
||||
Gets the width and height of the window.
|
||||
|
||||
Go: `WindowGetSize(ctx context.Context) (width int, height int)`<br/>
|
||||
JS: `WindowGetSize(): Promise<Size>`
|
||||
|
||||
### WindowSetMinSize
|
||||
|
||||
Sets the minimum window size.
|
||||
Will resize the window if the window is currently smaller than the given dimensions.
|
||||
|
||||
Setting a size of `0,0` will disable this constraint.
|
||||
|
||||
Go: `WindowSetMinSize(ctx context.Context, width int, height int)`<br/>
|
||||
JS: `WindowSetMinSize(width: number, height: number)`
|
||||
|
||||
### WindowSetMaxSize
|
||||
|
||||
Sets the maximum window size.
|
||||
Will resize the window if the window is currently larger than the given dimensions.
|
||||
|
||||
Setting a size of `0,0` will disable this constraint.
|
||||
|
||||
Go: `WindowSetMaxSize(ctx context.Context, width int, height int)`<br/>
|
||||
JS: `WindowSetMaxSize(width: number, height: number)`
|
||||
|
||||
### WindowSetAlwaysOnTop
|
||||
|
||||
Sets the window AlwaysOnTop or not on top.
|
||||
|
||||
Go: `WindowSetAlwaysOnTop(ctx context.Context, b bool)`<br/>
|
||||
JS: `WindowSetAlwaysOnTop(b: boolean)`
|
||||
|
||||
### WindowSetPosition
|
||||
|
||||
Sets the window position relative to the monitor the window is currently on.
|
||||
|
||||
Go: `WindowSetPosition(ctx context.Context, x int, y int)`<br/>
|
||||
JS: `WindowSetPosition(x: number, y: number)`
|
||||
|
||||
### WindowGetPosition
|
||||
|
||||
Gets the window position relative to the monitor the window is currently on.
|
||||
|
||||
Go: `WindowGetPosition(ctx context.Context) (x int, y int)`<br/>
|
||||
JS: `WindowGetPosition(): Promise<Position>`
|
||||
|
||||
### WindowMaximise
|
||||
|
||||
Maximises the window to fill the screen.
|
||||
|
||||
Go: `WindowMaximise(ctx context.Context)`<br/>
|
||||
JS: `WindowMaximise()`
|
||||
|
||||
### WindowUnmaximise
|
||||
|
||||
Restores the window to the dimensions and position prior to maximising.
|
||||
|
||||
Go: `WindowUnmaximise(ctx context.Context)`<br/>
|
||||
JS: `WindowUnmaximise()`
|
||||
|
||||
### WindowIsMaximised
|
||||
|
||||
Returns true if the window is maximised.
|
||||
|
||||
Go: `WindowIsMaximised(ctx context.Context) bool`<br/>
|
||||
JS: `WindowIsMaximised() Promise<boolean>`
|
||||
|
||||
### WindowToggleMaximise
|
||||
|
||||
Toggles between Maximised and UnMaximised.
|
||||
|
||||
Go: `WindowToggleMaximise(ctx context.Context)`<br/>
|
||||
JS: `WindowToggleMaximise()`
|
||||
|
||||
### WindowMinimise
|
||||
|
||||
Minimises the window.
|
||||
|
||||
Go: `WindowMinimise(ctx context.Context)`<br/>
|
||||
JS: `WindowMinimise()`
|
||||
|
||||
### WindowUnminimise
|
||||
|
||||
Restores the window to the dimensions and position prior to minimising.
|
||||
|
||||
Go: `WindowUnminimise(ctx context.Context)`<br/>
|
||||
JS: `WindowUnminimise()`
|
||||
|
||||
### WindowIsMinimised
|
||||
|
||||
Returns true if the window is minimised.
|
||||
|
||||
Go: `WindowIsMinimised(ctx context.Context) bool`<br/>
|
||||
JS: `WindowIsMinimised() Promise<boolean>`
|
||||
|
||||
### WindowSetBackgroundColour
|
||||
|
||||
Sets the background colour of the window to the given RGBA colour definition.
|
||||
This colour will show through for all transparent pixels.
|
||||
|
||||
Valid values for R, G, B and A are 0-255.
|
||||
|
||||
:::info Windows
|
||||
|
||||
On Windows, only alpha values of 0 or 255 are supported.
|
||||
Any value that is not 0 will be considered 255.
|
||||
|
||||
:::
|
||||
|
||||
Go: `WindowSetBackgroundColour(ctx context.Context, R, G, B, A uint8)`<br/>
|
||||
JS: `WindowSetBackgroundColour(R, G, B, A)`
|
||||
|
||||
### WindowPrint
|
||||
|
||||
Opens tha native print dialog.
|
||||
|
||||
Go: `WindowPrint(ctx context.Context)`<br/>
|
||||
JS: `WindowPrint()`
|
||||
|
||||
## TypeScript Object Definitions
|
||||
|
||||
### Position
|
||||
|
||||
```ts
|
||||
interface Position {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
```
|
||||
|
||||
### Size
|
||||
|
||||
```ts
|
||||
interface Size {
|
||||
w: number;
|
||||
h: number;
|
||||
}
|
||||
```
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"label": "Tutorials",
|
||||
"position": 70
|
||||
}
|
||||
|
|
@ -1,249 +0,0 @@
|
|||
---
|
||||
sidebar_position: 20
|
||||
---
|
||||
|
||||
# Dogs API
|
||||
|
||||
```mdx-code-block
|
||||
<div class="text--center">
|
||||
<img
|
||||
src={require("@site/static/img/tutorials/dogsapi/img.webp").default}
|
||||
width="50%"
|
||||
className="screenshot"
|
||||
/>
|
||||
</div>
|
||||
<br />
|
||||
```
|
||||
|
||||
:::note
|
||||
|
||||
This tutorial has been kindly provided by [@tatadan](https://twitter.com/tatadan) and forms part of
|
||||
their [Wails Examples Repository](https://github.com/tataDan/wails-v2-examples).
|
||||
|
||||
:::
|
||||
|
||||
In this tutorial we are going to develop an application that retrieves photos of dogs from the web
|
||||
and then displays them.
|
||||
|
||||
### Create the project
|
||||
|
||||
Let's create the application. From a terminal enter:
|
||||
`wails init -n dogs-api -t svelte`
|
||||
|
||||
Note: We could optionally add `-ide vscode` or `-ide goland` to the end of this command if you wanted
|
||||
to add IDE support.
|
||||
|
||||
Now let's `cd dogs-api` and start editing the project files.
|
||||
|
||||
### Remove unused code
|
||||
|
||||
We will start by removing some elements that we know we will not use:
|
||||
|
||||
- Open `app.go` and remove the following lines:
|
||||
|
||||
```go
|
||||
// Greet returns a greeting for the given name
|
||||
func (a *App) Greet(name string) string {
|
||||
return fmt.Sprintf("Hello %s, It's show time!", name)
|
||||
}
|
||||
```
|
||||
|
||||
- Open `frontend/src/App.svelte` and delete all lines.
|
||||
- Delete the `frontend/src/assets/images/logo-universal.png` file
|
||||
|
||||
### Creating our application
|
||||
|
||||
Now let's add our new Go code.
|
||||
|
||||
Add the following struct declarations to `app.go` before the function definitions:
|
||||
|
||||
```go
|
||||
type RandomImage struct {
|
||||
Message string
|
||||
Status string
|
||||
}
|
||||
|
||||
type AllBreeds struct {
|
||||
Message map[string]map[string][]string
|
||||
Status string
|
||||
}
|
||||
|
||||
type ImagesByBreed struct {
|
||||
Message []string
|
||||
Status string
|
||||
}
|
||||
```
|
||||
|
||||
Add the following functions to `app.go` (perhaps after the existing function definitions):
|
||||
|
||||
```go
|
||||
func (a *App) GetRandomImageUrl() string {
|
||||
response, err := http.Get("https://dog.ceo/api/breeds/image/random")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
responseData, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var data RandomImage
|
||||
json.Unmarshal(responseData, &data)
|
||||
|
||||
return data.Message
|
||||
}
|
||||
|
||||
func (a *App) GetBreedList() []string {
|
||||
var breeds []string
|
||||
|
||||
response, err := http.Get("https://dog.ceo/api/breeds/list/all")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
responseData, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var data AllBreeds
|
||||
json.Unmarshal(responseData, &data)
|
||||
|
||||
for k := range data.Message {
|
||||
breeds = append(breeds, k)
|
||||
}
|
||||
|
||||
sort.Strings(breeds)
|
||||
|
||||
return breeds
|
||||
}
|
||||
|
||||
func (a *App) GetImageUrlsByBreed(breed string) []string {
|
||||
|
||||
url := fmt.Sprintf("%s%s%s%s", "https://dog.ceo/api/", "breed/", breed, "/images")
|
||||
response, err := http.Get(url)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
responseData, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var data ImagesByBreed
|
||||
json.Unmarshal(responseData, &data)
|
||||
|
||||
return data.Message
|
||||
}
|
||||
```
|
||||
|
||||
Modify the `import` section of `app.go` to look like this:
|
||||
|
||||
```go
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"sort"
|
||||
)
|
||||
```
|
||||
|
||||
Add the following lines to `frontend/src/App.svelte`:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
```html
|
||||
<script>
|
||||
import { GetRandomImageUrl } from "../wailsjs/go/main/App.js";
|
||||
import { GetBreedList } from "../wailsjs/go/main/App.js";
|
||||
import { GetImageUrlsByBreed } from "../wailsjs/go/main/App.js";
|
||||
|
||||
let randomImageUrl = "";
|
||||
let breeds = [];
|
||||
let photos = [];
|
||||
let selectedBreed;
|
||||
let showRandomPhoto = false;
|
||||
let showBreedPhotos = false;
|
||||
|
||||
function init() {
|
||||
getBreedList();
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
function getRandomImageUrl() {
|
||||
showRandomPhoto = false;
|
||||
showBreedPhotos = false;
|
||||
GetRandomImageUrl().then((result) => (randomImageUrl = result));
|
||||
showRandomPhoto = true;
|
||||
}
|
||||
|
||||
function getBreedList() {
|
||||
GetBreedList().then((result) => (breeds = result));
|
||||
}
|
||||
|
||||
function getImageUrlsByBreed() {
|
||||
init();
|
||||
showRandomPhoto = false;
|
||||
showBreedPhotos = false;
|
||||
GetImageUrlsByBreed(selectedBreed).then((result) => (photos = result));
|
||||
showBreedPhotos = true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<h3>Dogs API</h3>
|
||||
<div>
|
||||
<button class="btn" on:click={getRandomImageUrl}>
|
||||
Fetch a dog randomly
|
||||
</button>
|
||||
Click on down arrow to select a breed
|
||||
<select bind:value={selectedBreed}>
|
||||
{#each breeds as breed}
|
||||
<option value={breed}>
|
||||
{breed}
|
||||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
<button class="btn" on:click={getImageUrlsByBreed}>
|
||||
Fetch by this breed
|
||||
</button>
|
||||
</div>
|
||||
<br />
|
||||
{#if showRandomPhoto}
|
||||
<img id="random-photo" src={randomImageUrl} alt="No dog found" />
|
||||
{/if}
|
||||
{#if showBreedPhotos}
|
||||
{#each photos as photo}
|
||||
<img id="breed-photos" src={photo} alt="No dog found" />
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
#random-photo {
|
||||
width: 600px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
#breed-photos {
|
||||
width: 300px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.btn:focus {
|
||||
border-width: 3px;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
### Testing the application
|
||||
|
||||
To generate the bindings and test the application, run `wails dev`.
|
||||
|
||||
### Compiling the application
|
||||
|
||||
To compile the application to a single, production grade binary, run `wails build`.
|
||||
|
|
@ -1,127 +0,0 @@
|
|||
---
|
||||
sidebar_position: 10
|
||||
---
|
||||
|
||||
# Hello World
|
||||
|
||||
The aim of this tutorial is to get you up and running with the most basic
|
||||
application using Wails. You will be able to:
|
||||
|
||||
- Create a new Wails application
|
||||
- Build the application
|
||||
- Run the application
|
||||
|
||||
:::note
|
||||
|
||||
This tutorial uses Windows as the target platform. Output will vary slightly
|
||||
depending on your operating system.
|
||||
|
||||
:::
|
||||
|
||||
## Create a new Wails application
|
||||
|
||||
To create a new Wails application using the default vanilla JS template,
|
||||
you need to run the following command:
|
||||
|
||||
```bash
|
||||
wails init -n helloworld
|
||||
```
|
||||
|
||||
You should see something similar to the following:
|
||||
|
||||
```
|
||||
Wails CLI v2.0.0
|
||||
|
||||
Initialising Project 'helloworld'
|
||||
---------------------------------
|
||||
|
||||
Project Name: helloworld
|
||||
Project Directory: C:\Users\leaan\tutorial\helloworld
|
||||
Project Template: vanilla
|
||||
Template Support: https://wails.io
|
||||
|
||||
Initialised project 'helloworld' in 232ms.
|
||||
```
|
||||
|
||||
This will create a new directory called `helloworld` in the current directory.
|
||||
In this directory, you will find a number of files:
|
||||
|
||||
```
|
||||
build/ - Contains the build files + compiled application
|
||||
frontend/ - Contains the frontend files
|
||||
app.go - Contains the application code
|
||||
main.go - The main program with the application configuration
|
||||
wails.json - The project configuration file
|
||||
go.mod - The go module file
|
||||
go.sum - The go module checksum file
|
||||
```
|
||||
|
||||
## Build the application
|
||||
|
||||
To build the application, change to the new `helloworld` project directory and run the following command:
|
||||
|
||||
```bash
|
||||
wails build
|
||||
```
|
||||
|
||||
You should see something like the following:
|
||||
|
||||
```
|
||||
Wails CLI v2.0.0
|
||||
|
||||
App Type: desktop
|
||||
Platforms: windows/amd64
|
||||
Compiler: C:\Users\leaan\go\go1.18.3\bin\go.exe
|
||||
Build Mode: Production
|
||||
Devtools: false
|
||||
Skip Frontend: false
|
||||
Compress: false
|
||||
Package: true
|
||||
Clean Build Dir: false
|
||||
LDFlags: ""
|
||||
Tags: []
|
||||
Race Detector: false
|
||||
|
||||
Building target: windows/amd64
|
||||
------------------------------
|
||||
- Installing frontend dependencies: Done.
|
||||
- Compiling frontend: Done.
|
||||
- Generating bundle assets: Done.
|
||||
- Compiling application: Done.
|
||||
Built 'C:\Users\leaan\tutorial\helloworld\build\bin\helloworld.exe' in 10.616s.
|
||||
```
|
||||
|
||||
This has compiled the application and saved it in the `build/bin` directory.
|
||||
|
||||
## Run the application
|
||||
|
||||
If we view the `build/bin` directory in Windows Explorer, we should see our project binary:
|
||||
|
||||
```mdx-code-block
|
||||
<div class="text--center">
|
||||
<img
|
||||
src={require("@site/static/img/helloworld-app-icon.webp").default}
|
||||
width="134px"
|
||||
/>
|
||||
</div>
|
||||
<br />
|
||||
```
|
||||
|
||||
We can run it by simply double-clicking the `helloworld.exe` file.
|
||||
|
||||
On Mac, Wails generates a `helloworld.app` file which can be run by double-clicking it.
|
||||
|
||||
On Linux, you can run the application using `./helloworld` from the `build/bin` directory.
|
||||
|
||||
You should see the application working as expected:
|
||||
|
||||
```mdx-code-block
|
||||
<div class="text--center">
|
||||
<img
|
||||
src={require("@site/static/img/windows-default-app.webp").default}
|
||||
width="50%"
|
||||
className="screenshot"
|
||||
/>
|
||||
</div>
|
||||
<br />
|
||||
```
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"docs": [
|
||||
{
|
||||
"type": "autogenerated",
|
||||
"dirName": "."
|
||||
},
|
||||
{
|
||||
"type": "link",
|
||||
"label": "Contributing",
|
||||
"href": "/community-guide#ways-of-contributing"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
["v2.8.0","v2.7.0"]
|
||||
["v2.8.1","v2.8.0"]
|
||||
Loading…
Add table
Add a link
Reference in a new issue