Compare commits

...

40 Commits

Author SHA1 Message Date
Lea Anthony
c13257b9e9 [v2] v2.0.0-alpha.66 2021-06-05 14:37:12 +10:00
Lea Anthony
3f773f80ac [linux] Fix header signatures 2021-06-05 14:22:37 +10:00
Lea Anthony
5b23122b35 [v2] Make user + email discovery optional 2021-06-05 14:18:42 +10:00
Lea Anthony
d5cbfa6749 [linux] Support wails build and wails dev 2021-06-04 20:36:56 +10:00
Lea Anthony
3ad92192a9 [linux] Add linux runtime to wails dev 2021-06-04 20:34:55 +10:00
Lea Anthony
466676d99f [linux] Create Linux runtime 2021-06-04 20:32:40 +10:00
Lea Anthony
a1d5412465 [v2] Remove redundant apps package 2021-06-03 21:32:19 +10:00
Lea Anthony
9fdd5148ca [mac] Update runtime to use window.wailsInvoke 2021-06-03 21:01:14 +10:00
Lea Anthony
ac957b27cb [v1] Upgrade vanilla template to use runtime v1.3.19 2021-06-03 21:00:13 +10:00
Lea Anthony
20bc332720 [v1] Fix vanilla template package-lock.json 2021-06-03 20:33:25 +10:00
Lea Anthony
d2507660c2 [linux] Get CLI working. yum->dnf. doctor improvements. 2021-06-02 20:02:45 +10:00
Lea Anthony
64264c6378 [v2] Add README to vanilla template 2021-06-01 21:40:35 +10:00
Lea Anthony
ddadcdc18f [v2] Rebuild runtime 2021-05-31 20:09:04 +10:00
Lea Anthony
4738a0e0a8 [v2] Remove common.js 2021-05-31 20:08:11 +10:00
Lea Anthony
d2e4a0b0d2 [windows] Support wails dev 2021-05-31 20:01:40 +10:00
Lea Anthony
9f365ed85e [windows] Support rollup in vanilla template 2021-05-30 20:05:07 +10:00
Lea Anthony
5e733657c2 [v2] Updated runtime 2021-05-30 20:03:28 +10:00
Lea Anthony
93d9b61366 [windows] Fix bridge payload for 'wails dev' 2021-05-30 20:03:01 +10:00
Lea Anthony
b5d289bda9 [v2] Published @wails/runtime v1.3.14 2021-05-30 11:24:15 +10:00
Lea Anthony
319b7a3755 [v2] Change import to require for bridge for compatibility reasons 2021-05-30 11:22:40 +10:00
Lea Anthony
410d23b4d9 [windows] wails doctor docker support Better output 2021-05-30 11:06:38 +10:00
Lea Anthony
003e505c4a [mac] detect upx 2021-05-30 10:19:27 +10:00
Lea Anthony
22f09772d3 [mac] better wails doctor 2021-05-30 10:18:36 +10:00
Lea Anthony
a300172adc [windows] Better wails doctor installation details 2021-05-30 09:41:47 +10:00
Lea Anthony
1eba408f64 [windows] Better wails doctor diagnostics 2021-05-30 09:34:07 +10:00
Lea Anthony
be39b293b5 [mac] better wails doctor 2021-05-26 21:18:52 +10:00
Travis McLane
31cf04a944 fix shadowed err (#718) 2021-05-19 05:55:05 +10:00
Lea Anthony
f5912d29b6 Updated README.md 2021-05-18 21:29:03 +10:00
Lea Anthony
caad3a6b00 [windows] add icon to main window 2021-05-18 21:25:34 +10:00
Lea Anthony
08f4476087 Support for upx and more go:embed. 2021-05-18 21:25:16 +10:00
Lea Anthony
46ea3e6074 Better handling of process in wails dev 2021-05-18 21:22:52 +10:00
Lea Anthony
8be2a39daf [windows] Generate syso file for windows builds 2021-05-17 19:51:43 +10:00
Lea Anthony
7591b45ffa [windows] fix for no windows config 2021-05-17 19:50:12 +10:00
Travis McLane
f5056e7232 hack: enable builds on non-Windows 2021-05-16 13:51:14 +10:00
Alexander Hudek
101d344303 Merge pull request #715
* Fixed multi-line tags being minified incorrectly. Fixed self closing …

* Improved html whitespace minification fix.
2021-05-16 13:22:44 +10:00
Lea Anthony
6ab1a4adb0 Support passing arguments when using wails dev 2021-05-14 14:22:25 +10:00
Lea Anthony
5a30425091 [windows] Fix broken WebView2Loader.dll 2021-05-14 09:09:52 +10:00
Lea Anthony
e9deb248f9 Move assets -> build dir. Bundle assets in CLI binary. 2021-05-13 20:12:19 +10:00
Lea Anthony
7d0ff8b1a2 [windows] Updated webview.dll 2021-05-13 20:03:39 +10:00
Alexander Hudek
8399cc1e57 Fix width and height being set to zero when no max width and max height is set. (#709) 2021-05-13 18:49:53 +10:00
109 changed files with 4489 additions and 1394 deletions

2
.gitignore vendored
View File

@@ -28,4 +28,6 @@ v2/test/kitchensink/frontend/public
v2/test/kitchensink/build/darwin/desktop/kitchensink
v2/test/kitchensink/frontend/package.json.md5
/v2/internal/ffenestri/windows/test/cmake-build-debug/
!v2/internal/ffenestri/windows/x64/webview2.dll
!v2/internal/ffenestri/windows/x64/WebView2Loader.dll
.idea/

View File

@@ -1,13 +0,0 @@
{
"files.associations": {
"ios": "c",
"typeinfo": "c",
"sstream": "c",
"__functional_03": "c",
"functional": "c",
"__locale": "c",
"locale": "c",
"chrono": "c",
"system_error": "c"
}
}

View File

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

View File

@@ -36,7 +36,10 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
command.StringFlag("compiler", "Use a different go compiler to build, eg go1.15beta1", &compilerCommand)
compress := false
command.BoolFlag("compress", "Compress final binary", &compress)
command.BoolFlag("upx", "Compress final binary with UPX (if installed)", &compress)
compressFlags := ""
command.StringFlag("upxflags", "Flags to pass to upx", &compressFlags)
// Setup Platform flag
platform := runtime.GOOS
@@ -95,6 +98,7 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
"darwin/amd64",
"darwin/arm64",
"darwin/universal",
"linux",
//"linux/amd64",
//"linux/arm-7",
"windows",
@@ -131,6 +135,7 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
KeepAssets: keepAssets,
Verbosity: verbosity,
Compress: compress,
CompressFlags: compressFlags,
UserTags: userTags,
}

View File

@@ -0,0 +1,22 @@
# Dev
The dev command allows you to develop your application through a standard browser.
## Usage
`wails dev <flags>`
### Flags
| Flag | Details | Default |
| :------------- | :----------- | :------ |
| -compiler path/to/compiler | Use a different go compiler, eg go1.15beta1 | go |
| -ldflags "custom ld flags" | Use given ldflags | |
| -e list,of,extensions | File extensions to trigger rebuilds | go |
| -w | Show warnings | false |
| -v int | Verbosity level (0 - silent, 1 - default, 2 - verbose) | 1 |
| -loglevel | Loglevel to pass to the application - Trace, Debug, Info, Warning, Error | Debug |
## How it works
The project is built using a special mode that starts a webserver and starts listening to port 34115. When the frontend project is run independently, so long as the JS is wrapped with the runtime method `ready`, then the frontend will connect to the backend code via websockets. The interface should be present in your browser, and you should be able to interact with the backend as you would in a desktop app.

View File

@@ -3,6 +3,7 @@ package dev
import (
"fmt"
"io"
"log"
"os"
"os/signal"
"path/filepath"
@@ -57,6 +58,10 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
showWarnings := false
command.BoolFlag("w", "Show warnings", &showWarnings)
// Verbosity
verbosity := 1
command.IntFlag("v", "Verbosity level (0 - silent, 1 - default, 2 - verbose)", &verbosity)
loglevel := ""
command.StringFlag("loglevel", "Loglevel to use - Trace, Debug, Info, Warning, Error", &loglevel)
@@ -72,7 +77,12 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
if err != nil {
return err
}
defer watcher.Close()
defer func(watcher *fsnotify.Watcher) {
err := watcher.Close()
if err != nil {
log.Fatal(err)
}
}(watcher)
var debugBinaryProcess *process.Process = nil
var extensionsThatTriggerARebuild = strings.Split(extensions, ",")
@@ -83,15 +93,22 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
debounceQuit := make(chan bool, 1)
var passthruArgs []string
//if len(os.Args) > 2 {
// passthruArgs = os.Args[2:]
//}
// Do initial build
logger.Println("Building application for development...")
newProcess, err := restartApp(logger, "dev", ldflags, compilerCommand, debugBinaryProcess, loglevel)
newProcess, appBinary, err := restartApp(logger, ldflags, compilerCommand, debugBinaryProcess, loglevel, passthruArgs, verbosity)
if newProcess != nil {
debugBinaryProcess = newProcess
}
if err != nil {
return err
}
var newBinaryProcess *process.Process
go debounce(100*time.Millisecond, watcher.Events, debounceQuit, func(event fsnotify.Event) {
// logger.Println("event: %+v", event)
@@ -135,7 +152,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
// Do a rebuild
// Try and build the app
newBinaryProcess, err := restartApp(logger, "dev", ldflags, compilerCommand, debugBinaryProcess, loglevel)
newBinaryProcess, _, err = restartApp(logger, ldflags, compilerCommand, debugBinaryProcess, loglevel, passthruArgs, verbosity)
if err != nil {
fmt.Printf("Error during build: %s", err.Error())
return
@@ -197,6 +214,12 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
}
}
// Remove dev binary
err = os.Remove(appBinary)
if err != nil {
return err
}
LogGreen("Development mode exited")
return nil
@@ -224,14 +247,14 @@ exit:
}
}
func restartApp(logger *clilogger.CLILogger, outputType string, ldflags string, compilerCommand string, debugBinaryProcess *process.Process, loglevel string) (*process.Process, error) {
func restartApp(logger *clilogger.CLILogger, ldflags string, compilerCommand string, debugBinaryProcess *process.Process, loglevel string, passthruArgs []string, verbosity int) (*process.Process, string, error) {
appBinary, err := buildApp(logger, outputType, ldflags, compilerCommand)
appBinary, err := buildApp(logger, ldflags, compilerCommand, verbosity)
println()
if err != nil {
LogRed("Build error - continuing to run current version")
LogDarkYellow(err.Error())
return nil, nil
return nil, "", nil
}
// Kill existing binary if need be
@@ -247,8 +270,12 @@ func restartApp(logger *clilogger.CLILogger, outputType string, ldflags string,
// TODO: Generate `backend.js`
// Start up new binary
newProcess := process.NewProcess(logger, appBinary, "-loglevel", loglevel)
// Start up new binary with correct args
var args = []string{"-loglevel", loglevel}
if len(passthruArgs) > 0 {
args = append(args, passthruArgs...)
}
newProcess := process.NewProcess(logger, appBinary, args...)
err = newProcess.Start()
if err != nil {
// Remove binary
@@ -259,18 +286,21 @@ func restartApp(logger *clilogger.CLILogger, outputType string, ldflags string,
logger.Fatal("Unable to start application: %s", err.Error())
}
return newProcess, nil
return newProcess, appBinary, nil
}
func buildApp(logger *clilogger.CLILogger, outputType string, ldflags string, compilerCommand string) (string, error) {
func buildApp(logger *clilogger.CLILogger, ldflags string, compilerCommand string, verbosity int) (string, error) {
// Create random output file
outputFile := fmt.Sprintf("dev-%d", time.Now().Unix())
outputFile := "wailsdev"
if runtime.GOOS == "windows" {
outputFile += ".exe"
}
// Create BuildOptions
buildOptions := &build.Options{
Logger: logger,
OutputType: outputType,
OutputType: "dev",
Mode: build.Debug,
Pack: false,
Platform: runtime.GOOS,
@@ -278,6 +308,7 @@ func buildApp(logger *clilogger.CLILogger, outputType string, ldflags string, co
Compiler: compilerCommand,
OutputFile: outputFile,
IgnoreFrontend: true,
Verbosity: verbosity,
}
return build.Build(buildOptions)

View File

@@ -3,7 +3,6 @@ package doctor
import (
"fmt"
"io"
"log"
"os"
"runtime"
"strings"
@@ -25,11 +24,13 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
logger := clilogger.New(w)
app.PrintBanner()
logger.Print("Scanning system - please wait...")
logger.Print("Scanning system - Please wait (this may take a long time)...")
// Get system info
info, err := system.GetInfo()
if err != nil {
logger.Println("Failed.")
return err
}
logger.Println("Done.")
@@ -39,25 +40,22 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
w.Init(os.Stdout, 8, 8, 0, '\t', 0)
// Write out the system information
fmt.Fprintf(w, "\n")
fmt.Fprintf(w, "System\n")
fmt.Fprintf(w, "------\n")
fmt.Fprintf(w, "%s\t%s\n", "OS:", info.OS.Name)
fmt.Fprintf(w, "%s\t%s\n", "Version: ", info.OS.Version)
fmt.Fprintf(w, "%s\t%s\n", "ID:", info.OS.ID)
// Exit early if PM not found
if info.PM == nil {
w.Flush()
return nil
}
fmt.Fprintf(w, "%s\t%s\n", "Package Manager: ", info.PM.Name())
// Output Go Information
fmt.Fprintf(w, "%s\t%s\n", "Go Version:", runtime.Version())
fmt.Fprintf(w, "%s\t%s\n", "Platform:", runtime.GOOS)
fmt.Fprintf(w, "%s\t%s\n", "Architecture:", runtime.GOARCH)
// Exit early if PM not found
if info.PM != nil {
fmt.Fprintf(w, "%s\t%s\n", "Package Manager: ", info.PM.Name())
}
// Output Dependencies Status
var dependenciesMissing = []string{}
var externalPackages = []*packagemanager.Dependancy{}
@@ -67,12 +65,14 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
fmt.Fprintf(w, "Dependency\tPackage Name\tStatus\tVersion\n")
fmt.Fprintf(w, "----------\t------------\t------\t-------\n")
hasOptionalDependencies := false
// Loop over dependencies
for _, dependency := range info.Dependencies {
name := dependency.Name
if dependency.Optional {
name += "*"
name = "*" + name
hasOptionalDependencies = true
}
packageName := "Unknown"
status := "Not Found"
@@ -107,44 +107,48 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", name, packageName, status, dependency.Version)
}
fmt.Fprintf(w, "\n")
fmt.Fprintf(w, "* - Optional Dependency\n")
if hasOptionalDependencies {
fmt.Fprintf(w, "\n")
fmt.Fprintf(w, "* - Optional Dependency\n")
}
w.Flush()
logger.Println("")
logger.Println("Diagnosis")
logger.Println("---------\n")
logger.Println("---------")
// Generate an appropriate diagnosis
if len(dependenciesMissing) == 0 && dependenciesAvailableRequired == 0 {
logger.Println("Your system is ready for Wails development!")
} else {
logger.Println("Your system has missing dependencies!\n")
}
if dependenciesAvailableRequired != 0 {
log.Println("Install required packages using: " + info.Dependencies.InstallAllRequiredCommand())
logger.Println("Required package(s) installation details: \n" + info.Dependencies.InstallAllRequiredCommand())
}
if dependenciesAvailableOptional != 0 {
log.Println("Install optional packages using: " + info.Dependencies.InstallAllOptionalCommand())
}
if len(externalPackages) > 0 {
for _, p := range externalPackages {
if p.Optional {
print("[Optional] ")
}
log.Println("Install " + p.Name + ": " + p.InstallCommand)
}
logger.Println("Optional package(s) installation details: \n" + info.Dependencies.InstallAllOptionalCommand())
}
//
//if len(externalPackages) > 0 {
// for _, p := range externalPackages {
// if p.Optional {
// print("[Optional] ")
// }
// logger.Println("Install " + p.Name + ": " + p.InstallCommand)
// }
//}
if len(dependenciesMissing) != 0 {
// TODO: Check if apps are available locally and if so, adjust the diagnosis
log.Println("Fatal:")
log.Println("Required dependencies missing: " + strings.Join(dependenciesMissing, " "))
log.Println("Please read this article on how to resolve this: https://wails.app/guides/resolving-missing-packages")
logger.Println("Fatal:")
logger.Println("Required dependencies missing: " + strings.Join(dependenciesMissing, " "))
logger.Println("Please read this article on how to resolve this: https://wails.app/guides/resolving-missing-packages")
}
log.Println("")
logger.Println("")
return nil
})

View File

@@ -2,6 +2,7 @@ package initialise
import (
"fmt"
"github.com/wailsapp/wails/v2/pkg/buildassets"
"io"
"strings"
"time"
@@ -40,7 +41,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
// Quiet Init
quiet := false
command.BoolFlag("q", "Supress output to console", &quiet)
command.BoolFlag("q", "Suppress output to console", &quiet)
initGit := false
gitInstalled := git.IsInstalled()
@@ -106,10 +107,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
}
// Try to discover author details from git config
err := findAuthorDetails(options)
if err != nil {
return err
}
findAuthorDetails(options)
return initProject(options)
})
@@ -129,6 +127,12 @@ func initProject(options *templates.Options) error {
return err
}
// Install the default assets
err = buildassets.Install(options.TargetDir, options.ProjectName)
if err != nil {
return err
}
if options.InitGit {
err = initGit(options)
if err != nil {
@@ -164,20 +168,18 @@ func initGit(options *templates.Options) error {
return nil
}
func findAuthorDetails(options *templates.Options) error {
// findAuthorDetails tries to find the user's name and email
// from gitconfig. If it finds them, it stores them in the project options
func findAuthorDetails(options *templates.Options) {
if git.IsInstalled() {
name, err := git.Name()
if err != nil {
return err
if err == nil {
options.AuthorName = strings.TrimSpace(name)
}
options.AuthorName = strings.TrimSpace(name)
email, err := git.Email()
if err != nil {
return err
if err == nil {
options.AuthorEmail = strings.TrimSpace(email)
}
options.AuthorEmail = strings.TrimSpace(email)
}
return nil
}

View File

@@ -0,0 +1,16 @@
# README
## About
This template uses vanilla JS / HTML and CSS. [Rollup](https://rollupjs.org/guide/en/) is used for processing and bundling the files.
## Building
To build this project in debug mode, use `wails build`. For production, use `wails build -production`.
To generate a platform native package, add the `-package` flag.
## Live Development
To run in live development mode, run `wails dev` in the project directory. In another terminal, go into the `frontend`
directory and run `npm run dev`. The frontend dev server will run on http://localhost:5000. Connect to this
in your browser and connect to your application.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
{
"name": "vanilla",
"version": "1.0.0",
"description": "Vanilla Wails v2 template",
"main": "src/main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "rollup -c",
"dev": "rollup -c -w",
"start": "sirv dist"
},
"author": "{{.AuthorName}}",
"license": "ISC",
"dependencies": {
"@rollup/plugin-commonjs": "^19.0.0",
"@rollup/plugin-image": "^2.0.6",
"@rollup/plugin-node-resolve": "^13.0.0",
"@rollup/plugin-url": "^6.0.0",
"@wails/runtime": "^1.3.19",
"rollup": "^2.50.4",
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-livereload": "^2.0.0",
"rollup-plugin-postcss": "^4.0.0",
"rollup-plugin-terser": "^7.0.2",
"sirv-cli": "^1.0.12"
}
}

View File

@@ -0,0 +1,103 @@
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
import postcss from 'rollup-plugin-postcss';
import image from '@rollup/plugin-image';
import url from '@rollup/plugin-url';
import copy from 'rollup-plugin-copy';
const production = !process.env.ROLLUP_WATCH;
export default {
input: 'src/main.js',
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: 'dist/main.js'
},
onwarn: handleRollupWarning,
plugins: [
image(),
copy({
targets: [
{ src: 'src/index.html', dest: 'dist' },
{ src: 'src/main.css', dest: 'dist' },
]
}),
// Embed binary files
url({
include: ['**/*.woff', '**/*.woff2'],
limit: Infinity,
}),
// If you have external dependencies installed from
// npm, you'll most likely need these plugins. In
// some cases you'll need additional configuration -
// consult the documentation for details:
// https://github.com/rollup/plugins/tree/master/packages/commonjs
resolve({
browser: true,
}),
commonjs(),
// PostCSS preprocessing
postcss({
extensions: ['.css', '.scss'],
extract: true,
minimize: false,
use: [
['sass', {
includePaths: [
'./src',
'./node_modules'
]
}]
],
}),
// In dev mode, call `npm run start` once
// the bundle has been generated
!production && serve(),
// Watch the `public` directory and refresh the
// browser on changes when not in production
!production && livereload('dist'),
// If we're building for production (npm run build
// instead of npm run dev), minify
production && terser()
],
watch: {
clearScreen: false
}
};
function handleRollupWarning(warning) {
console.error('ERROR: ' + warning.toString());
}
function serve() {
let server;
function toExit() {
if (server) server.kill(0);
}
return {
writeBundle() {
if (server) return;
server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
stdio: ['ignore', 'inherit', 'inherit'],
shell: true
});
process.on('SIGTERM', toExit);
process.on('exit', toExit);
}
};
}

View File

@@ -1,16 +1,21 @@
// Get input + focus
let nameElement = document.getElementById("name");
nameElement.focus();
// Setup the greet function
window.greet = function () {
import {ready} from '@wails/runtime';
// Get name
let name = nameElement.value;
ready( () => {
// Get input + focus
let nameElement = document.getElementById("name");
nameElement.focus();
// Call Basic.Greet(name)
window.backend.main.Basic.Greet(name).then((result) => {
// Update result with data back from Basic.Greet()
document.getElementById("result").innerText = result;
});
}
// Setup the greet function
window.greet = function () {
// Get name
let name = nameElement.value;
// Call Basic.Greet(name)
window.backend.main.Basic.Greet(name).then((result) => {
// Update result with data back from Basic.Greet()
document.getElementById("result").innerText = result;
});
};
});

View File

@@ -1,7 +1,9 @@
{
"name": "{{.ProjectName}}",
"outputfilename": "{{.BinaryName}}",
"html": "frontend/src/index.html",
"html": "frontend/dist/index.html",
"frontend:build": "npm run build",
"frontend:install": "npm ci",
"author": {
"name": "{{.AuthorName}}",
"email": "{{.AuthorEmail}}"

View File

@@ -1,3 +1,3 @@
package main
var version = "v2.0.0-alpha.65"
var version = "v2.0.0-alpha.66"

View File

@@ -10,10 +10,11 @@ require (
github.com/imdario/mergo v0.3.11
github.com/jackmordaunt/icns v1.0.0
github.com/leaanthony/clir v1.0.4
github.com/leaanthony/debme v1.1.2
github.com/leaanthony/debme v1.2.0
github.com/leaanthony/go-ansi-parser v1.0.1
github.com/leaanthony/gosod v1.0.1
github.com/leaanthony/slicer v1.5.0
github.com/leaanthony/winicon v0.0.0-20200606125418-4419cea822a0
github.com/matryer/is v1.4.0
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/olekukonko/tablewriter v0.0.4

View File

@@ -42,14 +42,16 @@ github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs
github.com/leaanthony/clir v1.0.4 h1:Dov2y9zWJmZr7CjaCe86lKa4b5CSxskGAt2yBkoDyiU=
github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0=
github.com/leaanthony/debme v1.1.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA=
github.com/leaanthony/debme v1.1.2 h1:dGeQuj0+xPIlDQzGIjmAU52+yRg85u5pWaaqrdLBjD0=
github.com/leaanthony/debme v1.1.2/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA=
github.com/leaanthony/debme v1.2.0 h1:i7JUQhuv7PtJ/7qV+SIa5QARTGBcojUZ+2eCiV9begU=
github.com/leaanthony/debme v1.2.0/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA=
github.com/leaanthony/go-ansi-parser v1.0.1 h1:97v6c5kYppVsbScf4r/VZdXyQ21KQIfeQOk2DgKxGG4=
github.com/leaanthony/go-ansi-parser v1.0.1/go.mod h1:7arTzgVI47srICYhvgUV4CGd063sGEeoSlych5yeSPM=
github.com/leaanthony/gosod v1.0.1 h1:F+4c3DmEBfigi7oAswCV2RpQ+k4DcNbhuCZUGdBHacQ=
github.com/leaanthony/gosod v1.0.1/go.mod h1:W8RyeSFBXu7RpIxPGEJfW4moSyGGEjlJMLV25wEbAdU=
github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0HtY=
github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
github.com/leaanthony/winicon v0.0.0-20200606125418-4419cea822a0 h1:FPGYnfxuuxqCZhrGq8nKjthEcYHgHmFbyY953Xv9cNI=
github.com/leaanthony/winicon v0.0.0-20200606125418-4419cea822a0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
@@ -92,6 +94,8 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw=
golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=

View File

@@ -79,7 +79,7 @@ func (a *App) Run() error {
// Default app options
var port = 8080
var ip = "localhost"
var supressLogging = false
var SuppressLogging = false
var debugMode = false
// Create CLI
@@ -89,7 +89,7 @@ func (a *App) Run() error {
cli.IntFlag("p", "Port to serve on", &port)
cli.StringFlag("i", "IP to serve on", &ip)
cli.BoolFlag("d", "Debug mode", &debugMode)
cli.BoolFlag("q", "Supress logging", &supressLogging)
cli.BoolFlag("q", "Suppress logging", &SuppressLogging)
// Setup main action
cli.Action(func() error {
@@ -98,8 +98,8 @@ func (a *App) Run() error {
a.webserver.SetPort(port)
a.webserver.SetIP(ip)
a.webserver.SetBindings(a.bindings)
// Log information (if we aren't supressing it)
if !supressLogging {
// Log information (if we aren't Suppressing it)
if !SuppressLogging {
cli.PrintBanner()
a.logger.Info("Running server at %s", a.webserver.URL())
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -18,6 +18,12 @@ import (
//go:embed darwin.js
var darwinRuntime string
//go:embed windows.js
var windowsRuntime string
//go:embed linux.js
var linuxRuntime string
// session represents a single websocket session
type session struct {
bindings string
@@ -84,6 +90,10 @@ func (s *session) start(firstSession bool) {
switch runtime.GOOS {
case "darwin":
wailsRuntime = darwinRuntime
case "windows":
wailsRuntime = windowsRuntime
case "linux":
wailsRuntime = linuxRuntime
default:
log.Fatal("platform not supported")
}
@@ -92,7 +102,10 @@ func (s *session) start(firstSession bool) {
s.log.Info(bindingsMessage)
bootstrapMessage := bindingsMessage + wailsRuntime
s.sendMessage("b" + bootstrapMessage)
err := s.sendMessage("b" + bootstrapMessage)
if err != nil {
s.log.Error(err.Error())
}
// Send menus
traymenus, err := s.menumanager.GetTrayMenus()
@@ -101,7 +114,10 @@ func (s *session) start(firstSession bool) {
}
for _, trayMenu := range traymenus {
s.sendMessage("TS" + trayMenu)
err := s.sendMessage("TS" + trayMenu)
if err != nil {
s.log.Error(err.Error())
}
}
for {
@@ -130,7 +146,10 @@ func (s *session) start(firstSession bool) {
// Shutdown
func (s *session) Shutdown() {
s.conn.Close()
err := s.conn.Close()
if err != nil {
s.log.Error(err.Error())
}
s.done = true
s.log.Info("session %v exit", s.Identifier())
}
@@ -146,10 +165,16 @@ func (s *session) writePump() {
s.Shutdown()
return
case msg, ok := <-s.writeChan:
s.conn.SetWriteDeadline(time.Now().Add(1 * time.Second))
err := s.conn.SetWriteDeadline(time.Now().Add(1 * time.Second))
if err != nil {
s.log.Error(err.Error())
}
if !ok {
s.log.Debug("writeChan was closed!")
s.conn.WriteMessage(websocket.CloseMessage, []byte{})
err := s.conn.WriteMessage(websocket.CloseMessage, []byte{})
if err != nil {
s.log.Error(err.Error())
}
return
}

File diff suppressed because one or more lines are too long

View File

@@ -983,7 +983,7 @@ void SaveDialog(struct Application *app, char *callbackID, char *title, char *fi
);
}
const char *invoke = "window.external={invoke:function(x){window.webkit.messageHandlers.external.postMessage(x);}};";
const char *invoke = "window.wailsInvoke=function(message){window.webkit.messageHandlers.external.postMessage(message);};window.wailsDrag=function(message){window.webkit.messageHandlers.windowDrag.postMessage(message);};window.wailsContextMenuMessage=function(message){window.webkit.messageHandlers.contextMenu.postMessage(message);};";
// DisableFrame disables the window frame
void DisableFrame(struct Application *app)

View File

@@ -2,6 +2,7 @@
#ifndef __FFENESTRI_LINUX_H__
#define __FFENESTRI_LINUX_H__
#include "common.h"
#include "gtk/gtk.h"
#include "webkit2/webkit2.h"
#include <time.h>
@@ -11,9 +12,10 @@
#include <stdarg.h>
// References to assets
extern const unsigned char *assets[];
extern const unsigned char runtime;
extern const char *icon[];
#include "icon.h"
#include "assets.h"
// Constants
#define PRIMARY_MOUSE_BUTTON 1
@@ -23,17 +25,6 @@ extern const char *icon[];
// MAIN DEBUG FLAG
int debug;
// Credit: https://stackoverflow.com/a/8465083
char *concat(const char *s1, const char *s2)
{
const size_t len1 = strlen(s1);
const size_t len2 = strlen(s2);
char *result = malloc(len1 + len2 + 1);
memcpy(result, s1, len1);
memcpy(result + len1, s2, len2 + 1);
return result;
}
// Debug works like sprintf but mutes if the global debug flag is true
// Credit: https://stackoverflow.com/a/20639708
void Debug(char *message, ...)
@@ -312,17 +303,17 @@ void SetMaxWindowSize(struct Application *app, int maxWidth, int maxHeight)
}
// SetColour sets the colour of the webview to the given colour string
int SetColour(struct Application *app, const char *colourString)
void SetColour(struct Application *app, int red, int green, int blue, int alpha)
{
GdkRGBA rgba;
gboolean result = gdk_rgba_parse(&rgba, colourString);
if (result == FALSE)
{
return 0;
}
// Debug("Setting webview colour to: %s", colourString);
webkit_web_view_get_background_color((WebKitWebView *)(app->webView), &rgba);
return 1;
// GdkRGBA rgba;
// rgba.
// gboolean result = gdk_rgba_parse(&rgba, colourString);
// if (result == FALSE)
// {
// return 0;
// }
// // Debug("Setting webview colour to: %s", colourString);
// webkit_web_view_get_background_color((WebKitWebView *)(app->webView), &rgba);
}
// DisableFrame disables the window frame
@@ -523,6 +514,11 @@ static void load_finished_cb(WebKitWebView *webView,
Debug("Binding Methods");
syncEval(app, app->bindings);
// Setup IPC commands
Debug("Setting up IPC methods");
const char *invoke = "window.wailsInvoke=function(message){window.webkit.messageHandlers.external.postMessage(message);};window.wailsDrag=function(message){window.webkit.messageHandlers.windowDrag.postMessage(message);};window.wailsContextMenuMessage=function(message){window.webkit.messageHandlers.contextMenu.postMessage(message);};";
syncEval(app, invoke);
// Runtime
Debug("Setting up Wails runtime");
syncEval(app, &runtime);
@@ -824,7 +820,7 @@ void Show(struct Application *app) {
// maximiseInternal maximises the main window
void maximiseInternal(struct Application *app) {
gtk_window_maximize(GTK_WIDGET(app->mainWindow));
gtk_window_maximize(GTK_WINDOW(app->mainWindow));
}
// Maximise places the maximiseInternal method onto the main thread for execution
@@ -841,7 +837,7 @@ void Maximise(struct Application *app) {
// unmaximiseInternal unmaximises the main window
void unmaximiseInternal(struct Application *app) {
gtk_window_unmaximize(GTK_WIDGET(app->mainWindow));
gtk_window_unmaximize(GTK_WINDOW(app->mainWindow));
}
// Unmaximise places the unmaximiseInternal method onto the main thread for execution
@@ -857,6 +853,21 @@ void Unmaximise(struct Application *app) {
}
void DarkModeEnabled(struct Application* app, char *callbackID) {}
void SetApplicationMenu(struct Application* app, const char *menuJSON) {}
void AddTrayMenu(struct Application* app, const char *menuTrayJSON) {}
void SetTrayMenu(struct Application* app, const char *menuTrayJSON) {}
void DeleteTrayMenuByID(struct Application* app, const char *id) {}
void UpdateTrayMenuLabel(struct Application* app, const char* JSON) {}
void AddContextMenu(struct Application* app, char *contextMenuJSON) {}
void UpdateContextMenu(struct Application* app, char *contextMenuJSON) {}
void WebviewIsTransparent(struct Application* app) {}
void WindowBackgroundIsTranslucent(struct Application* app) {}
void OpenDialog(struct Application* app, char *callbackID, char *title, char *filters, char *defaultFilename, char *defaultDir, int allowFiles, int allowDirs, int allowMultiple, int showHiddenFiles, int canCreateDirectories, int resolvesAliases, int treatPackagesAsDirectories) {}
void SaveDialog(struct Application* app, char *callbackID, char *title, char *filters, char *defaultFilename, char *defaultDir, int showHiddenFiles, int canCreateDirectories, int treatPackagesAsDirectories) {}
void MessageDialog(struct Application* app, char *callbackID, char *type, char *title, char *message, char *icon, char *button1, char *button2, char *button3, char *button4, char *defaultButton, char *cancelButton) {}
// minimiseInternal minimises the main window
void minimiseInternal(struct Application *app) {
gtk_window_iconify(app->mainWindow);

View File

@@ -0,0 +1,17 @@
package ffenestri
/*
#cgo linux CFLAGS: -DFFENESTRI_LINUX=1
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0
#include "ffenestri.h"
#include "ffenestri_linux.h"
*/
import "C"
func (a *Application) processPlatformSettings() error {
return nil
}

View File

@@ -0,0 +1,6 @@
#ifndef FFENESTRI_LINUX_H
#define FFENESTRI_LINUX_H
#endif

View File

@@ -195,8 +195,8 @@ void execJS(struct Application* app, const char *script) {
void loadAssets(struct Application* app) {
// patch window.external.invoke
std::string initialCode = std::string("window.external={invoke:s=>window.chrome.webview.postMessage(s)};");
// setup window.wailsInvoke
std::string initialCode = std::string("window.wailsInvoke=function(m){window.chrome.webview.postMessage(m)};");
// Load bindings
initialCode += std::string(app->bindings);
@@ -224,7 +224,7 @@ void loadAssets(struct Application* app) {
initialCode += std::string("wails._.DisableDefaultContextMenu();");
}
initialCode += std::string("window.external.invoke('completed');");
initialCode += std::string("window.wailsInvoke('completed');");
// Keep a copy of the code
app->initialCode = new char[initialCode.length()+1];
@@ -304,8 +304,8 @@ bool initWebView2(struct Application *app, int debugEnabled, messageCallback cb)
GetClientRect(app->window, &bounds);
app->webviewController->put_Bounds(bounds);
// Callback hack
app->webview->AddScriptToExecuteOnDocumentCreated(L"window.chrome.webview.postMessage('I');", nullptr);
// Let the backend know we have initialised
app->webview->AddScriptToExecuteOnDocumentCreated(L"window.chrome.webview.postMessage('initialised');", nullptr);
// Load the HTML
LPCWSTR html = (LPCWSTR) cstrToLPWSTR((char*)assets[0]);
app->webview->Navigate(html);
@@ -328,6 +328,8 @@ void Run(struct Application* app, int argc, char **argv) {
wc.hInstance = hInstance;
wc.lpszClassName = (LPCWSTR)"ffenestri";
wc.lpfnWndProc = WndProc;
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(100));
wc.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(100));
// TODO: Menu
// wc.lpszMenuName = nullptr;

View File

@@ -15,6 +15,9 @@ import "C"
func (a *Application) processPlatformSettings() error {
config := a.config.Windows
if config == nil {
return nil
}
// Check if the webview should be transparent
if config.WebviewIsTransparent {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +1,6 @@
cmake_minimum_required(VERSION 3.19)
project(test C)
project(test)
set(CMAKE_C_STANDARD 99)
set(SOURCES ../../ffenestri_windows.cpp)
set(CMAKE_CXX_STANDARD 14)
add_executable(test ${SOURCES} main.c)
add_executable(test main.cpp)

View File

@@ -1 +0,0 @@
g++ main.c ..\..\ffenestri_windows.cpp -lgdi32 -std=c++11

Binary file not shown.

View File

@@ -1,3 +1,5 @@
// +build windows
package x64
import _ "embed"

View File

@@ -0,0 +1,9 @@
// +build !windows
// This is a stub to define the following even though they don't exist
// on non-Windows systems. Note: This is not the right way to handle this.
package x64
var WebView2 []byte
var WebView2Loader []byte

View File

@@ -66,21 +66,12 @@ class wv2ComHandler
completed(app);
return S_OK;
}
switch(m[0]) {
// Standard message for backend
case 'S':
printf("--> Message to backend: %s\n", &m[1]);
messageFromWindowCallback(&m[1]);
break;
// DOM Initialised
case 'I':
else if (strcmp(m, "initialised") == 0) {
loadAssets(app);
break;
default:
printf("----> Unknown message type: %c\n", m[0]);
return S_OK;
}
else {
messageFromWindowCallback(m);
}
delete[] m;
return S_OK;

View File

@@ -52,21 +52,13 @@ func (a *Asset) AsString() string {
return a.Data
}
// AsCHexData processes the asset data so it may be used by C
func (a *Asset) AsCHexData() string {
// This will be our final string to hexify
dataString := a.Data
func (a *Asset) minifiedData() (string, error) {
switch a.Type {
case AssetTypes.HTML:
// Escape HTML
var re = regexp.MustCompile(`\s{2,}`)
result := re.ReplaceAllString(a.Data, ``)
result = strings.ReplaceAll(result, "\n", "")
result = strings.ReplaceAll(result, "\r\n", "")
result = strings.ReplaceAll(result, "\n", "")
var re = regexp.MustCompile(`[\s]+`)
result := re.ReplaceAllString(a.Data, ` `)
// Inject wailsloader code
result = strings.Replace(result, `</body>`, `<script id='wailsloader'>window.wailsloader = { html: true, runtime: false, userjs: false, usercss: false };var self=document.querySelector('#wailsloader');self.parentNode.removeChild(self);</script></body>`, 1)
@@ -75,7 +67,7 @@ func (a *Asset) AsCHexData() string {
urlString := strings.ReplaceAll(url.String(), "/", "%2f")
// Save Data uRI string
dataString = "data:text/html;charset=utf-8," + urlString
return "data:text/html;charset=utf-8," + urlString, nil
case AssetTypes.CSS:
@@ -91,19 +83,28 @@ func (a *Asset) AsCHexData() string {
result = strings.ReplaceAll(result, `'`, `\'`)
result = strings.ReplaceAll(result, ` {`, `{`)
result = strings.ReplaceAll(result, `: `, `:`)
dataString = fmt.Sprintf("window.wails._.InjectCSS(\"%s\");", result)
return fmt.Sprintf("window.wails._.InjectCSS(\"%s\");", result), nil
case AssetTypes.JS:
m := minify.New()
m.AddFunc("application/javascript", js.Minify)
var err error
dataString, err = m.String("application/javascript", a.Data+";")
result, err := m.String("application/javascript", a.Data+";")
if err != nil {
log.Fatal(err)
return "", err
}
a.Data = dataString
return result, nil
default:
return "", fmt.Errorf("minification for asset type %s not implemented", a.Type)
}
}
// AsCHexData processes the asset data so it may be used by C
func (a *Asset) AsCHexData() string {
dataString, err := a.minifiedData()
if err != nil {
log.Fatal(err)
}
// Get byte data of the string
bytes := *(*[]byte)(unsafe.Pointer(&dataString))

View File

@@ -0,0 +1,53 @@
package html
import "testing"
func TestAsset_minifiedData(t *testing.T) {
type fields struct {
Type string
Path string
Data string
}
tests := []struct {
name string
fields fields
want string
wantErr bool
}{
{
name: "multi-line tag",
fields: fields{
Type: AssetTypes.HTML,
Path: "foo.html",
Data: "<link\n rel=\"stylesheet\"\n href=\"src/foo.css\"\n>\n",
},
want: "data:text/html;charset=utf-8,%3Clink%20rel=%22stylesheet%22%20href=%22src%2ffoo.css%22%20%3E%20",
},
{
name: "multi-line tag no spaces",
fields: fields{
Type: AssetTypes.HTML,
Path: "foo.html",
Data: "<link\nrel=\"stylesheet\"\nhref=\"src/foo.css\"\n>\n",
},
want: "data:text/html;charset=utf-8,%3Clink%20rel=%22stylesheet%22%20href=%22src%2ffoo.css%22%20%3E%20",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
a := &Asset{
Type: tt.fields.Type,
Path: tt.fields.Path,
Data: tt.fields.Data,
}
got, err := a.minifiedData()
if (err != nil) != tt.wantErr {
t.Errorf("Asset.minifiedData() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("Asset.minifiedData() = %v, want %v", got, tt.want)
}
})
}
}

View File

@@ -84,7 +84,7 @@ func (a *AssetBundle) processHTML(htmldata string) error {
}
//process the token according to the token type...
if tokenType == html.StartTagToken {
if tokenType == html.StartTagToken || tokenType == html.SelfClosingTagToken {
//get the token
token := tokenizer.Token()

View File

@@ -0,0 +1,73 @@
package html
import (
"testing"
)
func TestNewAssetBundle(t *testing.T) {
tests := []struct {
name string
pathToHTML string
wantAssets []string
wantErr bool
}{
{
name: "basic html",
pathToHTML: "testdata/basic.html",
wantAssets: []string{
AssetTypes.HTML,
AssetTypes.FAVICON,
AssetTypes.JS,
AssetTypes.CSS,
},
wantErr: false,
},
{
name: "self closing tags",
pathToHTML: "testdata/self_closing.html",
wantAssets: []string{
AssetTypes.HTML,
AssetTypes.FAVICON,
AssetTypes.JS,
AssetTypes.CSS,
},
wantErr: false,
},
{
name: "multi-line tags",
pathToHTML: "testdata/self_closing.html",
wantAssets: []string{
AssetTypes.HTML,
AssetTypes.FAVICON,
AssetTypes.JS,
AssetTypes.CSS,
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := NewAssetBundle(tt.pathToHTML)
if (err != nil) != tt.wantErr {
t.Errorf("NewAssetBundle() error = %v, wantErr %v", err, tt.wantErr)
return
}
if len(got.assets) != len(tt.wantAssets) {
t.Errorf("NewAssetBundle() len(assets) = %d, want %d",
len(got.assets), len(tt.wantAssets))
}
for i := range tt.wantAssets {
if i >= len(got.assets) {
t.Errorf("NewAssetBundle() missing assets[%d].Type = %s",
i, tt.wantAssets[i])
} else {
if got.assets[i].Type != tt.wantAssets[i] {
t.Errorf("NewAssetBundle() assets[%d].Type = %s, want %s",
i, got.assets[i].Type, tt.wantAssets[i])
}
}
}
})
}
}

14
v2/internal/html/testdata/basic.html vendored Normal file
View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg"></link>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script type="text/javascript" src="src/bundle.js"></script>
<link rel="stylesheet" href="src/style.css"></link>
<title>Vite App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>

View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script type="text/javascript" src="src/bundle.js"></script>
<link
rel="stylesheet"
href="src/style.css"
/>
<title>Vite App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>

View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script type="text/javascript" src="src/bundle.js"></script>
<link rel="stylesheet" href="src/style.css" />
<title>Vite App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>

View File

@@ -0,0 +1 @@
window.alert("I am JS!");

View File

@@ -0,0 +1,8 @@
<svg version="1.1"
baseProfile="full"
width="300" height="200"
xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" fill="blue" />
</svg>

After

Width:  |  Height:  |  Size: 172 B

View File

@@ -0,0 +1,3 @@
.body {
background: blue;
}

View File

@@ -39,12 +39,7 @@ func (p *Process) Start() error {
go func(cmd *exec.Cmd, running *bool, logger *clilogger.CLILogger, exitChannel chan bool) {
logger.Println("Starting process (PID: %d)", cmd.Process.Pid)
err := cmd.Wait()
if err != nil {
if err.Error() != "signal: killed" {
logger.Fatal("Fatal error from app: " + err.Error())
}
}
_ = cmd.Wait()
logger.Println("Exiting process (PID: %d)", cmd.Process.Pid)
*running = false
exitChannel <- true
@@ -59,6 +54,13 @@ func (p *Process) Kill() error {
return nil
}
err := p.cmd.Process.Kill()
if err != nil {
return err
}
err = p.cmd.Process.Release()
if err != nil {
return err
}
// Wait for command to exit properly
<-p.exitChannel

View File

@@ -25,8 +25,8 @@ type Project struct {
// The path to the project directory
Path string
// Assets directory
AssetsDir string `json:"assetsdir"`
// Build directory
BuildDir string `json:"builddir"`
// The output filename
OutputFilename string `json:"outputfilename"`
@@ -76,8 +76,8 @@ func Load(projectPath string) (*Project, error) {
}
// Set default assets directory if none given
if result.AssetsDir == "" {
result.AssetsDir = filepath.Join(result.Path, "assets")
if result.BuildDir == "" {
result.BuildDir = filepath.Join(result.Path, "build")
}
// Fix up OutputFilename

View File

@@ -0,0 +1,12 @@
package assets
import _ "embed"
//go:embed desktop_darwin.js
var desktopDarwinJS string
//go:embed desktop_windows.js
var desktopWindowsJS string
//go:embed wails.js
var wailsJS string

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -10,20 +10,6 @@ The lightweight framework for web-like apps
/* jshint esversion: 6 */
import { SetBindings } from './bindings';
import { Init } from './main';
import {RaiseError} from '../desktop/darwin';
// Setup global error handler
window.onerror = function (msg, url, lineNo, columnNo, error) {
const errorMessage = {
message: msg,
url: url,
line: lineNo,
column: columnNo,
error: JSON.stringify(error),
stack: function() { return JSON.stringify(new Error().stack); }(),
};
RaiseError(errorMessage);
};
// Initialise the Runtime
Init();

View File

@@ -15,7 +15,7 @@ import * as Dialog from './dialog';
import { On, Once, OnMultiple, Emit, Notify } from './events';
import { Callback, SystemCall } from './calls';
import { AddScript, InjectCSS, DisableDefaultContextMenu } from './utils';
import { AddIPCListener } from 'ipc';
import { AddIPCListener, SendMessage } from 'ipc';
import * as Platform from 'platform';
import * as Store from './store';
import * as Tray from './tray';
@@ -47,6 +47,7 @@ export function Init() {
// Init,
AddIPCListener,
SystemCall,
SendMessage,
},
Store,
};

View File

@@ -13,60 +13,53 @@ The lightweight framework for web-like apps
* Initialises platform specific code
*/
// import * as common from './common';
const common = require('./common');
export const System = {
...common,
Platform: () => "darwin",
}
AppType: 'desktop',
Platform: () => 'darwin',
};
export function SendMessage(message) {
window.webkit.messageHandlers.external.postMessage(message);
}
export function RaiseError(message) {
window.webkit.messageHandlers.error.postMessage(message);
window.wailsInvoke(message);
}
export function Init() {
// Setup drag handler
// Based on code from: https://github.com/patr0nus/DeskGap
window.addEventListener('mousedown', function (e) {
let currentElement = e.target;
while (currentElement != null) {
if (currentElement.hasAttribute('data-wails-no-drag')) {
break;
} else if (currentElement.hasAttribute('data-wails-drag')) {
window.webkit.messageHandlers.windowDrag.postMessage(null);
break;
}
currentElement = currentElement.parentElement;
}
});
// Setup drag handler
// Based on code from: https://github.com/patr0nus/DeskGap
window.addEventListener('mousedown', function (e) {
let currentElement = e.target;
while (currentElement != null) {
if (currentElement.hasAttribute('data-wails-no-drag')) {
break;
} else if (currentElement.hasAttribute('data-wails-drag')) {
window.wailsDrag(null);
break;
}
currentElement = currentElement.parentElement;
}
});
// Setup context menu hook
window.addEventListener('contextmenu', function (e) {
let currentElement = e.target;
let contextMenuId;
while (currentElement != null) {
contextMenuId = currentElement.dataset['wails-context-menu-id'];
if (contextMenuId != null) {
break;
}
currentElement = currentElement.parentElement;
}
if (contextMenuId != null || window.disableWailsDefaultContextMenu) {
e.preventDefault();
}
if( contextMenuId != null ) {
let contextData = currentElement.dataset['wails-context-menu-data'];
let message = {
id: contextMenuId,
data: contextData || "",
};
window.webkit.messageHandlers.contextMenu.postMessage(JSON.stringify(message));
}
});
// Setup context menu hook
window.addEventListener('contextmenu', function (e) {
let currentElement = e.target;
let contextMenuId;
while (currentElement != null) {
contextMenuId = currentElement.dataset['wails-context-menu-id'];
if (contextMenuId != null) {
break;
}
currentElement = currentElement.parentElement;
}
if (contextMenuId != null || window.disableWailsDefaultContextMenu) {
e.preventDefault();
}
if( contextMenuId != null ) {
let contextData = currentElement.dataset['wails-context-menu-data'];
let message = {
id: contextMenuId,
data: contextData || '',
};
window.wailsContextMenuMessage(JSON.stringify(message));
}
});
}

View File

@@ -14,28 +14,52 @@ The lightweight framework for web-like apps
*/
export const System = {
...common,
Platform: () => "linux",
}
AppType: 'desktop',
Platform: () => 'linux',
};
export function SendMessage(message) {
window.webkit.messageHandlers.external.postMessage(message);
window.wailsInvoke(message);
}
export function Init() {
// Setup drag handler
// Based on code from: https://github.com/patr0nus/DeskGap
window.addEventListener('mousedown', function (e) {
let currentElement = e.target;
while (currentElement != null) {
if (currentElement.hasAttribute('data-wails-no-drag')) {
break;
} else if (currentElement.hasAttribute('data-wails-drag')) {
window.webkit.messageHandlers.windowDrag.postMessage(null);
break;
}
currentElement = currentElement.parentElement;
}
});
// Setup drag handler
// Based on code from: https://github.com/patr0nus/DeskGap
window.addEventListener('mousedown', function (e) {
let currentElement = e.target;
while (currentElement != null) {
if (currentElement.hasAttribute('data-wails-no-drag')) {
break;
} else if (currentElement.hasAttribute('data-wails-drag')) {
window.wailsDrag(null);
break;
}
currentElement = currentElement.parentElement;
}
});
// Setup context menu hook
window.addEventListener('contextmenu', function (e) {
let currentElement = e.target;
let contextMenuId;
while (currentElement != null) {
contextMenuId = currentElement.dataset['wails-context-menu-id'];
if (contextMenuId != null) {
break;
}
currentElement = currentElement.parentElement;
}
if (contextMenuId != null || window.disableWailsDefaultContextMenu) {
e.preventDefault();
}
if( contextMenuId != null ) {
let contextData = currentElement.dataset['wails-context-menu-data'];
let message = {
id: contextMenuId,
data: contextData || '',
};
window.wailsContextMenuMessage(JSON.stringify(message));
}
});
}

View File

@@ -13,20 +13,13 @@ The lightweight framework for web-like apps
* Initialises platform specific code
*/
// import * as common from './common';
const common = require('./common');
export const System = {
...common,
AppType: 'desktop',
Platform: () => 'windows',
};
export function SendMessage(message) {
window.chrome.webview.postMessage('S'+message);
}
export function RaiseError(message) {
window.chrome.webview.postMessage('E'+message);
window.wailsInvoke(message);
}
export function Init() {
@@ -39,7 +32,7 @@ export function Init() {
if (currentElement.hasAttribute('data-wails-no-drag')) {
break;
} else if (currentElement.hasAttribute('data-wails-drag')) {
window.chrome.webview.postMessage('wails-drag');
window.wailsInvoke('wails-drag');
break;
}
currentElement = currentElement.parentElement;
@@ -66,7 +59,7 @@ export function Init() {
id: contextMenuId,
data: contextData || '',
};
window.chrome.webview.postMessage('C'+JSON.stringify(message));
window.wailsInvoke('C'+JSON.stringify(message));
}
});
}

View File

@@ -678,7 +678,7 @@
function add_css() {
var style = element("style");
style.id = "svelte-9nqyfr-style";
style.textContent = ".wails-reconnect-overlay.svelte-9nqyfr{position:fixed;top:0;left:0;width:100%;height:100%;backdrop-filter:blur(20px) saturate(160%) contrast(45%) brightness(140%);z-index:999999\n }.wails-reconnect-overlay-content.svelte-9nqyfr{position:relative;top:50%;transform:translateY(-50%);margin:0;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC8AAAAuCAMAAACPpbA7AAAAflBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQAAAAAAAAAAAABAQEEBAQAAAAAAAAEBAQAAAADAwMAAAABAQEAAAAAAAAAAAAAAAAAAAACAgICAgIBAQEAAAAAAAAAAAAAAAAAAAACAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBQWCC3waAAAAKXRSTlMALgUMIBk0+xEqJs70Xhb3lu3EjX2EZTlv5eHXvbarQj3cdmpXSqOeUDwaqNAAAAKCSURBVEjHjZTntqsgEIUPVVCwtxg1vfD+L3hHRe8K6snZf+KKn8OewvzsSSeXLruLnz+KHs0gr6DkT3xsRkU6VVn4Ha/UxLe1Z4y64i847sykPBh/AvQ7ry3eFN70oKrfcBJYvm/tQ1qxP4T3emXPeXAkvodPUvtdjbhk+Ft4c0hslTiXVOzxOJ15NWUblQhRsdu3E1AfCjj3Gdm18zSOsiH8Lk4TB480ksy62fiqNo4OpyU8O21l6+hyRtS6z8r1pHlmle5sR1/WXS6Mq2Nl+YeKt3vr+vdH/q4O68tzXuwkiZmngYb4R8Co1jh0+Ww2UTyWxBvtyxLO7QVjO3YOD/lWZpbXDGellFG2Mws58mMnjVZSn7p+XvZ6IF4nn02OJZV0aTO22arp/DgLPtrgpVoi6TPbZm4XQBjY159w02uO0BDdYsfrOEi0M2ulRXlCIPAOuN1NOVhi+riBR3dgwQplYsZRZJLXq23Mlo5njkbY0rZFu3oiNIYG2kqsbVz67OlNuZZIOlfxHDl0UpyRX86z/OYC/3qf1A1xTrMp/PWWM4ePzf8DDp1nesQRpcFk7BlwdzN08ZIALJpCaciQXO0f6k4dnuT/Ewg4l7qSTNzm2SykdHn6GJ12mWc6aCNj/g1cTXpB8YFfr0uVc96aFkkqiIiX4nO+salKwGtIkvfB+Ja8DxMeD3hIXP5mTOYPB4eVT0+32I5ykvPZjesnkGgIREgYnmLrPb0PdV3hoLup2TjcGBPM4mgsfF5BrawZR4/GpzYQzQfrUZCf0TCWYo2DqhdhTJBQ6j4xqmmLN5LjdRIY8LWExiFUsSrza/nmFBqw3I9tEZB9h0lIQSO9if8DkISDAj8CDawAAAAASUVORK5CYII=);background-repeat:no-repeat;background-position:center\n }.wails-reconnect-overlay-loadingspinner.svelte-9nqyfr{pointer-events:none;width:2.5em;height:2.5em;border:.4em solid transparent;border-color:#f00 #eee0 #f00 #eee0;border-radius:50%;animation:svelte-9nqyfr-loadingspin 1s linear infinite;margin:auto;padding:2.5em\n }@keyframes svelte-9nqyfr-loadingspin{100%{transform:rotate(360deg)}}";
style.textContent = ".wails-reconnect-overlay.svelte-9nqyfr{position:fixed;top:0;left:0;width:100%;height:100%;backdrop-filter:blur(20px) saturate(160%) contrast(45%) brightness(140%);z-index:999999\r\n }.wails-reconnect-overlay-content.svelte-9nqyfr{position:relative;top:50%;transform:translateY(-50%);margin:0;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC8AAAAuCAMAAACPpbA7AAAAflBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQAAAAAAAAAAAABAQEEBAQAAAAAAAAEBAQAAAADAwMAAAABAQEAAAAAAAAAAAAAAAAAAAACAgICAgIBAQEAAAAAAAAAAAAAAAAAAAACAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBQWCC3waAAAAKXRSTlMALgUMIBk0+xEqJs70Xhb3lu3EjX2EZTlv5eHXvbarQj3cdmpXSqOeUDwaqNAAAAKCSURBVEjHjZTntqsgEIUPVVCwtxg1vfD+L3hHRe8K6snZf+KKn8OewvzsSSeXLruLnz+KHs0gr6DkT3xsRkU6VVn4Ha/UxLe1Z4y64i847sykPBh/AvQ7ry3eFN70oKrfcBJYvm/tQ1qxP4T3emXPeXAkvodPUvtdjbhk+Ft4c0hslTiXVOzxOJ15NWUblQhRsdu3E1AfCjj3Gdm18zSOsiH8Lk4TB480ksy62fiqNo4OpyU8O21l6+hyRtS6z8r1pHlmle5sR1/WXS6Mq2Nl+YeKt3vr+vdH/q4O68tzXuwkiZmngYb4R8Co1jh0+Ww2UTyWxBvtyxLO7QVjO3YOD/lWZpbXDGellFG2Mws58mMnjVZSn7p+XvZ6IF4nn02OJZV0aTO22arp/DgLPtrgpVoi6TPbZm4XQBjY159w02uO0BDdYsfrOEi0M2ulRXlCIPAOuN1NOVhi+riBR3dgwQplYsZRZJLXq23Mlo5njkbY0rZFu3oiNIYG2kqsbVz67OlNuZZIOlfxHDl0UpyRX86z/OYC/3qf1A1xTrMp/PWWM4ePzf8DDp1nesQRpcFk7BlwdzN08ZIALJpCaciQXO0f6k4dnuT/Ewg4l7qSTNzm2SykdHn6GJ12mWc6aCNj/g1cTXpB8YFfr0uVc96aFkkqiIiX4nO+salKwGtIkvfB+Ja8DxMeD3hIXP5mTOYPB4eVT0+32I5ykvPZjesnkGgIREgYnmLrPb0PdV3hoLup2TjcGBPM4mgsfF5BrawZR4/GpzYQzQfrUZCf0TCWYo2DqhdhTJBQ6j4xqmmLN5LjdRIY8LWExiFUsSrza/nmFBqw3I9tEZB9h0lIQSO9if8DkISDAj8CDawAAAAASUVORK5CYII=);background-repeat:no-repeat;background-position:center\r\n }.wails-reconnect-overlay-loadingspinner.svelte-9nqyfr{pointer-events:none;width:2.5em;height:2.5em;border:.4em solid transparent;border-color:#f00 #eee0 #f00 #eee0;border-radius:50%;animation:svelte-9nqyfr-loadingspin 1s linear infinite;margin:auto;padding:2.5em\r\n }@keyframes svelte-9nqyfr-loadingspin{100%{transform:rotate(360deg)}}";
append(document.head, style);
}
@@ -1543,154 +1543,148 @@
function StartWebsocket(userCallback) {
callback = userCallback;
callback = userCallback;
window.onbeforeunload = function() {
if( websocket ) {
websocket.onclose = function () { };
websocket.close();
websocket = null;
}
};
window.onbeforeunload = function() {
if( websocket ) {
websocket.onclose = function () { };
websocket.close();
websocket = null;
}
};
// ...and attempt to connect
connect();
// ...and attempt to connect
connect();
}
function setupIPCBridge() {
// darwin
window.webkit = {
messageHandlers: {
external: {
postMessage: (message) => {
websocket.send(message);
}
},
windowDrag: {
postMessage: () => {
// Ignore window drag events
}
}
}
window.wailsInvoke = (message) => {
websocket.send(message);
};
window.wailsDrag = (message) => {
websocket.send(message);
};
window.wailsContextMenuMessage = (message) => {
websocket.send(message);
};
}
// Handles incoming websocket connections
function handleConnect() {
log('Connected to backend');
setupIPCBridge();
hideOverlay();
clearInterval(connectTimer);
websocket.onclose = handleDisconnect;
websocket.onmessage = handleMessage;
log('Connected to backend');
setupIPCBridge();
hideOverlay();
clearInterval(connectTimer);
websocket.onclose = handleDisconnect;
websocket.onmessage = handleMessage;
}
// Handles websocket disconnects
function handleDisconnect() {
log('Disconnected from backend');
websocket = null;
showOverlay();
connect();
log('Disconnected from backend');
websocket = null;
showOverlay();
connect();
}
// Try to connect to the backend every 1s (default value).
function connect() {
connectTimer = setInterval(function () {
if (websocket == null) {
websocket = new WebSocket('ws://' + window.location.hostname + ':34115/bridge');
websocket.onopen = handleConnect;
websocket.onerror = function (e) {
e.stopImmediatePropagation();
e.stopPropagation();
e.preventDefault();
websocket = null;
return false;
};
}
}, 1000);
connectTimer = setInterval(function () {
if (websocket == null) {
websocket = new WebSocket('ws://' + window.location.hostname + ':34115/bridge');
websocket.onopen = handleConnect;
websocket.onerror = function (e) {
e.stopImmediatePropagation();
e.stopPropagation();
e.preventDefault();
websocket = null;
return false;
};
}
}, 1000);
}
// Adds a script to the Dom.
// Removes it if second parameter is true.
function addScript(script, remove) {
const s = document.createElement('script');
s.setAttribute('type', 'text/javascript');
s.textContent = script;
document.head.appendChild(s);
const s = document.createElement('script');
s.setAttribute('type', 'text/javascript');
s.textContent = script;
document.head.appendChild(s);
// Remove internal messages from the DOM
if (remove) {
s.parentNode.removeChild(s);
}
// Remove internal messages from the DOM
if (remove) {
s.parentNode.removeChild(s);
}
}
function handleMessage(message) {
// As a bridge we ignore js and css injections
switch (message.data[0]) {
// Wails library - inject!
case 'b':
message = message.data.slice(1);
addScript(message);
log('Loaded Wails Runtime');
// As a bridge we ignore js and css injections
switch (message.data[0]) {
// Wails library - inject!
case 'b':
message = message.data.slice(1);
addScript(message);
log('Loaded Wails Runtime');
// We need to now send a message to the backend telling it
// we have loaded (System Start)
window.webkit.messageHandlers.external.postMessage("SS");
// We need to now send a message to the backend telling it
// we have loaded (System Start)
window.wailsInvoke('SS');
// Now wails runtime is loaded, wails for the ready event
// and callback to the main app
// window.wails.Events.On('wails:loaded', function () {
if (callback) {
log('Notifying application');
callback(window.wails);
}
// });
break;
// Notifications
case 'n':
window.wails._.Notify(message.data.slice(1));
break;
// // Binding
// case 'b':
// const binding = message.data.slice(1);
// //log("Binding: " + binding)
// window.wails._.NewBinding(binding);
// break;
// // Call back
case 'c':
const callbackData = message.data.slice(1);
window.wails._.Callback(callbackData);
break;
// Tray
case 'T':
const trayMessage = message.data.slice(1);
switch (trayMessage[0]) {
case 'S':
// Set tray
const trayJSON = trayMessage.slice(1);
let tray = JSON.parse(trayJSON);
setTray(tray);
break;
case 'U':
// Update label
const updateTrayLabelJSON = trayMessage.slice(1);
let trayLabelData = JSON.parse(updateTrayLabelJSON);
updateTrayLabel(trayLabelData);
break;
case 'D':
// Delete Tray Menu
const id = trayMessage.slice(1);
deleteTrayMenu(id);
break;
default:
log('Unknown tray message: ' + message.data);
}
break;
// Now wails runtime is loaded, wails for the ready event
// and callback to the main app
// window.wails.Events.On('wails:loaded', function () {
if (callback) {
log('Notifying application');
callback(window.wails);
}
// });
break;
// Notifications
case 'n':
window.wails._.Notify(message.data.slice(1));
break;
// // Binding
// case 'b':
// const binding = message.data.slice(1);
// //log("Binding: " + binding)
// window.wails._.NewBinding(binding);
// break;
// // Call back
case 'c':
const callbackData = message.data.slice(1);
window.wails._.Callback(callbackData);
break;
// Tray
case 'T':
const trayMessage = message.data.slice(1);
switch (trayMessage[0]) {
case 'S':
// Set tray
const trayJSON = trayMessage.slice(1);
let tray = JSON.parse(trayJSON);
setTray(tray);
break
case 'U':
// Update label
const updateTrayLabelJSON = trayMessage.slice(1);
let trayLabelData = JSON.parse(updateTrayLabelJSON);
updateTrayLabel(trayLabelData);
break
case 'D':
// Delete Tray Menu
const id = trayMessage.slice(1);
deleteTrayMenu(id);
break
default:
log('Unknown tray message: ' + message.data);
}
break;
default:
log('Unknown message: ' + message.data);
}
default:
log('Unknown message: ' + message.data);
}
}
/*

View File

@@ -9,7 +9,7 @@ The lightweight framework for web-like apps
*/
/* jshint esversion: 6 */
import bridge from './bridge';
const bridge = require('./bridge');
/**
* ready will execute the callback when Wails has loaded

View File

@@ -1,6 +1,6 @@
{
"name": "@wails/runtime",
"version": "1.2.24",
"version": "1.3.15",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -1,6 +1,6 @@
{
"name": "@wails/runtime",
"version": "1.3.13",
"version": "1.3.19",
"description": "Wails V2 Javascript runtime library",
"main": "main.js",
"types": "runtime.d.ts",

View File

@@ -1,616 +1,8 @@
{
"name": "bridge",
"version": "1.0.0",
"lockfileVersion": 2,
"lockfileVersion": 1,
"requires": true,
"packages": {
"": {
"name": "bridge",
"version": "1.0.0",
"license": "ISC",
"devDependencies": {
"@rollup/plugin-commonjs": "^17.1.0",
"@rollup/plugin-node-resolve": "^11.1.1",
"rollup": "^2.38.5",
"rollup-plugin-svelte": "^7.1.0",
"rollup-plugin-terser": "^7.0.2",
"svelte": "^3.32.2"
}
},
"node_modules/@babel/code-frame": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz",
"integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==",
"dev": true,
"dependencies": {
"@babel/highlight": "^7.12.13"
}
},
"node_modules/@babel/helper-validator-identifier": {
"version": "7.12.11",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz",
"integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==",
"dev": true
},
"node_modules/@babel/highlight": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz",
"integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==",
"dev": true,
"dependencies": {
"@babel/helper-validator-identifier": "^7.12.11",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
}
},
"node_modules/@rollup/plugin-commonjs": {
"version": "17.1.0",
"resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-17.1.0.tgz",
"integrity": "sha512-PoMdXCw0ZyvjpCMT5aV4nkL0QywxP29sODQsSGeDpr/oI49Qq9tRtAsb/LbYbDzFlOydVEqHmmZWFtXJEAX9ew==",
"dev": true,
"dependencies": {
"@rollup/pluginutils": "^3.1.0",
"commondir": "^1.0.1",
"estree-walker": "^2.0.1",
"glob": "^7.1.6",
"is-reference": "^1.2.1",
"magic-string": "^0.25.7",
"resolve": "^1.17.0"
},
"engines": {
"node": ">= 8.0.0"
}
},
"node_modules/@rollup/plugin-commonjs/node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true
},
"node_modules/@rollup/plugin-node-resolve": {
"version": "11.1.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.1.1.tgz",
"integrity": "sha512-zlBXR4eRS+2m79TsUZWhsd0slrHUYdRx4JF+aVQm+MI0wsKdlpC2vlDVjmlGvtZY1vsefOT9w3JxvmWSBei+Lg==",
"dev": true,
"dependencies": {
"@rollup/pluginutils": "^3.1.0",
"@types/resolve": "1.17.1",
"builtin-modules": "^3.1.0",
"deepmerge": "^4.2.2",
"is-module": "^1.0.0",
"resolve": "^1.19.0"
},
"engines": {
"node": ">= 10.0.0"
}
},
"node_modules/@rollup/pluginutils": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
"integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
"dev": true,
"dependencies": {
"@types/estree": "0.0.39",
"estree-walker": "^1.0.1",
"picomatch": "^2.2.2"
},
"engines": {
"node": ">= 8.0.0"
}
},
"node_modules/@types/estree": {
"version": "0.0.39",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
"dev": true
},
"node_modules/@types/node": {
"version": "14.14.25",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.25.tgz",
"integrity": "sha512-EPpXLOVqDvisVxtlbvzfyqSsFeQxltFbluZNRndIb8tr9KiBnYNLzrc1N3pyKUCww2RNrfHDViqDWWE1LCJQtQ==",
"dev": true
},
"node_modules/@types/resolve": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
"integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==",
"dev": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"dependencies": {
"color-convert": "^1.9.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"dev": true
},
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/buffer-from": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
"dev": true
},
"node_modules/builtin-modules": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz",
"integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"dependencies": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"dev": true,
"dependencies": {
"color-name": "1.1.3"
}
},
"node_modules/color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
},
"node_modules/commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true
},
"node_modules/commondir": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
"integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
"dev": true
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"node_modules/deepmerge": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
"dev": true,
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/estree-walker": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
"integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
"dev": true
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
},
"node_modules/glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"dev": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
}
},
"node_modules/has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.1"
},
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true,
"engines": {
"node": ">=4"
}
},
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"node_modules/is-core-module": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz",
"integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==",
"dev": true,
"dependencies": {
"has": "^1.0.3"
}
},
"node_modules/is-module": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
"integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=",
"dev": true
},
"node_modules/is-reference": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz",
"integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==",
"dev": true,
"dependencies": {
"@types/estree": "*"
}
},
"node_modules/jest-worker": {
"version": "26.6.2",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz",
"integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==",
"dev": true,
"dependencies": {
"@types/node": "*",
"merge-stream": "^2.0.0",
"supports-color": "^7.0.0"
},
"engines": {
"node": ">= 10.13.0"
}
},
"node_modules/jest-worker/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/jest-worker/node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"dev": true
},
"node_modules/magic-string": {
"version": "0.25.7",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
"integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==",
"dev": true,
"dependencies": {
"sourcemap-codec": "^1.4.4"
}
},
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
"dev": true
},
"node_modules/minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
"engines": {
"node": "*"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"dependencies": {
"wrappy": "1"
}
},
"node_modules/path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/path-parse": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
"dev": true
},
"node_modules/picomatch": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
"dev": true,
"engines": {
"node": ">=8.6"
}
},
"node_modules/randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
"dev": true,
"dependencies": {
"safe-buffer": "^5.1.0"
}
},
"node_modules/require-relative": {
"version": "0.8.7",
"resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz",
"integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=",
"dev": true
},
"node_modules/resolve": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz",
"integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==",
"dev": true,
"dependencies": {
"is-core-module": "^2.1.0",
"path-parse": "^1.0.6"
}
},
"node_modules/rollup": {
"version": "2.38.5",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.38.5.tgz",
"integrity": "sha512-VoWt8DysFGDVRGWuHTqZzT02J0ASgjVq/hPs9QcBOGMd7B+jfTr/iqMVEyOi901rE3xq+Deq66GzIT1yt7sGwQ==",
"dev": true,
"bin": {
"rollup": "dist/bin/rollup"
},
"engines": {
"node": ">=10.0.0"
},
"optionalDependencies": {
"fsevents": "~2.3.1"
}
},
"node_modules/rollup-plugin-svelte": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/rollup-plugin-svelte/-/rollup-plugin-svelte-7.1.0.tgz",
"integrity": "sha512-vopCUq3G+25sKjwF5VilIbiY6KCuMNHP1PFvx2Vr3REBNMDllKHFZN2B9jwwC+MqNc3UPKkjXnceLPEjTjXGXg==",
"dev": true,
"dependencies": {
"require-relative": "^0.8.7",
"rollup-pluginutils": "^2.8.2"
},
"engines": {
"node": ">=10"
}
},
"node_modules/rollup-plugin-terser": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz",
"integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==",
"dev": true,
"dependencies": {
"@babel/code-frame": "^7.10.4",
"jest-worker": "^26.2.1",
"serialize-javascript": "^4.0.0",
"terser": "^5.0.0"
}
},
"node_modules/rollup-pluginutils": {
"version": "2.8.2",
"resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz",
"integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==",
"dev": true,
"dependencies": {
"estree-walker": "^0.6.1"
}
},
"node_modules/rollup-pluginutils/node_modules/estree-walker": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
"integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==",
"dev": true
},
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"dev": true
},
"node_modules/serialize-javascript": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
"integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
"dev": true,
"dependencies": {
"randombytes": "^2.1.0"
}
},
"node_modules/source-map": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
"dev": true,
"engines": {
"node": ">= 8"
}
},
"node_modules/source-map-support": {
"version": "0.5.19",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
"integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
"dev": true,
"dependencies": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
"node_modules/source-map-support/node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/sourcemap-codec": {
"version": "1.4.8",
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
"dev": true
},
"node_modules/supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"dependencies": {
"has-flag": "^3.0.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/svelte": {
"version": "3.32.2",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-3.32.2.tgz",
"integrity": "sha512-Zxh1MQQl/+vnToKbU1Per+PoMN8Jb2MeKJcGxiOsCGR677hXw7jkMfbnNXq33+dxIzV/HfA4xtoSPJrqeB0VUg==",
"dev": true,
"engines": {
"node": ">= 8"
}
},
"node_modules/terser": {
"version": "5.5.1",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.5.1.tgz",
"integrity": "sha512-6VGWZNVP2KTUcltUQJ25TtNjx/XgdDsBDKGt8nN0MpydU36LmbPPcMBd2kmtZNNGVVDLg44k7GKeHHj+4zPIBQ==",
"dev": true,
"dependencies": {
"commander": "^2.20.0",
"source-map": "~0.7.2",
"source-map-support": "~0.5.19"
},
"bin": {
"terser": "bin/terser"
},
"engines": {
"node": ">=10"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
}
},
"dependencies": {
"@babel/code-frame": {
"version": "7.12.13",

View File

@@ -10,8 +10,8 @@ The lightweight framework for web-like apps
/* jshint esversion: 6 */
import {setTray, hideOverlay, showOverlay, updateTrayLabel, deleteTrayMenu} from "./store";
import {log} from "./log";
import {setTray, hideOverlay, showOverlay, updateTrayLabel, deleteTrayMenu} from './store';
import {log} from './log';
let websocket = null;
let callback = null;
@@ -19,152 +19,140 @@ let connectTimer;
export function StartWebsocket(userCallback) {
callback = userCallback;
callback = userCallback;
window.onbeforeunload = function() {
if( websocket ) {
websocket.onclose = function () { };
websocket.close();
websocket = null;
}
}
window.onbeforeunload = function() {
if( websocket ) {
websocket.onclose = function () { };
websocket.close();
websocket = null;
}
};
// ...and attempt to connect
connect();
// ...and attempt to connect
connect();
}
function setupIPCBridge() {
// darwin
window.webkit = {
messageHandlers: {
external: {
postMessage: (message) => {
websocket.send(message);
}
},
windowDrag: {
postMessage: () => {
// Ignore window drag events
}
}
}
};
window.wailsInvoke = (message) => {
websocket.send(message);
};
}
// Handles incoming websocket connections
function handleConnect() {
log('Connected to backend');
setupIPCBridge();
hideOverlay();
clearInterval(connectTimer);
websocket.onclose = handleDisconnect;
websocket.onmessage = handleMessage;
log('Connected to backend');
setupIPCBridge();
hideOverlay();
clearInterval(connectTimer);
websocket.onclose = handleDisconnect;
websocket.onmessage = handleMessage;
}
// Handles websocket disconnects
function handleDisconnect() {
log('Disconnected from backend');
websocket = null;
showOverlay();
connect();
log('Disconnected from backend');
websocket = null;
showOverlay();
connect();
}
// Try to connect to the backend every 1s (default value).
function connect() {
connectTimer = setInterval(function () {
if (websocket == null) {
websocket = new WebSocket('ws://' + window.location.hostname + ':34115/bridge');
websocket.onopen = handleConnect;
websocket.onerror = function (e) {
e.stopImmediatePropagation();
e.stopPropagation();
e.preventDefault();
websocket = null;
return false;
};
}
}, 1000);
connectTimer = setInterval(function () {
if (websocket == null) {
websocket = new WebSocket('ws://' + window.location.hostname + ':34115/bridge');
websocket.onopen = handleConnect;
websocket.onerror = function (e) {
e.stopImmediatePropagation();
e.stopPropagation();
e.preventDefault();
websocket = null;
return false;
};
}
}, 1000);
}
// Adds a script to the Dom.
// Removes it if second parameter is true.
function addScript(script, remove) {
const s = document.createElement('script');
s.setAttribute('type', 'text/javascript');
s.textContent = script;
document.head.appendChild(s);
const s = document.createElement('script');
s.setAttribute('type', 'text/javascript');
s.textContent = script;
document.head.appendChild(s);
// Remove internal messages from the DOM
if (remove) {
s.parentNode.removeChild(s);
}
// Remove internal messages from the DOM
if (remove) {
s.parentNode.removeChild(s);
}
}
function handleMessage(message) {
// As a bridge we ignore js and css injections
switch (message.data[0]) {
// Wails library - inject!
case 'b':
message = message.data.slice(1)
addScript(message);
log('Loaded Wails Runtime');
// As a bridge we ignore js and css injections
switch (message.data[0]) {
// Wails library - inject!
case 'b':
message = message.data.slice(1);
addScript(message);
log('Loaded Wails Runtime');
// We need to now send a message to the backend telling it
// we have loaded (System Start)
window.webkit.messageHandlers.external.postMessage("SS");
// We need to now send a message to the backend telling it
// we have loaded (System Start)
window.wailsInvoke('SS');
// Now wails runtime is loaded, wails for the ready event
// and callback to the main app
// window.wails.Events.On('wails:loaded', function () {
if (callback) {
log('Notifying application');
callback(window.wails);
}
// });
break;
// Notifications
case 'n':
window.wails._.Notify(message.data.slice(1));
break;
// // Binding
// case 'b':
// const binding = message.data.slice(1);
// //log("Binding: " + binding)
// window.wails._.NewBinding(binding);
// break;
// // Call back
case 'c':
const callbackData = message.data.slice(1);
window.wails._.Callback(callbackData);
break;
// Tray
case 'T':
const trayMessage = message.data.slice(1);
switch (trayMessage[0]) {
case 'S':
// Set tray
const trayJSON = trayMessage.slice(1);
let tray = JSON.parse(trayJSON);
setTray(tray);
break;
case 'U':
// Update label
const updateTrayLabelJSON = trayMessage.slice(1);
let trayLabelData = JSON.parse(updateTrayLabelJSON);
updateTrayLabel(trayLabelData);
break;
case 'D':
// Delete Tray Menu
const id = trayMessage.slice(1);
deleteTrayMenu(id);
break;
default:
log('Unknown tray message: ' + message.data);
}
break;
// Now wails runtime is loaded, wails for the ready event
// and callback to the main app
// window.wails.Events.On('wails:loaded', function () {
if (callback) {
log('Notifying application');
callback(window.wails);
}
// });
break;
// Notifications
case 'n':
window.wails._.Notify(message.data.slice(1));
break;
// // Binding
// case 'b':
// const binding = message.data.slice(1);
// //log("Binding: " + binding)
// window.wails._.NewBinding(binding);
// break;
// // Call back
case 'c':
const callbackData = message.data.slice(1);
window.wails._.Callback(callbackData);
break;
// Tray
case 'T':
const trayMessage = message.data.slice(1);
switch (trayMessage[0]) {
case 'S':
// Set tray
const trayJSON = trayMessage.slice(1);
let tray = JSON.parse(trayJSON)
setTray(tray)
break
case 'U':
// Update label
const updateTrayLabelJSON = trayMessage.slice(1);
let trayLabelData = JSON.parse(updateTrayLabelJSON)
updateTrayLabel(trayLabelData)
break
case 'D':
// Delete Tray Menu
const id = trayMessage.slice(1);
deleteTrayMenu(id)
break
default:
log('Unknown tray message: ' + message.data);
}
break;
default:
log('Unknown message: ' + message.data);
}
default:
log('Unknown message: ' + message.data);
}
}

View File

@@ -16,7 +16,7 @@ func main() {
sourceDir := fs.RelativePath("../../../internal/runtime/js")
platforms := []string{"darwin", "windows"}
platforms := []string{"darwin", "windows", "linux"}
for _, platform := range platforms {
println("Building JS Runtime for " + platform)

View File

@@ -1,5 +0,0 @@
package apps
func Find() []Apps {
}

View File

@@ -9,23 +9,23 @@ import (
"github.com/wailsapp/wails/v2/internal/shell"
)
// Yum represents the Yum manager
type Yum struct {
// Dnf represents the Dnf manager
type Dnf struct {
name string
osid string
}
// NewYum creates a new Yum instance
func NewYum(osid string) *Yum {
return &Yum{
name: "yum",
// NewDnf creates a new Dnf instance
func NewDnf(osid string) *Dnf {
return &Dnf{
name: "dnf",
osid: osid,
}
}
// Packages returns the libraries that we need for Wails to compile
// They will potentially differ on different distributions or versions
func (y *Yum) Packages() packagemap {
func (y *Dnf) Packages() packagemap {
return packagemap{
"libgtk-3": []*Package{
{Name: "gtk3-devel", SystemPackage: true, Library: true},
@@ -43,6 +43,9 @@ func (y *Yum) Packages() packagemap {
"npm": []*Package{
{Name: "npm", SystemPackage: true},
},
"upx": []*Package{
{Name: "upx", SystemPackage: true, Optional: true},
},
"docker": []*Package{
{
SystemPackage: false,
@@ -57,16 +60,16 @@ func (y *Yum) Packages() packagemap {
}
// Name returns the name of the package manager
func (y *Yum) Name() string {
func (y *Dnf) Name() string {
return y.name
}
// PackageInstalled tests if the given package name is installed
func (y *Yum) PackageInstalled(pkg *Package) (bool, error) {
func (y *Dnf) PackageInstalled(pkg *Package) (bool, error) {
if pkg.SystemPackage == false {
return false, nil
}
stdout, _, err := shell.RunCommand(".", "yum", "info", "installed", pkg.Name)
stdout, _, err := shell.RunCommand(".", "dnf", "info", "installed", pkg.Name)
if err != nil {
_, ok := err.(*exec.ExitError)
if ok {
@@ -87,11 +90,11 @@ func (y *Yum) PackageInstalled(pkg *Package) (bool, error) {
}
// PackageAvailable tests if the given package is available for installation
func (y *Yum) PackageAvailable(pkg *Package) (bool, error) {
func (y *Dnf) PackageAvailable(pkg *Package) (bool, error) {
if pkg.SystemPackage == false {
return false, nil
}
stdout, _, err := shell.RunCommand(".", "yum", "info", pkg.Name)
stdout, _, err := shell.RunCommand(".", "dnf", "info", pkg.Name)
// We add a space to ensure we get a full match, not partial match
if err != nil {
_, ok := err.(*exec.ExitError)
@@ -111,14 +114,14 @@ func (y *Yum) PackageAvailable(pkg *Package) (bool, error) {
}
// InstallCommand returns the package manager specific command to install a package
func (y *Yum) InstallCommand(pkg *Package) string {
func (y *Dnf) InstallCommand(pkg *Package) string {
if pkg.SystemPackage == false {
return pkg.InstallCommand[y.osid]
}
return "sudo yum install " + pkg.Name
return "sudo dnf install " + pkg.Name
}
func (y *Yum) getPackageVersion(pkg *Package, output string) {
func (y *Dnf) getPackageVersion(pkg *Package, output string) {
splitOutput := strings.Split(output, " ")
if len(splitOutput) > 0 {
pkg.Version = splitOutput[1]

View File

@@ -9,12 +9,11 @@ import (
"github.com/wailsapp/wails/v2/internal/shell"
)
// A list of package manager commands
var pmcommands = []string{
"eopkg",
"apt",
"yum",
"dnf",
"pacman",
"emerge",
"zypper",
@@ -38,8 +37,8 @@ func newPackageManager(pmname string, osid string) PackageManager {
return NewEopkg(osid)
case "apt":
return NewApt(osid)
case "yum":
return NewYum(osid)
case "dnf":
return NewDnf(osid)
case "pacman":
return NewPacman(osid)
case "emerge":
@@ -77,7 +76,7 @@ func Dependancies(p PackageManager) (DependencyList, error) {
if installed {
dependency.Installed = true
dependency.Version = pkg.Version
if !pkg.Library {
if !pkg.SystemPackage {
dependency.Version = AppVersion(name)
}
} else {

View File

@@ -21,7 +21,6 @@ type PackageManager interface {
InstallCommand(*Package) string
}
// Dependancy represents a system package that we require
type Dependancy struct {
Name string
@@ -36,20 +35,13 @@ type Dependancy struct {
// DependencyList is a list of Dependency instances
type DependencyList []*Dependancy
// InstallAllRequiredCommand returns the command you need to use to install all required dependencies
func (d DependencyList) InstallAllRequiredCommand() string {
result := ""
for _, dependency := range d {
if dependency.PackageName != "" {
if !dependency.Installed && !dependency.Optional {
if result == "" {
result = dependency.InstallCommand
} else {
result += " " + dependency.PackageName
}
}
if !dependency.Installed && !dependency.Optional {
result += " - " + dependency.Name + ": " + dependency.InstallCommand + "\n"
}
}
@@ -61,17 +53,10 @@ func (d DependencyList) InstallAllOptionalCommand() string {
result := ""
for _, dependency := range d {
if dependency.PackageName != "" {
if !dependency.Installed && dependency.Optional {
if result == "" {
result = dependency.InstallCommand
} else {
result += " " + dependency.PackageName
}
}
if !dependency.Installed && dependency.Optional {
result += " - " + dependency.Name + ": " + dependency.InstallCommand + "\n"
}
}
return result
}

View File

@@ -3,6 +3,8 @@ package system
import (
"github.com/wailsapp/wails/v2/internal/system/operatingsystem"
"github.com/wailsapp/wails/v2/internal/system/packagemanager"
"os/exec"
"strings"
)
// Info holds information about the current operating system,
@@ -24,3 +26,82 @@ func GetInfo() (*Info, error) {
}
return &result, nil
}
func checkNPM() *packagemanager.Dependancy {
// Check for npm
output, err := exec.Command("npm", "-version").Output()
installed := true
version := ""
if err != nil {
installed = false
} else {
version = strings.TrimSpace(strings.Split(string(output), "\n")[0])
}
return &packagemanager.Dependancy{
Name: "npm ",
PackageName: "N/A",
Installed: installed,
InstallCommand: "Available at https://nodejs.org/en/download/",
Version: version,
Optional: false,
External: false,
}
}
func checkUPX() *packagemanager.Dependancy {
// Check for npm
output, err := exec.Command("upx", "-V").Output()
installed := true
version := ""
if err != nil {
installed = false
} else {
version = strings.TrimSpace(strings.Split(string(output), "\n")[0])
}
return &packagemanager.Dependancy{
Name: "upx ",
PackageName: "N/A",
Installed: installed,
InstallCommand: "Available at https://upx.github.io/",
Version: version,
Optional: true,
External: false,
}
}
func checkDocker() *packagemanager.Dependancy {
// Check for npm
output, err := exec.Command("docker", "version").Output()
installed := true
version := ""
// Docker errors if it is not running so check for that
if len(output) == 0 && err != nil {
installed = false
} else {
// Version is in a line like: " Version: 20.10.5"
versionOutput := strings.Split(string(output), "\n")
for _, line := range versionOutput[1:] {
splitLine := strings.Split(line, ":")
if len(splitLine) > 1 {
key := strings.TrimSpace(splitLine[0])
if key == "Version" {
version = strings.TrimSpace(splitLine[1])
break
}
}
}
}
return &packagemanager.Dependancy{
Name: "docker ",
PackageName: "N/A",
Installed: installed,
InstallCommand: "Available at https://www.docker.com/products/docker-desktop",
Version: version,
Optional: true,
External: false,
}
}

View File

@@ -2,7 +2,14 @@
package system
import "github.com/wailsapp/wails/v2/internal/system/operatingsystem"
import (
"os/exec"
"strings"
"github.com/wailsapp/wails/v2/internal/system/packagemanager"
"github.com/wailsapp/wails/v2/internal/system/operatingsystem"
)
func (i *Info) discover() error {
var err error
@@ -11,5 +18,29 @@ func (i *Info) discover() error {
return err
}
i.OS = osinfo
// Check for xcode command line tools
output, err := exec.Command("xcode-select", "-v").Output()
installed := true
version := ""
if err != nil {
installed = false
} else {
version = strings.TrimPrefix(string(output), "xcode-select version ")
version = strings.TrimSpace(version)
version = strings.TrimSuffix(version, ".")
}
xcodeDep := &packagemanager.Dependancy{
Name: "xcode command line tools ",
PackageName: "N/A",
Installed: installed,
InstallCommand: "xcode-select --install",
Version: version,
Optional: false,
External: false,
}
i.Dependencies = append(i.Dependencies, xcodeDep)
i.Dependencies = append(i.Dependencies, checkNPM())
i.Dependencies = append(i.Dependencies, checkUPX())
return nil
}

View File

@@ -2,7 +2,12 @@
package system
import "github.com/wailsapp/wails/v2/internal/system/operatingsystem"
import (
"github.com/wailsapp/wails/v2/internal/system/operatingsystem"
"github.com/wailsapp/wails/v2/internal/system/packagemanager"
"os/exec"
"strings"
)
func (i *Info) discover() error {
@@ -12,5 +17,29 @@ func (i *Info) discover() error {
return err
}
i.OS = osinfo
// Check for gcc
output, err := exec.Command("gcc", "--version").Output()
installed := true
version := ""
if err != nil {
installed = false
} else {
version = strings.TrimSpace(strings.Split(string(output), "\n")[0])
}
gccDependency := &packagemanager.Dependancy{
Name: "gcc ",
PackageName: "N/A",
Installed: installed,
InstallCommand: "Available at https://jmeubank.github.io/tdm-gcc/",
Version: version,
Optional: false,
External: false,
}
i.Dependencies = append(i.Dependencies, gccDependency)
i.Dependencies = append(i.Dependencies, checkNPM())
i.Dependencies = append(i.Dependencies, checkUPX())
i.Dependencies = append(i.Dependencies, checkDocker())
return nil
}

View File

@@ -1,9 +1,10 @@
# Assets Directory
# Build Directory
The assets directory is used to house all the assets of your application.
The build directory is used to house all the build files and assets for your application.
The structure is:
* bin - Output directory
* dialog - Icons for dialogs
* tray - Icons for the system tray
* mac - MacOS specific files

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@@ -0,0 +1,14 @@
<!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>{{.Name}}</string>
<key>CFBundleExecutable</key><string>{{.Name}}</string>
<key>CFBundleIdentifier</key><string>com.wails.{{.Name}}</string>
<key>CFBundleVersion</key><string>1.0.0</string>
<key>CFBundleGetInfoString</key><string>Built using Wails (https://wails.app)</string>
<key>CFBundleShortVersionString</key><string>1.0.0</string>
<key>CFBundleIconFile</key><string>iconfile</string>
<key>LSMinimumSystemVersion</key><string>10.13.0</string>
<key>NSHighResolutionCapable</key><string>true</string>
<key>NSHumanReadableCopyright</key><string>Copyright.........</string>
</dict></plist>

View File

@@ -0,0 +1,3 @@
# Default Dialog Icons
This directory contains the default dialog icons. These are pre-compiled into a single C file (`defaultDialogIcons.c`) which resides in the `ffenestri` directory. If these icons are ever updated, then there is a need to run: `go run build.go` in this directory. This will generate a new `defaultDialogIcons.c` file in the `ffenestri` directory.

Binary file not shown.

After

Width:  |  Height:  |  Size: 780 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 764 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 830 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 720 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<assemblyIdentity type="win32" name="MyApplication" version="1.0.0.0" processorArchitecture="amd64"/>
<asmv3:application>
<asmv3:windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware> <!-- fallback for Windows 7 and 8 -->
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">permonitorv2,permonitor</dpiAwareness> <!-- falls back to per-monitor if per-monitor v2 is not supported -->
<gdiScaling xmlns="http://schemas.microsoft.com/SMI/2017/WindowsSettings">true</gdiScaling> <!-- enables GDI DPI scaling -->
</asmv3:windowsSettings>
</asmv3:application>
</assembly>

View File

@@ -0,0 +1,2 @@
100 ICON "app.ico"
110 24 "{{.Name}}.exe.manifest"

View File

@@ -0,0 +1,84 @@
package buildassets
import (
"embed"
"github.com/leaanthony/debme"
"github.com/leaanthony/gosod"
"os"
"path/filepath"
"text/template"
)
//go:embed build
var assets embed.FS
type assetData struct {
Name string
}
// Install will install all default project assets
func Install(targetDir string, projectName string) error {
templateDir := gosod.New(assets)
err := templateDir.Extract(targetDir, &assetData{Name: projectName})
if err != nil {
return err
}
// Rename the manifest file
windowsDir := filepath.Join(targetDir, "build", "windows")
manifest := filepath.Join(windowsDir, "wails.exe.manifest")
targetFile := filepath.Join(windowsDir, projectName+".exe.manifest")
err = os.Rename(manifest, targetFile)
if err != nil {
return err
}
// Rename the rc file
rc := filepath.Join(windowsDir, "wails.rc")
targetFile = filepath.Join(windowsDir, projectName+".rc")
err = os.Rename(rc, targetFile)
if err != nil {
return err
}
return nil
}
// RegenerateRCFile will recreate the RC file
func RegenerateRCFile(projectDir string, projectName string) error {
targetFile, err := os.OpenFile(filepath.Join(projectDir, "build", "windows", projectName+".rc"), os.O_CREATE, 0644)
if err != nil {
return err
}
data := &assetData{Name: projectName}
templateData, err := assets.ReadFile("build/windows/wails.rc.tmpl")
if err != nil {
return err
}
tmpl, err := template.New("rc").Parse(string(templateData))
if err != nil {
return err
}
err = tmpl.Execute(targetFile, data)
if err != nil {
return err
}
return nil
}
func RegenerateManifest(target string) error {
a, err := debme.FS(assets, "build")
if err != nil {
return err
}
return a.CopyFile("windows/wails.exe.manifest", target, 0644)
}
func RegenerateAppIcon(target string) error {
a, err := debme.FS(assets, "build")
if err != nil {
return err
}
return a.CopyFile("appicon.png", target, 0644)
}

View File

@@ -152,7 +152,16 @@ func (b *BaseBuilder) CleanUp() {
func (b *BaseBuilder) OutputFilename(options *Options) string {
outputFile := options.OutputFile
if outputFile == "" {
outputFile = b.projectData.OutputFilename
target := strings.TrimSuffix(b.projectData.OutputFilename, ".exe")
if b.projectData.OutputType != "desktop" {
target += "-" + b.projectData.OutputType
}
switch b.options.Platform {
case "windows":
outputFile = b.projectData.OutputFilename
case "darwin", "linux":
outputFile = fmt.Sprintf("%s-%s-%s", target, b.options.Platform, b.options.Arch)
}
}
return outputFile
}
@@ -306,7 +315,7 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
println("Done.")
// If we are targeting windows, dump the DLLs
if options.Platform == "windows" {
err := os.WriteFile(filepath.Join(appDir, "webview2.dll"), x64.WebView2, 0755)
err := os.WriteFile(filepath.Join(appDir, "webview.dll"), x64.WebView2, 0755)
if err != nil {
return err
}
@@ -328,16 +337,23 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
return nil
}
if verbose {
println("upx", "--best", "--no-color", "--no-progress", options.CompiledBinary)
var args = []string{"--best", "--no-color", "--no-progress", options.CompiledBinary}
if options.CompressFlags != "" {
args = strings.Split(options.CompressFlags, " ")
args = append(args, options.CompiledBinary)
}
output, err := exec.Command("upx", "--best", "--no-color", "--no-progress", options.CompiledBinary).Output()
if verbose {
println("upx", strings.Join(args, " "))
}
output, err := exec.Command("upx", args...).Output()
if err != nil {
return errors.Wrap(err, "Error during compression:")
}
if verbose {
println(output)
println(string(output))
}
return nil
}

View File

@@ -2,6 +2,7 @@ package build
import (
"fmt"
"log"
"os"
"path/filepath"
"runtime"
@@ -32,7 +33,7 @@ type Options struct {
UserTags []string // Tags to pass to the Go compiler
Logger *clilogger.CLILogger // All output to the logger
OutputType string // EG: desktop, server....
Mode Mode // release or debug
Mode Mode // release or debug or dev
ProjectData *project.Project // The project data
Pack bool // Create a package for the app after building
Platform string // The platform to build for
@@ -46,6 +47,7 @@ type Options struct {
KeepAssets bool // Keep the generated assets/files
Verbosity int // Verbosity level (0 - silent, 1 - default, 2 - verbose)
Compress bool // Compress the final binary
CompressFlags string // Flags to pass to UPX
AppleIdentity string
}
@@ -74,7 +76,7 @@ func Build(options *Options) (string, error) {
options.ProjectData = projectData
// Set build directory
options.BuildDirectory = filepath.Join(options.ProjectData.Path, "build", options.Platform, options.OutputType)
options.BuildDirectory = filepath.Join(options.ProjectData.Path, "build", "bin")
// Save the project type
projectData.OutputType = options.OutputType
@@ -121,6 +123,25 @@ func Build(options *Options) (string, error) {
return "", err
}
// If we are building for windows, we will need to generate the asset bundle before
// compilation. This will be a .syso file in the project root
if options.Pack && options.Platform == "windows" {
outputLogger.Print("Generating bundle assets: ")
err := packageApplication(options)
if err != nil {
return "", err
}
outputLogger.Println("Done.")
// When we finish, we will want to remove the syso file
defer func() {
err := os.Remove(filepath.Join(options.ProjectData.Path, options.ProjectData.Name+"-res.syso"))
if err != nil {
log.Fatal(err)
}
}()
}
// Compile the application
outputLogger.Print("Compiling application: ")
@@ -161,8 +182,14 @@ func Build(options *Options) (string, error) {
return "", fmt.Errorf("%s - %s", err.Error(), stderr)
}
// Remove temp binaries
fs.DeleteFile(filepath.Join(options.BuildDirectory, amd64Filename))
fs.DeleteFile(filepath.Join(options.BuildDirectory, arm64Filename))
err = fs.DeleteFile(filepath.Join(options.BuildDirectory, amd64Filename))
if err != nil {
return "", err
}
err = fs.DeleteFile(filepath.Join(options.BuildDirectory, arm64Filename))
if err != nil {
return "", err
}
projectData.OutputFilename = outputFile
options.CompiledBinary = filepath.Join(options.BuildDirectory, outputFile)
} else {
@@ -171,10 +198,9 @@ func Build(options *Options) (string, error) {
return "", err
}
}
outputLogger.Println("Done.")
// Do we need to pack the app?
if options.Pack {
// Do we need to pack the app for non-windows?
if options.Pack && options.Platform != "windows" {
outputLogger.Print("Packaging application: ")

View File

@@ -2,6 +2,7 @@ package build
import (
"fmt"
"github.com/wailsapp/wails/v2/pkg/buildassets"
"io/ioutil"
"path/filepath"
@@ -25,11 +26,9 @@ func (d *DesktopBuilder) BuildAssets(options *Options) error {
var err error
// Check assets directory exists
if !fs.DirExists(options.ProjectData.AssetsDir) {
if !fs.DirExists(options.ProjectData.BuildDir) {
// Path to default assets
defaultAssets := fs.RelativePath("./internal/assets")
// Copy the default assets directory
err := fs.CopyDir(defaultAssets, options.ProjectData.AssetsDir)
err := buildassets.Install(options.ProjectData.Path, options.ProjectData.Name)
if err != nil {
return err
}
@@ -106,9 +105,9 @@ func (d *DesktopBuilder) BuildBaseAssets(assets *html.AssetBundle, options *Opti
func (d *DesktopBuilder) processApplicationIcon(assetDir string) error {
// Copy default icon if one doesn't exist
iconFile := filepath.Join(d.projectData.AssetsDir, "appicon.png")
iconFile := filepath.Join(d.projectData.BuildDir, "appicon.png")
if !fs.FileExists(iconFile) {
err := fs.CopyFile(defaultIconPath(), iconFile)
err := buildassets.RegenerateAppIcon(iconFile)
if err != nil {
return err
}

View File

@@ -27,7 +27,7 @@ func (d *DesktopBuilder) processTrayIcons(assetDir string, options *Options) err
var err error
// Get all the tray icon filenames
trayIconDirectory := filepath.Join(options.ProjectData.AssetsDir, "tray")
trayIconDirectory := filepath.Join(options.ProjectData.BuildDir, "tray")
// If the directory doesn't exist, create it
if !fs.DirExists(trayIconDirectory) {
@@ -116,7 +116,7 @@ func (d *DesktopBuilder) processDialogIcons(assetDir string, options *Options) e
var err error
// Get all the dialog icon filenames
dialogIconDirectory := filepath.Join(options.ProjectData.AssetsDir, "dialog")
dialogIconDirectory := filepath.Join(options.ProjectData.BuildDir, "dialog")
var dialogIconFilenames []string
// If the directory does not exist, create it

View File

@@ -17,7 +17,7 @@ func (d *DesktopBuilder) compileIcon(assetDir string, iconFile string) error {
// Load icon into a databuffer
targetFilename := "icon"
targetFile := filepath.Join(assetDir, targetFilename+".c")
targetFile := filepath.Join(assetDir, targetFilename+".h")
d.addFileToDelete(targetFile)
@@ -33,7 +33,10 @@ func (d *DesktopBuilder) compileIcon(assetDir string, iconFile string) error {
if err != nil {
return err
}
f.Close()
err = f.Close()
if err != nil {
return err
}
var buf strings.Builder
@@ -52,3 +55,181 @@ func (d *DesktopBuilder) compileIcon(assetDir string, iconFile string) error {
return err
}
// We will compile all tray icons found at <projectdir>/assets/trayicons/*.png into the application
func (d *DesktopBuilder) processTrayIcons(assetDir string, options *Options) error {
//
// var err error
//
// // Get all the tray icon filenames
// trayIconDirectory := filepath.Join(options.ProjectData.BuildDir, "tray")
//
// // If the directory doesn't exist, create it
// if !fs.DirExists(trayIconDirectory) {
// err = fs.MkDirs(trayIconDirectory)
// if err != nil {
// return err
// }
// }
//
// var trayIconFilenames []string
// trayIconFilenames, err = filepath.Glob(trayIconDirectory + "/*.png")
// if err != nil {
// log.Fatal(err)
// return err
// }
//
// // Setup target
// targetFilename := "trayicons"
// targetFile := filepath.Join(assetDir, targetFilename+".h")
// d.addFileToDelete(targetFile)
//
// var dataBytes []byte
//
// // Use a strings builder
// var cdata strings.Builder
//
// // Write header
// header := `// trayicons.h
//// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Ă‚ MODIWL.
//// This file was auto-generated. DO NOT MODIFY.
//
//`
// cdata.WriteString(header)
//
// var variableList slicer.StringSlicer
//
// // Loop over icons
// for count, filename := range trayIconFilenames {
//
// // Load the tray icon
// dataBytes, err = ioutil.ReadFile(filename)
// if err != nil {
// return err
// }
//
// iconname := strings.TrimSuffix(filepath.Base(filename), ".png")
// trayIconName := fmt.Sprintf("trayIcon%dName", count)
// variableList.Add(trayIconName)
// cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { %s0x00 };\n", trayIconName, d.convertToHexLiteral([]byte(iconname))))
//
// trayIconLength := fmt.Sprintf("trayIcon%dLength", count)
// variableList.Add(trayIconLength)
// lengthAsString := strconv.Itoa(len(dataBytes))
// cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { %s0x00 };\n", trayIconLength, d.convertToHexLiteral([]byte(lengthAsString))))
//
// trayIconData := fmt.Sprintf("trayIcon%dData", count)
// variableList.Add(trayIconData)
// cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { ", trayIconData))
//
// // Convert each byte to hex
// for _, b := range dataBytes {
// cdata.WriteString(fmt.Sprintf("0x%x, ", b))
// }
//
// cdata.WriteString("0x00 };\n")
// }
//
// // Write out main trayIcons data
// cdata.WriteString("const unsigned char *trayIcons[] = { ")
// cdata.WriteString(variableList.Join(", "))
// if len(trayIconFilenames) > 0 {
// cdata.WriteString(", ")
// }
// cdata.WriteString("0x00 };\n")
//
// err = ioutil.WriteFile(targetFile, []byte(cdata.String()), 0600)
// if err != nil {
// return err
// }
return nil
}
// We will compile all dialog icons found at <projectdir>/icons/dialog/*.png into the application
func (d *DesktopBuilder) processDialogIcons(assetDir string, options *Options) error {
// var err error
//
// // Get all the dialog icon filenames
// dialogIconDirectory := filepath.Join(options.ProjectData.BuildDir, "dialog")
// var dialogIconFilenames []string
//
// // If the directory does not exist, create it
// if !fs.DirExists(dialogIconDirectory) {
// err = fs.MkDirs(dialogIconDirectory)
// if err != nil {
// return err
// }
// }
//
// dialogIconFilenames, err = filepath.Glob(dialogIconDirectory + "/*.png")
// if err != nil {
// log.Fatal(err)
// return err
// }
//
// // Setup target
// targetFilename := "userdialogicons"
// targetFile := filepath.Join(assetDir, targetFilename+".h")
// d.addFileToDelete(targetFile)
//
// var dataBytes []byte
//
// // Use a strings builder
// var cdata strings.Builder
//
// // Write header
// header := `// userdialogicons.h
//// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Ă‚ MODIWL.
//// This file was auto-generated. DO NOT MODIFY.
//
//`
// cdata.WriteString(header)
//
// var variableList slicer.StringSlicer
//
// // Loop over icons
// for count, filename := range dialogIconFilenames {
//
// // Load the tray icon
// dataBytes, err = ioutil.ReadFile(filename)
// if err != nil {
// return err
// }
//
// iconname := strings.TrimSuffix(filepath.Base(filename), ".png")
// dialogIconName := fmt.Sprintf("userDialogIcon%dName", count)
// variableList.Add(dialogIconName)
// cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { %s0x00 };\n", dialogIconName, d.convertToHexLiteral([]byte(iconname))))
//
// dialogIconLength := fmt.Sprintf("userDialogIcon%dLength", count)
// variableList.Add(dialogIconLength)
// lengthAsString := strconv.Itoa(len(dataBytes))
// cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { %s0x00 };\n", dialogIconLength, d.convertToHexLiteral([]byte(lengthAsString))))
//
// dialogIconData := fmt.Sprintf("userDialogIcon%dData", count)
// variableList.Add(dialogIconData)
// cdata.WriteString(fmt.Sprintf("const unsigned char %s[] = { ", dialogIconData))
//
// // Convert each byte to hex
// for _, b := range dataBytes {
// cdata.WriteString(fmt.Sprintf("0x%x, ", b))
// }
//
// cdata.WriteString("0x00 };\n")
// }
//
// // Write out main dialogIcons data
// cdata.WriteString("const unsigned char *userDialogIcons[] = { ")
// cdata.WriteString(variableList.Join(", "))
// if len(dialogIconFilenames) > 0 {
// cdata.WriteString(", ")
// }
// cdata.WriteString("0x00 };\n")
//
// err = ioutil.WriteFile(targetFile, []byte(cdata.String()), 0600)
// if err != nil {
// return err
// }
return nil
}

View File

@@ -8,7 +8,7 @@ func (d *DesktopBuilder) processTrayIcons(assetDir string, options *Options) err
// var err error
//
// // Get all the tray icon filenames
// trayIconDirectory := filepath.Join(options.ProjectData.AssetsDir, "tray")
// trayIconDirectory := filepath.Join(options.ProjectData.BuildDir, "tray")
//
// // If the directory doesn't exist, create it
// if !fs.DirExists(trayIconDirectory) {
@@ -97,7 +97,7 @@ func (d *DesktopBuilder) processDialogIcons(assetDir string, options *Options) e
// var err error
//
// // Get all the dialog icon filenames
// dialogIconDirectory := filepath.Join(options.ProjectData.AssetsDir, "dialog")
// dialogIconDirectory := filepath.Join(options.ProjectData.BuildDir, "dialog")
// var dialogIconFilenames []string
//
// // If the directory does not exist, create it

View File

@@ -30,12 +30,6 @@ func (b *HybridBuilder) BuildAssets(options *Options) error {
if err != nil {
return err
}
// Build static assets
err = b.buildCustomAssets(b.projectData)
if err != nil {
return err
}
return nil
}
@@ -63,18 +57,6 @@ func (b *HybridBuilder) BuildBaseAssets(options *Options) error {
return err
}
// Build desktop static assets
err = b.desktop.buildCustomAssets(b.projectData)
if err != nil {
return err
}
// Build server static assets
err = b.server.buildCustomAssets(b.projectData)
if err != nil {
return err
}
return nil
}

View File

@@ -2,11 +2,13 @@
<plist version="1.0"><dict>
<key>CFBundlePackageType</key><string>APPL</string>
<key>CFBundleName</key><string>{{.Title}}</string>
<key>CFBundleExecutable</key><string>{{.Exe}}</string>
<key>CFBundleIdentifier</key><string>{{.PackageID}}</string>
<key>CFBundleVersion</key><string>{{.Version}}</string>
<key>CFBundleGetInfoString</key><string>Built by {{.Author}} using Wails (https://wails.app)</string>
<key>CFBundleShortVersionString</key><string>{{.Version}}</string>
<key>CFBundleExecutable</key><string>{{.Title}}</string>
<key>CFBundleIdentifier</key><string>com.wails.{{.Title}}</string>
<key>CFBundleVersion</key><string>1.0.0</string>
<key>CFBundleGetInfoString</key><string>Built using Wails (https://wails.app)</string>
<key>CFBundleShortVersionString</key><string>1.0.0</string>
<key>CFBundleIconFile</key><string>iconfile</string>
<key>LSMinimumSystemVersion</key><string>10.13.0</string>
<key>NSHighResolutionCapable</key><string>true</string>
<key>NSHumanReadableCopyright</key><string>Copyright.........</string>
</dict></plist>

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