diff --git a/v3/examples/notifications/README.md b/v3/examples/notifications/README.md new file mode 100644 index 000000000..ad12c3f40 --- /dev/null +++ b/v3/examples/notifications/README.md @@ -0,0 +1,59 @@ +# Welcome to Your New Wails3 Project! + +Congratulations on generating your Wails3 application! This README will guide you through the next steps to get your project up and running. + +## Getting Started + +1. Navigate to your project directory in the terminal. + +2. To run your application in development mode, use the following command: + + ``` + wails3 dev + ``` + + This will start your application and enable hot-reloading for both frontend and backend changes. + +3. To build your application for production, use: + + ``` + wails3 build + ``` + + This will create a production-ready executable in the `build` directory. + +## Exploring Wails3 Features + +Now that you have your project set up, it's time to explore the features that Wails3 offers: + +1. **Check out the examples**: The best way to learn is by example. Visit the `examples` directory in the `v3/examples` directory to see various sample applications. + +2. **Run an example**: To run any of the examples, navigate to the example's directory and use: + + ``` + go run . + ``` + + Note: Some examples may be under development during the alpha phase. + +3. **Explore the documentation**: Visit the [Wails3 documentation](https://v3.wails.io/) for in-depth guides and API references. + +4. **Join the community**: Have questions or want to share your progress? Join the [Wails Discord](https://discord.gg/JDdSxwjhGf) or visit the [Wails discussions on GitHub](https://github.com/wailsapp/wails/discussions). + +## Project Structure + +Take a moment to familiarize yourself with your project structure: + +- `frontend/`: Contains your frontend code (HTML, CSS, JavaScript/TypeScript) +- `main.go`: The entry point of your Go backend +- `app.go`: Define your application structure and methods here +- `wails.json`: Configuration file for your Wails project + +## Next Steps + +1. Modify the frontend in the `frontend/` directory to create your desired UI. +2. Add backend functionality in `main.go`. +3. Use `wails3 dev` to see your changes in real-time. +4. When ready, build your application with `wails3 build`. + +Happy coding with Wails3! If you encounter any issues or have questions, don't hesitate to consult the documentation or reach out to the Wails community. diff --git a/v3/examples/notifications/Taskfile.yml b/v3/examples/notifications/Taskfile.yml new file mode 100644 index 000000000..1455cd70c --- /dev/null +++ b/v3/examples/notifications/Taskfile.yml @@ -0,0 +1,34 @@ +version: '3' + +includes: + common: ./build/Taskfile.yml + windows: ./build/windows/Taskfile.yml + darwin: ./build/darwin/Taskfile.yml + linux: ./build/linux/Taskfile.yml + +vars: + APP_NAME: "Notifications\\ Demo" + BIN_DIR: "bin" + VITE_PORT: '{{.WAILS_VITE_PORT | default 9245}}' + +tasks: + build: + summary: Builds the application + cmds: + - task: "{{OS}}:build" + + package: + summary: Packages a production build of the application + cmds: + - task: "{{OS}}:package" + + run: + summary: Runs the application + cmds: + - task: "{{OS}}:run" + + dev: + summary: Runs the application in development mode + cmds: + - wails3 dev -config ./build/config.yml -port {{.VITE_PORT}} + diff --git a/v3/examples/notifications/build/Taskfile.yml b/v3/examples/notifications/build/Taskfile.yml new file mode 100644 index 000000000..5f3517efc --- /dev/null +++ b/v3/examples/notifications/build/Taskfile.yml @@ -0,0 +1,86 @@ +version: '3' + +tasks: + go:mod:tidy: + summary: Runs `go mod tidy` + internal: true + cmds: + - go mod tidy + + install:frontend:deps: + summary: Install frontend dependencies + dir: frontend + sources: + - package.json + - package-lock.json + generates: + - node_modules/* + preconditions: + - sh: npm version + msg: "Looks like npm isn't installed. Npm is part of the Node installer: https://nodejs.org/en/download/" + cmds: + - npm install + + build:frontend: + label: build:frontend (PRODUCTION={{.PRODUCTION}}) + summary: Build the frontend project + dir: frontend + sources: + - "**/*" + generates: + - dist/**/* + deps: + - task: install:frontend:deps + - task: generate:bindings + vars: + BUILD_FLAGS: + ref: .BUILD_FLAGS + cmds: + - npm run {{.BUILD_COMMAND}} -q + env: + PRODUCTION: '{{.PRODUCTION | default "false"}}' + vars: + BUILD_COMMAND: '{{if eq .PRODUCTION "true"}}build{{else}}build:dev{{end}}' + + + generate:bindings: + label: generate:bindings (BUILD_FLAGS={{.BUILD_FLAGS}}) + summary: Generates bindings for the frontend + deps: + - task: go:mod:tidy + sources: + - "**/*.[jt]s" + - exclude: frontend/**/* + - frontend/bindings/**/* # Rerun when switching between dev/production mode causes changes in output + - "**/*.go" + - go.mod + - go.sum + generates: + - frontend/bindings/**/* + cmds: + - wails3 generate bindings -f '{{.BUILD_FLAGS}}' -clean=true -ts + + generate:icons: + summary: Generates Windows `.ico` and Mac `.icns` files from an image + dir: build + sources: + - "appicon.png" + generates: + - "darwin/icons.icns" + - "windows/icon.ico" + cmds: + - wails3 generate icons -input appicon.png -macfilename darwin/icons.icns -windowsfilename windows/icon.ico + + dev:frontend: + summary: Runs the frontend in development mode + dir: frontend + deps: + - task: install:frontend:deps + cmds: + - npm run dev -- --port {{.VITE_PORT}} --strictPort + + update:build-assets: + summary: Updates the build assets + dir: build + cmds: + - wails3 update build-assets -name "{{.APP_NAME}}" -binaryname "{{.APP_NAME}}" -config config.yml -dir . diff --git a/v3/examples/notifications/build/appicon.png b/v3/examples/notifications/build/appicon.png new file mode 100644 index 000000000..63617fe4f Binary files /dev/null and b/v3/examples/notifications/build/appicon.png differ diff --git a/v3/examples/notifications/build/config.yml b/v3/examples/notifications/build/config.yml new file mode 100644 index 000000000..bc09a6d28 --- /dev/null +++ b/v3/examples/notifications/build/config.yml @@ -0,0 +1,62 @@ +# This file contains the configuration for this project. +# When you update `info` or `fileAssociations`, run `wails3 task common:update:build-assets` to update the assets. +# Note that this will overwrite any changes you have made to the assets. +version: '3' + +# This information is used to generate the build assets. +info: + companyName: "My Company" # The name of the company + productName: "My Product" # The name of the application + productIdentifier: "com.mycompany.myproduct" # The unique product identifier + description: "A program that does X" # The application description + copyright: "(c) 2025, My Company" # Copyright text + comments: "Some Product Comments" # Comments + version: "v0.0.1" # The application version + +# Dev mode configuration +dev_mode: + root_path: . + log_level: warn + debounce: 1000 + ignore: + dir: + - .git + - node_modules + - frontend + - bin + file: + - .DS_Store + - .gitignore + - .gitkeep + watched_extension: + - "*.go" + git_ignore: true + executes: + - cmd: wails3 task common:install:frontend:deps + type: once + - cmd: wails3 task common:dev:frontend + type: background + - cmd: go mod tidy + type: blocking + - cmd: wails3 task build + type: blocking + - cmd: wails3 task run + type: primary + +# File Associations +# More information at: https://v3.wails.io/noit/done/yet +fileAssociations: +# - ext: wails +# name: Wails +# description: Wails Application File +# iconName: wailsFileIcon +# role: Editor +# - ext: jpg +# name: JPEG +# description: Image File +# iconName: jpegFileIcon +# role: Editor + +# Other data +other: + - name: My Other Data \ No newline at end of file diff --git a/v3/examples/notifications/build/darwin/Info.dev.plist b/v3/examples/notifications/build/darwin/Info.dev.plist new file mode 100644 index 000000000..3a5b9735f --- /dev/null +++ b/v3/examples/notifications/build/darwin/Info.dev.plist @@ -0,0 +1,32 @@ + + + + CFBundlePackageType + APPL + CFBundleName + My Product + CFBundleExecutable + Notifications Demo + CFBundleIdentifier + com.wails.notifications-demo + CFBundleVersion + 0.1.0 + CFBundleGetInfoString + This is a comment + CFBundleShortVersionString + 0.1.0 + CFBundleIconFile + icons + LSMinimumSystemVersion + 10.15.0 + NSHighResolutionCapable + true + NSHumanReadableCopyright + © now, My Company + NSAppTransportSecurity + + NSAllowsLocalNetworking + + + + \ No newline at end of file diff --git a/v3/examples/notifications/build/darwin/Info.plist b/v3/examples/notifications/build/darwin/Info.plist new file mode 100644 index 000000000..464270019 --- /dev/null +++ b/v3/examples/notifications/build/darwin/Info.plist @@ -0,0 +1,27 @@ + + + + CFBundlePackageType + APPL + CFBundleName + My Product + CFBundleExecutable + Notifications Demo + CFBundleIdentifier + com.wails.notifications-demo + CFBundleVersion + 0.1.0 + CFBundleGetInfoString + This is a comment + CFBundleShortVersionString + 0.1.0 + CFBundleIconFile + icons + LSMinimumSystemVersion + 10.15.0 + NSHighResolutionCapable + true + NSHumanReadableCopyright + © now, My Company + + \ No newline at end of file diff --git a/v3/examples/notifications/build/darwin/Taskfile.yml b/v3/examples/notifications/build/darwin/Taskfile.yml new file mode 100644 index 000000000..3b6a9dc99 --- /dev/null +++ b/v3/examples/notifications/build/darwin/Taskfile.yml @@ -0,0 +1,80 @@ +version: '3' + +includes: + common: ../Taskfile.yml + +tasks: + build: + summary: Creates a production build of the application + deps: + - task: common:go:mod:tidy + - task: common:build:frontend + vars: + BUILD_FLAGS: + ref: .BUILD_FLAGS + PRODUCTION: + ref: .PRODUCTION + - task: common:generate:icons + cmds: + - go build {{.BUILD_FLAGS}} -o {{.OUTPUT}} + vars: + BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' + DEFAULT_OUTPUT: '{{.BIN_DIR}}/{{.APP_NAME}}' + OUTPUT: '{{ .OUTPUT | default .DEFAULT_OUTPUT }}' + env: + GOOS: darwin + CGO_ENABLED: 1 + GOARCH: '{{.ARCH | default ARCH}}' + CGO_CFLAGS: "-mmacosx-version-min=10.15" + CGO_LDFLAGS: "-mmacosx-version-min=10.15" + MACOSX_DEPLOYMENT_TARGET: "10.15" + PRODUCTION: '{{.PRODUCTION | default "false"}}' + + build:universal: + summary: Builds darwin universal binary (arm64 + amd64) + deps: + - task: build + vars: + ARCH: amd64 + OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" + - task: build + vars: + ARCH: arm64 + OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" + cmds: + - lipo -create -output "{{.BIN_DIR}}/{{.APP_NAME}}" "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" + - rm "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" + + package: + summary: Packages a production build of the application into a `.app` bundle + deps: + - task: build + vars: + PRODUCTION: "true" + cmds: + - task: create:app:bundle + + package:universal: + summary: Packages darwin universal binary (arm64 + amd64) + deps: + - task: build:universal + cmds: + - task: create:app:bundle + + + create:app:bundle: + summary: Creates an `.app` bundle + cmds: + - mkdir -p {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/{MacOS,Resources} + - cp build/darwin/icons.icns {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/Resources + - cp {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/MacOS + - cp build/darwin/Info.plist {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents + + run: + cmds: + - mkdir -p {{.BIN_DIR}}/dev/{{.APP_NAME}}.app/Contents/{MacOS,Resources} + - cp build/darwin/icons.icns {{.BIN_DIR}}/dev/{{.APP_NAME}}.app/Contents/Resources + - cp {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/dev/{{.APP_NAME}}.app/Contents/MacOS + - cp build/darwin/Info.dev.plist {{.BIN_DIR}}/dev/{{.APP_NAME}}.app/Contents/Info.plist + - codesign --force --deep --sign - {{.BIN_DIR}}/dev/{{.APP_NAME}}.app + - '{{.BIN_DIR}}/dev/{{.APP_NAME}}.app/Contents/MacOS/{{.APP_NAME}}' diff --git a/v3/examples/notifications/build/darwin/icons.icns b/v3/examples/notifications/build/darwin/icons.icns new file mode 100644 index 000000000..1b5bd4c86 Binary files /dev/null and b/v3/examples/notifications/build/darwin/icons.icns differ diff --git a/v3/examples/notifications/build/linux/Taskfile.yml b/v3/examples/notifications/build/linux/Taskfile.yml new file mode 100644 index 000000000..560cc9c92 --- /dev/null +++ b/v3/examples/notifications/build/linux/Taskfile.yml @@ -0,0 +1,119 @@ +version: '3' + +includes: + common: ../Taskfile.yml + +tasks: + build: + summary: Builds the application for Linux + deps: + - task: common:go:mod:tidy + - task: common:build:frontend + vars: + BUILD_FLAGS: + ref: .BUILD_FLAGS + PRODUCTION: + ref: .PRODUCTION + - task: common:generate:icons + cmds: + - go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}} + vars: + BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' + env: + GOOS: linux + CGO_ENABLED: 1 + GOARCH: '{{.ARCH | default ARCH}}' + PRODUCTION: '{{.PRODUCTION | default "false"}}' + + package: + summary: Packages a production build of the application for Linux + deps: + - task: build + vars: + PRODUCTION: "true" + cmds: + - task: create:appimage + - task: create:deb + - task: create:rpm + - task: create:aur + + create:appimage: + summary: Creates an AppImage + dir: build/linux/appimage + deps: + - task: build + vars: + PRODUCTION: "true" + - task: generate:dotdesktop + cmds: + - cp {{.APP_BINARY}} {{.APP_NAME}} + - cp ../../appicon.png appicon.png + - wails3 generate appimage -binary {{.APP_NAME}} -icon {{.ICON}} -desktopfile {{.DESKTOP_FILE}} -outputdir {{.OUTPUT_DIR}} -builddir {{.ROOT_DIR}}/build/linux/appimage/build + vars: + APP_NAME: '{{.APP_NAME}}' + APP_BINARY: '../../../bin/{{.APP_NAME}}' + ICON: '../../appicon.png' + DESKTOP_FILE: '../{{.APP_NAME}}.desktop' + OUTPUT_DIR: '../../../bin' + + create:deb: + summary: Creates a deb package + deps: + - task: build + vars: + PRODUCTION: "true" + cmds: + - task: generate:dotdesktop + - task: generate:deb + + create:rpm: + summary: Creates a rpm package + deps: + - task: build + vars: + PRODUCTION: "true" + cmds: + - task: generate:dotdesktop + - task: generate:rpm + + create:aur: + summary: Creates a arch linux packager package + deps: + - task: build + vars: + PRODUCTION: "true" + cmds: + - task: generate:dotdesktop + - task: generate:aur + + generate:deb: + summary: Creates a deb package + cmds: + - wails3 tool package -name {{.APP_NAME}} -format deb -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin + + generate:rpm: + summary: Creates a rpm package + cmds: + - wails3 tool package -name {{.APP_NAME}} -format rpm -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin + + generate:aur: + summary: Creates a arch linux packager package + cmds: + - wails3 tool package -name {{.APP_NAME}} -format archlinux -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin + + generate:dotdesktop: + summary: Generates a `.desktop` file + dir: build + cmds: + - mkdir -p {{.ROOT_DIR}}/build/linux/appimage + - wails3 generate .desktop -name "{{.APP_NAME}}" -exec "{{.EXEC}}" -icon "{{.ICON}}" -outputfile {{.ROOT_DIR}}/build/linux/{{.APP_NAME}}.desktop -categories "{{.CATEGORIES}}" + vars: + APP_NAME: '{{.APP_NAME}}' + EXEC: '{{.APP_NAME}}' + ICON: 'appicon' + CATEGORIES: 'Development;' + OUTPUTFILE: '{{.ROOT_DIR}}/build/linux/{{.APP_NAME}}.desktop' + + run: + cmds: + - '{{.BIN_DIR}}/{{.APP_NAME}}' diff --git a/v3/examples/notifications/build/linux/appimage/build.sh b/v3/examples/notifications/build/linux/appimage/build.sh new file mode 100644 index 000000000..85901c34e --- /dev/null +++ b/v3/examples/notifications/build/linux/appimage/build.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# Copyright (c) 2018-Present Lea Anthony +# SPDX-License-Identifier: MIT + +# Fail script on any error +set -euxo pipefail + +# Define variables +APP_DIR="${APP_NAME}.AppDir" + +# Create AppDir structure +mkdir -p "${APP_DIR}/usr/bin" +cp -r "${APP_BINARY}" "${APP_DIR}/usr/bin/" +cp "${ICON_PATH}" "${APP_DIR}/" +cp "${DESKTOP_FILE}" "${APP_DIR}/" + +if [[ $(uname -m) == *x86_64* ]]; then + # Download linuxdeploy and make it executable + wget -q -4 -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage + chmod +x linuxdeploy-x86_64.AppImage + + # Run linuxdeploy to bundle the application + ./linuxdeploy-x86_64.AppImage --appdir "${APP_DIR}" --output appimage +else + # Download linuxdeploy and make it executable (arm64) + wget -q -4 -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-aarch64.AppImage + chmod +x linuxdeploy-aarch64.AppImage + + # Run linuxdeploy to bundle the application (arm64) + ./linuxdeploy-aarch64.AppImage --appdir "${APP_DIR}" --output appimage +fi + +# Rename the generated AppImage +mv "${APP_NAME}*.AppImage" "${APP_NAME}.AppImage" + diff --git a/v3/examples/notifications/build/linux/nfpm/nfpm.yaml b/v3/examples/notifications/build/linux/nfpm/nfpm.yaml new file mode 100644 index 000000000..c2cb7cd81 --- /dev/null +++ b/v3/examples/notifications/build/linux/nfpm/nfpm.yaml @@ -0,0 +1,50 @@ +# Feel free to remove those if you don't want/need to use them. +# Make sure to check the documentation at https://nfpm.goreleaser.com +# +# The lines below are called `modelines`. See `:help modeline` + +name: "notifications" +arch: ${GOARCH} +platform: "linux" +version: "0.1.0" +section: "default" +priority: "extra" +maintainer: ${GIT_COMMITTER_NAME} <${GIT_COMMITTER_EMAIL}> +description: "My Product Description" +vendor: "My Company" +homepage: "https://wails.io" +license: "MIT" +release: "1" + +contents: + - src: "./bin/notifications" + dst: "/usr/local/bin/notifications" + - src: "./build/appicon.png" + dst: "/usr/share/icons/hicolor/128x128/apps/notifications.png" + - src: "./build/linux/notifications.desktop" + dst: "/usr/share/applications/notifications.desktop" + +depends: + - gtk3 + - libwebkit2gtk + +# replaces: +# - foobar +# provides: +# - bar +# depends: +# - gtk3 +# - libwebkit2gtk +# recommends: +# - whatever +# suggests: +# - something-else +# conflicts: +# - not-foo +# - not-bar +# changelog: "changelog.yaml" +# scripts: +# preinstall: ./build/linux/nfpm/scripts/preinstall.sh +# postinstall: ./build/linux/nfpm/scripts/postinstall.sh +# preremove: ./build/linux/nfpm/scripts/preremove.sh +# postremove: ./build/linux/nfpm/scripts/postremove.sh diff --git a/v3/examples/notifications/build/linux/nfpm/scripts/postinstall.sh b/v3/examples/notifications/build/linux/nfpm/scripts/postinstall.sh new file mode 100644 index 000000000..a9bf588e2 --- /dev/null +++ b/v3/examples/notifications/build/linux/nfpm/scripts/postinstall.sh @@ -0,0 +1 @@ +#!/bin/bash diff --git a/v3/examples/notifications/build/linux/nfpm/scripts/postremove.sh b/v3/examples/notifications/build/linux/nfpm/scripts/postremove.sh new file mode 100644 index 000000000..a9bf588e2 --- /dev/null +++ b/v3/examples/notifications/build/linux/nfpm/scripts/postremove.sh @@ -0,0 +1 @@ +#!/bin/bash diff --git a/v3/examples/notifications/build/linux/nfpm/scripts/preinstall.sh b/v3/examples/notifications/build/linux/nfpm/scripts/preinstall.sh new file mode 100644 index 000000000..a9bf588e2 --- /dev/null +++ b/v3/examples/notifications/build/linux/nfpm/scripts/preinstall.sh @@ -0,0 +1 @@ +#!/bin/bash diff --git a/v3/examples/notifications/build/linux/nfpm/scripts/preremove.sh b/v3/examples/notifications/build/linux/nfpm/scripts/preremove.sh new file mode 100644 index 000000000..a9bf588e2 --- /dev/null +++ b/v3/examples/notifications/build/linux/nfpm/scripts/preremove.sh @@ -0,0 +1 @@ +#!/bin/bash diff --git a/v3/examples/notifications/build/windows/Taskfile.yml b/v3/examples/notifications/build/windows/Taskfile.yml new file mode 100644 index 000000000..534f4fb31 --- /dev/null +++ b/v3/examples/notifications/build/windows/Taskfile.yml @@ -0,0 +1,63 @@ +version: '3' + +includes: + common: ../Taskfile.yml + +tasks: + build: + summary: Builds the application for Windows + deps: + - task: common:go:mod:tidy + - task: common:build:frontend + vars: + BUILD_FLAGS: + ref: .BUILD_FLAGS + PRODUCTION: + ref: .PRODUCTION + - task: common:generate:icons + cmds: + - task: generate:syso + - go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}}.exe + - cmd: powershell Remove-item *.syso + platforms: [windows] + - cmd: rm -f *.syso + platforms: [linux, darwin] + vars: + BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s -H windowsgui"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' + env: + GOOS: windows + CGO_ENABLED: 0 + GOARCH: '{{.ARCH | default ARCH}}' + PRODUCTION: '{{.PRODUCTION | default "false"}}' + + package: + summary: Packages a production build of the application into a `.exe` bundle + cmds: + - task: create:nsis:installer + + generate:syso: + summary: Generates Windows `.syso` file + dir: build + cmds: + - wails3 generate syso -arch {{.ARCH}} -icon windows/icon.ico -manifest windows/wails.exe.manifest -info windows/info.json -out ../wails_windows_{{.ARCH}}.syso + vars: + ARCH: '{{.ARCH | default ARCH}}' + + create:nsis:installer: + summary: Creates an NSIS installer + dir: build/windows/nsis + deps: + - task: build + vars: + PRODUCTION: "true" + cmds: + # Create the Microsoft WebView2 bootstrapper if it doesn't exist + - wails3 generate webview2bootstrapper -dir "{{.ROOT_DIR}}/build/windows/nsis" + - makensis -DARG_WAILS_{{.ARG_FLAG}}_BINARY="{{.ROOT_DIR}}/{{.BIN_DIR}}/{{.APP_NAME}}.exe" project.nsi + vars: + ARCH: '{{.ARCH | default ARCH}}' + ARG_FLAG: '{{if eq .ARCH "amd64"}}AMD64{{else}}ARM64{{end}}' + + run: + cmds: + - '{{.BIN_DIR}}/{{.APP_NAME}}.exe' diff --git a/v3/examples/notifications/build/windows/icon.ico b/v3/examples/notifications/build/windows/icon.ico new file mode 100644 index 000000000..bfa0690b7 Binary files /dev/null and b/v3/examples/notifications/build/windows/icon.ico differ diff --git a/v3/examples/notifications/build/windows/info.json b/v3/examples/notifications/build/windows/info.json new file mode 100644 index 000000000..850b2b5b0 --- /dev/null +++ b/v3/examples/notifications/build/windows/info.json @@ -0,0 +1,15 @@ +{ + "fixed": { + "file_version": "0.1.0" + }, + "info": { + "0000": { + "ProductVersion": "0.1.0", + "CompanyName": "My Company", + "FileDescription": "My Product Description", + "LegalCopyright": "© now, My Company", + "ProductName": "My Product", + "Comments": "This is a comment" + } + } +} \ No newline at end of file diff --git a/v3/examples/notifications/build/windows/nsis/project.nsi b/v3/examples/notifications/build/windows/nsis/project.nsi new file mode 100644 index 000000000..4cb18e04f --- /dev/null +++ b/v3/examples/notifications/build/windows/nsis/project.nsi @@ -0,0 +1,112 @@ +Unicode true + +#### +## Please note: Template replacements don't work in this file. They are provided with default defines like +## mentioned underneath. +## If the keyword is not defined, "wails_tools.nsh" will populate them. +## If they are defined here, "wails_tools.nsh" will not touch them. This allows you to use this project.nsi manually +## from outside of Wails for debugging and development of the installer. +## +## For development first make a wails nsis build to populate the "wails_tools.nsh": +## > wails build --target windows/amd64 --nsis +## Then you can call makensis on this file with specifying the path to your binary: +## For a AMD64 only installer: +## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app.exe +## For a ARM64 only installer: +## > makensis -DARG_WAILS_ARM64_BINARY=..\..\bin\app.exe +## For a installer with both architectures: +## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app-amd64.exe -DARG_WAILS_ARM64_BINARY=..\..\bin\app-arm64.exe +#### +## The following information is taken from the wails_tools.nsh file, but they can be overwritten here. +#### +## !define INFO_PROJECTNAME "my-project" # Default "notifications" +## !define INFO_COMPANYNAME "My Company" # Default "My Company" +## !define INFO_PRODUCTNAME "My Product Name" # Default "My Product" +## !define INFO_PRODUCTVERSION "1.0.0" # Default "0.1.0" +## !define INFO_COPYRIGHT "(c) Now, My Company" # Default "© now, My Company" +### +## !define PRODUCT_EXECUTABLE "Application.exe" # Default "${INFO_PROJECTNAME}.exe" +## !define UNINST_KEY_NAME "UninstKeyInRegistry" # Default "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" +#### +## !define REQUEST_EXECUTION_LEVEL "admin" # Default "admin" see also https://nsis.sourceforge.io/Docs/Chapter4.html +#### +## Include the wails tools +#### +!include "wails_tools.nsh" + +# The version information for this two must consist of 4 parts +VIProductVersion "${INFO_PRODUCTVERSION}.0" +VIFileVersion "${INFO_PRODUCTVERSION}.0" + +VIAddVersionKey "CompanyName" "${INFO_COMPANYNAME}" +VIAddVersionKey "FileDescription" "${INFO_PRODUCTNAME} Installer" +VIAddVersionKey "ProductVersion" "${INFO_PRODUCTVERSION}" +VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}" +VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}" +VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}" + +# Enable HiDPI support. https://nsis.sourceforge.io/Reference/ManifestDPIAware +ManifestDPIAware true + +!include "MUI.nsh" + +!define MUI_ICON "..\icon.ico" +!define MUI_UNICON "..\icon.ico" +# !define MUI_WELCOMEFINISHPAGE_BITMAP "resources\leftimage.bmp" #Include this to add a bitmap on the left side of the Welcome Page. Must be a size of 164x314 +!define MUI_FINISHPAGE_NOAUTOCLOSE # Wait on the INSTFILES page so the user can take a look into the details of the installation steps +!define MUI_ABORTWARNING # This will warn the user if they exit from the installer. + +!insertmacro MUI_PAGE_WELCOME # Welcome to the installer page. +# !insertmacro MUI_PAGE_LICENSE "resources\eula.txt" # Adds a EULA page to the installer +!insertmacro MUI_PAGE_DIRECTORY # In which folder install page. +!insertmacro MUI_PAGE_INSTFILES # Installing page. +!insertmacro MUI_PAGE_FINISH # Finished installation page. + +!insertmacro MUI_UNPAGE_INSTFILES # Uninstalling page + +!insertmacro MUI_LANGUAGE "English" # Set the Language of the installer + +## The following two statements can be used to sign the installer and the uninstaller. The path to the binaries are provided in %1 +#!uninstfinalize 'signtool --file "%1"' +#!finalize 'signtool --file "%1"' + +Name "${INFO_PRODUCTNAME}" +OutFile "..\..\..\bin\${INFO_PROJECTNAME}-${ARCH}-installer.exe" # Name of the installer's file. +InstallDir "$PROGRAMFILES64\${INFO_COMPANYNAME}\${INFO_PRODUCTNAME}" # Default installing folder ($PROGRAMFILES is Program Files folder). +ShowInstDetails show # This will always show the installation details. + +Function .onInit + !insertmacro wails.checkArchitecture +FunctionEnd + +Section + !insertmacro wails.setShellContext + + !insertmacro wails.webview2runtime + + SetOutPath $INSTDIR + + !insertmacro wails.files + + CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" + CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" + + !insertmacro wails.associateFiles + + !insertmacro wails.writeUninstaller +SectionEnd + +Section "uninstall" + !insertmacro wails.setShellContext + + RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath + + RMDir /r $INSTDIR + + Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" + Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk" + + !insertmacro wails.unassociateFiles + + !insertmacro wails.deleteUninstaller +SectionEnd diff --git a/v3/examples/notifications/build/windows/nsis/wails_tools.nsh b/v3/examples/notifications/build/windows/nsis/wails_tools.nsh new file mode 100644 index 000000000..ee4c8ca1a --- /dev/null +++ b/v3/examples/notifications/build/windows/nsis/wails_tools.nsh @@ -0,0 +1,212 @@ +# DO NOT EDIT - Generated automatically by `wails build` + +!include "x64.nsh" +!include "WinVer.nsh" +!include "FileFunc.nsh" + +!ifndef INFO_PROJECTNAME + !define INFO_PROJECTNAME "notifications" +!endif +!ifndef INFO_COMPANYNAME + !define INFO_COMPANYNAME "My Company" +!endif +!ifndef INFO_PRODUCTNAME + !define INFO_PRODUCTNAME "My Product" +!endif +!ifndef INFO_PRODUCTVERSION + !define INFO_PRODUCTVERSION "0.1.0" +!endif +!ifndef INFO_COPYRIGHT + !define INFO_COPYRIGHT "© now, My Company" +!endif +!ifndef PRODUCT_EXECUTABLE + !define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe" +!endif +!ifndef UNINST_KEY_NAME + !define UNINST_KEY_NAME "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" +!endif +!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINST_KEY_NAME}" + +!ifndef REQUEST_EXECUTION_LEVEL + !define REQUEST_EXECUTION_LEVEL "admin" +!endif + +RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}" + +!ifdef ARG_WAILS_AMD64_BINARY + !define SUPPORTS_AMD64 +!endif + +!ifdef ARG_WAILS_ARM64_BINARY + !define SUPPORTS_ARM64 +!endif + +!ifdef SUPPORTS_AMD64 + !ifdef SUPPORTS_ARM64 + !define ARCH "amd64_arm64" + !else + !define ARCH "amd64" + !endif +!else + !ifdef SUPPORTS_ARM64 + !define ARCH "arm64" + !else + !error "Wails: Undefined ARCH, please provide at least one of ARG_WAILS_AMD64_BINARY or ARG_WAILS_ARM64_BINARY" + !endif +!endif + +!macro wails.checkArchitecture + !ifndef WAILS_WIN10_REQUIRED + !define WAILS_WIN10_REQUIRED "This product is only supported on Windows 10 (Server 2016) and later." + !endif + + !ifndef WAILS_ARCHITECTURE_NOT_SUPPORTED + !define WAILS_ARCHITECTURE_NOT_SUPPORTED "This product can't be installed on the current Windows architecture. Supports: ${ARCH}" + !endif + + ${If} ${AtLeastWin10} + !ifdef SUPPORTS_AMD64 + ${if} ${IsNativeAMD64} + Goto ok + ${EndIf} + !endif + + !ifdef SUPPORTS_ARM64 + ${if} ${IsNativeARM64} + Goto ok + ${EndIf} + !endif + + IfSilent silentArch notSilentArch + silentArch: + SetErrorLevel 65 + Abort + notSilentArch: + MessageBox MB_OK "${WAILS_ARCHITECTURE_NOT_SUPPORTED}" + Quit + ${else} + IfSilent silentWin notSilentWin + silentWin: + SetErrorLevel 64 + Abort + notSilentWin: + MessageBox MB_OK "${WAILS_WIN10_REQUIRED}" + Quit + ${EndIf} + + ok: +!macroend + +!macro wails.files + !ifdef SUPPORTS_AMD64 + ${if} ${IsNativeAMD64} + File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_AMD64_BINARY}" + ${EndIf} + !endif + + !ifdef SUPPORTS_ARM64 + ${if} ${IsNativeARM64} + File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_ARM64_BINARY}" + ${EndIf} + !endif +!macroend + +!macro wails.writeUninstaller + WriteUninstaller "$INSTDIR\uninstall.exe" + + SetRegView 64 + WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${INFO_COMPANYNAME}" + WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${INFO_PRODUCTNAME}" + WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${INFO_PRODUCTVERSION}" + WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_EXECUTABLE}" + WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" + WriteRegStr HKLM "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" + + ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 + IntFmt $0 "0x%08X" $0 + WriteRegDWORD HKLM "${UNINST_KEY}" "EstimatedSize" "$0" +!macroend + +!macro wails.deleteUninstaller + Delete "$INSTDIR\uninstall.exe" + + SetRegView 64 + DeleteRegKey HKLM "${UNINST_KEY}" +!macroend + +!macro wails.setShellContext + ${If} ${REQUEST_EXECUTION_LEVEL} == "admin" + SetShellVarContext all + ${else} + SetShellVarContext current + ${EndIf} +!macroend + +# Install webview2 by launching the bootstrapper +# See https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#online-only-deployment +!macro wails.webview2runtime + !ifndef WAILS_INSTALL_WEBVIEW_DETAILPRINT + !define WAILS_INSTALL_WEBVIEW_DETAILPRINT "Installing: WebView2 Runtime" + !endif + + SetRegView 64 + # If the admin key exists and is not empty then webview2 is already installed + ReadRegStr $0 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" + ${If} $0 != "" + Goto ok + ${EndIf} + + ${If} ${REQUEST_EXECUTION_LEVEL} == "user" + # If the installer is run in user level, check the user specific key exists and is not empty then webview2 is already installed + ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" + ${If} $0 != "" + Goto ok + ${EndIf} + ${EndIf} + + SetDetailsPrint both + DetailPrint "${WAILS_INSTALL_WEBVIEW_DETAILPRINT}" + SetDetailsPrint listonly + + InitPluginsDir + CreateDirectory "$pluginsdir\webview2bootstrapper" + SetOutPath "$pluginsdir\webview2bootstrapper" + File "MicrosoftEdgeWebview2Setup.exe" + ExecWait '"$pluginsdir\webview2bootstrapper\MicrosoftEdgeWebview2Setup.exe" /silent /install' + + SetDetailsPrint both + ok: +!macroend + +# Copy of APP_ASSOCIATE and APP_UNASSOCIATE macros from here https://gist.github.com/nikku/281d0ef126dbc215dd58bfd5b3a5cd5b +!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND + ; Backup the previously associated file class + ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" "" + WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0" + + WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}" + + WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}` + WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}` + WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" "open" + WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open" "" `${COMMANDTEXT}` + WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open\command" "" `${COMMAND}` +!macroend + +!macro APP_UNASSOCIATE EXT FILECLASS + ; Backup the previously associated file class + ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" `${FILECLASS}_backup` + WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "$R0" + + DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}` +!macroend + +!macro wails.associateFiles + ; Create file associations + +!macroend + +!macro wails.unassociateFiles + ; Delete app associations + +!macroend \ No newline at end of file diff --git a/v3/examples/notifications/build/windows/wails.exe.manifest b/v3/examples/notifications/build/windows/wails.exe.manifest new file mode 100644 index 000000000..0299e62ca --- /dev/null +++ b/v3/examples/notifications/build/windows/wails.exe.manifest @@ -0,0 +1,15 @@ + + + + + + + + + + + true/pm + permonitorv2,permonitor + + + \ No newline at end of file diff --git a/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/index.js b/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/index.js deleted file mode 100644 index eb8893845..000000000 --- a/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/index.js +++ /dev/null @@ -1,25 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -import * as $models from "./models.js"; - -/** - * NotificationAction represents an action button for a notification - * @typedef {$models.NotificationAction} NotificationAction - */ - -/** - * NotificationCategory groups actions for notifications - * @typedef {$models.NotificationCategory} NotificationCategory - */ - -/** - * NotificationOptions contains configuration for a notification - * @typedef {$models.NotificationOptions} NotificationOptions - */ diff --git a/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/index.ts b/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/index.ts new file mode 100644 index 000000000..bbdce6579 --- /dev/null +++ b/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/index.ts @@ -0,0 +1,13 @@ +// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL +// This file is automatically generated. DO NOT EDIT + +import * as Service from "./service.js"; +export { + Service +}; + +export { + NotificationAction, + NotificationCategory, + NotificationOptions +} from "./models.js"; diff --git a/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/models.js b/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/models.js deleted file mode 100644 index 1b53de966..000000000 --- a/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/models.js +++ /dev/null @@ -1,36 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import {Create as $Create} from "@wailsio/runtime"; - -/** - * NotificationAction represents an action button for a notification - * @typedef {Object} NotificationAction - * @property {string} [id] - * @property {string} [title] - * @property {boolean} [destructive] - (macOS-specific) - */ - -/** - * NotificationCategory groups actions for notifications - * @typedef {Object} NotificationCategory - * @property {string} [id] - * @property {NotificationAction[]} [actions] - * @property {boolean} [hasReplyField] - * @property {string} [replyPlaceholder] - * @property {string} [replyButtonTitle] - */ - -/** - * NotificationOptions contains configuration for a notification - * @typedef {Object} NotificationOptions - * @property {string} [id] - * @property {string} [title] - * @property {string} [subtitle] - (macOS-specific) - * @property {string} [body] - * @property {string} [categoryId] - * @property {{ [_: string]: any }} [data] - */ diff --git a/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/models.ts b/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/models.ts new file mode 100644 index 000000000..d7f48edfe --- /dev/null +++ b/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/models.ts @@ -0,0 +1,107 @@ +// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL +// This file is automatically generated. DO NOT EDIT + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore: Unused imports +import { Create as $Create } from "@wailsio/runtime"; + +/** + * NotificationAction represents an action button for a notification. + */ +export class NotificationAction { + "id"?: string; + "title"?: string; + + /** + * (macOS-specific) + */ + "destructive"?: boolean; + + /** Creates a new NotificationAction instance. */ + constructor($$source: Partial = {}) { + + Object.assign(this, $$source); + } + + /** + * Creates a new NotificationAction instance from a string or object. + */ + static createFrom($$source: any = {}): NotificationAction { + let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; + return new NotificationAction($$parsedSource as Partial); + } +} + +/** + * NotificationCategory groups actions for notifications. + */ +export class NotificationCategory { + "id"?: string; + "actions"?: NotificationAction[]; + "hasReplyField"?: boolean; + "replyPlaceholder"?: string; + "replyButtonTitle"?: string; + + /** Creates a new NotificationCategory instance. */ + constructor($$source: Partial = {}) { + + Object.assign(this, $$source); + } + + /** + * Creates a new NotificationCategory instance from a string or object. + */ + static createFrom($$source: any = {}): NotificationCategory { + const $$createField1_0 = $$createType1; + let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; + if ("actions" in $$parsedSource) { + $$parsedSource["actions"] = $$createField1_0($$parsedSource["actions"]); + } + return new NotificationCategory($$parsedSource as Partial); + } +} + +/** + * NotificationOptions contains configuration for a notification + */ +export class NotificationOptions { + "id": string; + "title": string; + + /** + * (macOS and Linux only) + */ + "subtitle"?: string; + "body"?: string; + "categoryId"?: string; + "data"?: { [_: string]: any }; + + /** Creates a new NotificationOptions instance. */ + constructor($$source: Partial = {}) { + if (!("id" in $$source)) { + this["id"] = ""; + } + if (!("title" in $$source)) { + this["title"] = ""; + } + + Object.assign(this, $$source); + } + + /** + * Creates a new NotificationOptions instance from a string or object. + */ + static createFrom($$source: any = {}): NotificationOptions { + const $$createField5_0 = $$createType2; + let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; + if ("data" in $$parsedSource) { + $$parsedSource["data"] = $$createField5_0($$parsedSource["data"]); + } + return new NotificationOptions($$parsedSource as Partial); + } +} + +// Private type creation functions +const $$createType0 = NotificationAction.createFrom; +const $$createType1 = $Create.Array($$createType0); +const $$createType2 = $Create.Map($Create.Any, $Create.Any); diff --git a/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/service.js b/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/service.js deleted file mode 100644 index 40c55b4a9..000000000 --- a/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/service.js +++ /dev/null @@ -1,131 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * Service represents the notifications service - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import {Call as $Call, Create as $Create} from "@wailsio/runtime"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * CheckNotificationAuthorization checks current notification permission status. - * @returns {Promise & { cancel(): void }} - */ -export function CheckNotificationAuthorization() { - let $resultPromise = /** @type {any} */($Call.ByID(2789931702)); - return $resultPromise; -} - -/** - * RegisterNotificationCategory registers a new NotificationCategory to be used with SendNotificationWithActions. - * Registering a category with the same name as a previously registered NotificationCategory will override it. - * @param {$models.NotificationCategory} category - * @returns {Promise & { cancel(): void }} - */ -export function RegisterNotificationCategory(category) { - let $resultPromise = /** @type {any} */($Call.ByID(2679064664, category)); - return $resultPromise; -} - -/** - * RemoveAllDeliveredNotifications removes all delivered notifications. - * @returns {Promise & { cancel(): void }} - */ -export function RemoveAllDeliveredNotifications() { - let $resultPromise = /** @type {any} */($Call.ByID(384520397)); - return $resultPromise; -} - -/** - * RemoveAllPendingNotifications removes all pending notifications. - * @returns {Promise & { cancel(): void }} - */ -export function RemoveAllPendingNotifications() { - let $resultPromise = /** @type {any} */($Call.ByID(1423986276)); - return $resultPromise; -} - -/** - * RemoveDeliveredNotification removes a delivered notification matching the unique identifier. - * @param {string} identifier - * @returns {Promise & { cancel(): void }} - */ -export function RemoveDeliveredNotification(identifier) { - let $resultPromise = /** @type {any} */($Call.ByID(149440045, identifier)); - return $resultPromise; -} - -/** - * RemoveNotification is a macOS stub that always returns nil. - * Use one of the following instead: - * RemoveAllPendingNotifications - * RemovePendingNotification - * RemoveAllDeliveredNotifications - * RemoveDeliveredNotification - * (Linux-specific) - * @param {string} identifier - * @returns {Promise & { cancel(): void }} - */ -export function RemoveNotification(identifier) { - let $resultPromise = /** @type {any} */($Call.ByID(3702062929, identifier)); - return $resultPromise; -} - -/** - * RemoveNotificationCategory remove a previously registered NotificationCategory. - * @param {string} categoryId - * @returns {Promise & { cancel(): void }} - */ -export function RemoveNotificationCategory(categoryId) { - let $resultPromise = /** @type {any} */($Call.ByID(229511469, categoryId)); - return $resultPromise; -} - -/** - * RemovePendingNotification removes a pending notification matching the unique identifier. - * @param {string} identifier - * @returns {Promise & { cancel(): void }} - */ -export function RemovePendingNotification(identifier) { - let $resultPromise = /** @type {any} */($Call.ByID(3872412470, identifier)); - return $resultPromise; -} - -/** - * RequestNotificationAuthorization requests permission for notifications. - * @returns {Promise & { cancel(): void }} - */ -export function RequestNotificationAuthorization() { - let $resultPromise = /** @type {any} */($Call.ByID(729898933)); - return $resultPromise; -} - -/** - * SendNotification sends a basic notification with a unique identifier, title, subtitle, and body. - * @param {$models.NotificationOptions} options - * @returns {Promise & { cancel(): void }} - */ -export function SendNotification(options) { - let $resultPromise = /** @type {any} */($Call.ByID(2246903123, options)); - return $resultPromise; -} - -/** - * SendNotificationWithActions sends a notification with additional actions and inputs. - * A NotificationCategory must be registered with RegisterNotificationCategory first. The `CategoryID` must match the registered category. - * If a NotificationCategory is not registered a basic notification will be sent. - * @param {$models.NotificationOptions} options - * @returns {Promise & { cancel(): void }} - */ -export function SendNotificationWithActions(options) { - let $resultPromise = /** @type {any} */($Call.ByID(1615199806, options)); - return $resultPromise; -} diff --git a/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/service.ts b/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/service.ts new file mode 100644 index 000000000..28f1cb3b2 --- /dev/null +++ b/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/service.ts @@ -0,0 +1,62 @@ +// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL +// This file is automatically generated. DO NOT EDIT + +/** + * Service represents the notifications service + * @module + */ + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore: Unused imports +import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "@wailsio/runtime"; + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore: Unused imports +import * as $models from "./models.js"; + +export function CheckNotificationAuthorization(): $CancellablePromise { + return $Call.ByID(2789931702); +} + +export function RegisterNotificationCategory(category: $models.NotificationCategory): $CancellablePromise { + return $Call.ByID(2679064664, category); +} + +export function RemoveAllDeliveredNotifications(): $CancellablePromise { + return $Call.ByID(384520397); +} + +export function RemoveAllPendingNotifications(): $CancellablePromise { + return $Call.ByID(1423986276); +} + +export function RemoveDeliveredNotification(identifier: string): $CancellablePromise { + return $Call.ByID(149440045, identifier); +} + +export function RemoveNotification(identifier: string): $CancellablePromise { + return $Call.ByID(3702062929, identifier); +} + +export function RemoveNotificationCategory(categoryID: string): $CancellablePromise { + return $Call.ByID(229511469, categoryID); +} + +export function RemovePendingNotification(identifier: string): $CancellablePromise { + return $Call.ByID(3872412470, identifier); +} + +/** + * Public methods that delegate to the implementation. + */ +export function RequestNotificationAuthorization(): $CancellablePromise { + return $Call.ByID(729898933); +} + +export function SendNotification(options: $models.NotificationOptions): $CancellablePromise { + return $Call.ByID(2246903123, options); +} + +export function SendNotificationWithActions(options: $models.NotificationOptions): $CancellablePromise { + return $Call.ByID(1615199806, options); +} diff --git a/v3/examples/notifications/frontend/index.html b/v3/examples/notifications/frontend/index.html index 3c0d45f85..ae067c8a2 100644 --- a/v3/examples/notifications/frontend/index.html +++ b/v3/examples/notifications/frontend/index.html @@ -13,17 +13,18 @@ - - + + -

Wails + Javascript

- - + diff --git a/v3/examples/notifications/frontend/main.js b/v3/examples/notifications/frontend/main.js deleted file mode 100644 index 781f8983e..000000000 --- a/v3/examples/notifications/frontend/main.js +++ /dev/null @@ -1,67 +0,0 @@ -import * as Notifications from "./bindings/github.com/wailsapp/wails/v3/pkg/services/notifications"; -import { Events } from "@wailsio/runtime"; - -const notificationsElement = document.getElementById('notifications'); - -window.sendNotification = async () => { - const granted = await Notifications.Service.RequestNotificationAuthorization(); - if (granted) { - await Notifications.Service.SendNotification({ - id: crypto.randomUUID(), - title: "Title", - body: "Body!", - data: { - messageId: "msg-123", - senderId: "user-123", - timestamp: Date.now(), - } - }); - } -} - -window.sendComplexNotification = async () => { - const granted = await Notifications.Service.RequestNotificationAuthorization(); - if (granted) { - await Notifications.Service.RegisterNotificationCategory({ - id: "FRONTEND_NOTIF", - actions: [ - { id: "VIEW_ACTION", title: "View" }, - { id: "MARK_READ_ACTION", title: "Mark as Read" }, - ], - hasReplyField: true, - replyButtonTitle: "Reply", - replyPlaceholder: "Reply to frontend...", - }); - - await Notifications.Service.SendNotificationWithActions({ - id: crypto.randomUUID(), - title: "Complex Frontend Notification", - subtitle: "From: Jane Doe", - body: "Is it rainging today where you are?", - categoryId: "FRONTEND_NOTIF", - data: { - messageId: "msg-456", - senderId: "user-456", - timestamp: Date.now(), - } - }); - } -} - -window.removeNotification = async (id) => { - const granted = await Notifications.Service.RequestNotificationAuthorization(); - if (granted) { - await Notifications.Service.RemoveDeliveredNotification(id); - } -} - -window.removeAllNotifications = async (id) => { - const granted = await Notifications.Service.RequestNotificationAuthorization(); - if (granted) { - await Notifications.Service.RemoveAllDeliveredNotifications(); - } -} - -Events.On("notification:response", (response) => { - notificationsElement.innerText = JSON.stringify(response.data[0]); -}); \ No newline at end of file diff --git a/v3/examples/notifications/frontend/package-lock.json b/v3/examples/notifications/frontend/package-lock.json new file mode 100644 index 000000000..cdd50c49d --- /dev/null +++ b/v3/examples/notifications/frontend/package-lock.json @@ -0,0 +1,935 @@ +{ + "name": "frontend", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "frontend", + "version": "0.0.0", + "devDependencies": { + "@wailsio/runtime": "latest", + "typescript": "^4.9.3", + "vite": "^5.0.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.37.0.tgz", + "integrity": "sha512-l7StVw6WAa8l3vA1ov80jyetOAEo1FtHvZDbzXDO/02Sq/QVvqlHkYoFwDJPIMj0GKiistsBudfx5tGFnwYWDQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.37.0.tgz", + "integrity": "sha512-6U3SlVyMxezt8Y+/iEBcbp945uZjJwjZimu76xoG7tO1av9VO691z8PkhzQ85ith2I8R2RddEPeSfcbyPfD4hA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.37.0.tgz", + "integrity": "sha512-+iTQ5YHuGmPt10NTzEyMPbayiNTcOZDWsbxZYR1ZnmLnZxG17ivrPSWFO9j6GalY0+gV3Jtwrrs12DBscxnlYA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.37.0.tgz", + "integrity": "sha512-m8W2UbxLDcmRKVjgl5J/k4B8d7qX2EcJve3Sut7YGrQoPtCIQGPH5AMzuFvYRWZi0FVS0zEY4c8uttPfX6bwYQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.37.0.tgz", + "integrity": "sha512-FOMXGmH15OmtQWEt174v9P1JqqhlgYge/bUjIbiVD1nI1NeJ30HYT9SJlZMqdo1uQFyt9cz748F1BHghWaDnVA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.37.0.tgz", + "integrity": "sha512-SZMxNttjPKvV14Hjck5t70xS3l63sbVwl98g3FlVVx2YIDmfUIy29jQrsw06ewEYQ8lQSuY9mpAPlmgRD2iSsA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.37.0.tgz", + "integrity": "sha512-hhAALKJPidCwZcj+g+iN+38SIOkhK2a9bqtJR+EtyxrKKSt1ynCBeqrQy31z0oWU6thRZzdx53hVgEbRkuI19w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.37.0.tgz", + "integrity": "sha512-jUb/kmn/Gd8epbHKEqkRAxq5c2EwRt0DqhSGWjPFxLeFvldFdHQs/n8lQ9x85oAeVb6bHcS8irhTJX2FCOd8Ag==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.37.0.tgz", + "integrity": "sha512-oNrJxcQT9IcbcmKlkF+Yz2tmOxZgG9D9GRq+1OE6XCQwCVwxixYAa38Z8qqPzQvzt1FCfmrHX03E0pWoXm1DqA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.37.0.tgz", + "integrity": "sha512-pfxLBMls+28Ey2enpX3JvjEjaJMBX5XlPCZNGxj4kdJyHduPBXtxYeb8alo0a7bqOoWZW2uKynhHxF/MWoHaGQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.37.0.tgz", + "integrity": "sha512-yCE0NnutTC/7IGUq/PUHmoeZbIwq3KRh02e9SfFh7Vmc1Z7atuJRYWhRME5fKgT8aS20mwi1RyChA23qSyRGpA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.37.0.tgz", + "integrity": "sha512-NxcICptHk06E2Lh3a4Pu+2PEdZ6ahNHuK7o6Np9zcWkrBMuv21j10SQDJW3C9Yf/A/P7cutWoC/DptNLVsZ0VQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.37.0.tgz", + "integrity": "sha512-PpWwHMPCVpFZLTfLq7EWJWvrmEuLdGn1GMYcm5MV7PaRgwCEYJAwiN94uBuZev0/J/hFIIJCsYw4nLmXA9J7Pw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.37.0.tgz", + "integrity": "sha512-DTNwl6a3CfhGTAOYZ4KtYbdS8b+275LSLqJVJIrPa5/JuIufWWZ/QFvkxp52gpmguN95eujrM68ZG+zVxa8zHA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.37.0.tgz", + "integrity": "sha512-hZDDU5fgWvDdHFuExN1gBOhCuzo/8TMpidfOR+1cPZJflcEzXdCy1LjnklQdW8/Et9sryOPJAKAQRw8Jq7Tg+A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.37.0.tgz", + "integrity": "sha512-pKivGpgJM5g8dwj0ywBwe/HeVAUSuVVJhUTa/URXjxvoyTT/AxsLTAbkHkDHG7qQxLoW2s3apEIl26uUe08LVQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.37.0.tgz", + "integrity": "sha512-E2lPrLKE8sQbY/2bEkVTGDEk4/49UYRVWgj90MY8yPjpnGBQ+Xi1Qnr7b7UIWw1NOggdFQFOLZ8+5CzCiz143w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.37.0.tgz", + "integrity": "sha512-Jm7biMazjNzTU4PrQtr7VS8ibeys9Pn29/1bm4ph7CP2kf21950LgN+BaE2mJ1QujnvOc6p54eWWiVvn05SOBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.37.0.tgz", + "integrity": "sha512-e3/1SFm1OjefWICB2Ucstg2dxYDkDTZGDYgwufcbsxTHyqQps1UQf33dFEChBNmeSsTOyrjw2JJq0zbG5GF6RA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.37.0.tgz", + "integrity": "sha512-LWbXUBwn/bcLx2sSsqy7pK5o+Nr+VCoRoAohfJ5C/aBio9nfJmGQqHAhU6pwxV/RmyTk5AqdySma7uwWGlmeuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@wailsio/runtime": { + "version": "3.0.0-alpha.66", + "resolved": "https://registry.npmjs.org/@wailsio/runtime/-/runtime-3.0.0-alpha.66.tgz", + "integrity": "sha512-ENLu8rn1griL1gFHJqkq1i+BVxrrA0JPJHYneUJYuf/s54kjuQViW0RKDEe/WTDo56ABpfykrd/T8OYpPUyXUw==", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/postcss": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/rollup": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.37.0.tgz", + "integrity": "sha512-iAtQy/L4QFU+rTJ1YUjXqJOJzuwEghqWzCEYD2FEghT7Gsy1VdABntrO4CLopA5IkflTyqNiLNwPcOJ3S7UKLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.37.0", + "@rollup/rollup-android-arm64": "4.37.0", + "@rollup/rollup-darwin-arm64": "4.37.0", + "@rollup/rollup-darwin-x64": "4.37.0", + "@rollup/rollup-freebsd-arm64": "4.37.0", + "@rollup/rollup-freebsd-x64": "4.37.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.37.0", + "@rollup/rollup-linux-arm-musleabihf": "4.37.0", + "@rollup/rollup-linux-arm64-gnu": "4.37.0", + "@rollup/rollup-linux-arm64-musl": "4.37.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.37.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.37.0", + "@rollup/rollup-linux-riscv64-gnu": "4.37.0", + "@rollup/rollup-linux-riscv64-musl": "4.37.0", + "@rollup/rollup-linux-s390x-gnu": "4.37.0", + "@rollup/rollup-linux-x64-gnu": "4.37.0", + "@rollup/rollup-linux-x64-musl": "4.37.0", + "@rollup/rollup-win32-arm64-msvc": "4.37.0", + "@rollup/rollup-win32-ia32-msvc": "4.37.0", + "@rollup/rollup-win32-x64-msvc": "4.37.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/vite": { + "version": "5.4.15", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.15.tgz", + "integrity": "sha512-6ANcZRivqL/4WtwPGTKNaosuNJr5tWiftOC7liM7G9+rMb8+oeJeyzymDu4rTN93seySBmbjSfsS3Vzr19KNtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + } + } +} diff --git a/v3/examples/notifications/frontend/package.json b/v3/examples/notifications/frontend/package.json index 9ae87549e..4d675f189 100644 --- a/v3/examples/notifications/frontend/package.json +++ b/v3/examples/notifications/frontend/package.json @@ -5,11 +5,12 @@ "type": "module", "scripts": { "dev": "vite", - "build:dev": "vite build --minify false --mode development", - "build": "vite build --mode production", + "build:dev": "tsc && vite build --minify false --mode development", + "build": "tsc && vite build --mode production", "preview": "vite preview" }, "devDependencies": { + "typescript": "^4.9.3", "vite": "^5.0.0", "@wailsio/runtime": "latest" } diff --git a/v3/examples/notifications/frontend/public/javascript.svg b/v3/examples/notifications/frontend/public/javascript.svg deleted file mode 100644 index f9abb2b72..000000000 --- a/v3/examples/notifications/frontend/public/javascript.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/examples/notifications/frontend/public/style.css b/v3/examples/notifications/frontend/public/style.css index 127799eda..074717bca 100644 --- a/v3/examples/notifications/frontend/public/style.css +++ b/v3/examples/notifications/frontend/public/style.css @@ -30,11 +30,6 @@ url("./Inter-Medium.ttf") format("truetype"); } -h3 { - font-size: 3em; - line-height: 1.1; -} - a { font-weight: 500; color: #646cff; @@ -45,8 +40,12 @@ a:hover { color: #535bf2; } +.controls { + display: flex; + gap: 1em; +} + button { - /* width: 60px; */ height: 30px; line-height: 30px; border-radius: 3px; @@ -56,11 +55,6 @@ button { cursor: pointer; } -.result { - height: 20px; - line-height: 20px; -} - body { margin: 0; display: flex; @@ -75,11 +69,12 @@ body { flex-direction: column; align-items: center; justify-content: center; + padding: 3em; } -h1 { - font-size: 3.2em; +h1, h3 { line-height: 1.1; + text-align: center; } #app { @@ -103,19 +98,23 @@ h1 { filter: drop-shadow(0 0 2em #f7df1eaa); } -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - .footer { margin-top: 1rem; align-content: center; text-align: center; } +.footer table { + font-size: 12px; + border-collapse: collapse; + margin: 0 auto; +} + +.footer table, th, td { + border: 1px solid #ddd; + padding: 0.5em; +} + @media (prefers-color-scheme: light) { :root { color: #213547; @@ -129,32 +128,4 @@ h1 { button { background-color: #f9f9f9; } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); } \ No newline at end of file diff --git a/v3/examples/notifications/frontend/public/typescript.svg b/v3/examples/notifications/frontend/public/typescript.svg new file mode 100644 index 000000000..d91c910cc --- /dev/null +++ b/v3/examples/notifications/frontend/public/typescript.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/v3/examples/notifications/frontend/src/main.ts b/v3/examples/notifications/frontend/src/main.ts new file mode 100644 index 000000000..437fb8c94 --- /dev/null +++ b/v3/examples/notifications/frontend/src/main.ts @@ -0,0 +1,95 @@ +import { Events } from "@wailsio/runtime"; +import * as Notifications from "../bindings/github.com/wailsapp/wails/v3/pkg/services/notifications"; + +document.querySelector("#basic")?.addEventListener("click", async () => { + try { + const authorized = await Notifications.Service.CheckNotificationAuthorization(); + if (authorized) { + await Notifications.Service.SendNotification({ + id: crypto.randomUUID(), + title: "Notification Title", + subtitle: "Subtitle on macOS and Linux", + body: "Body text of notification.", + data: { + "user-id": "user-123", + "message-id": "msg-123", + "timestamp": Date.now(), + }, + }); + } else { + console.warn("Notifications are not authorized.\n You can attempt to request again or let the user know in the UI.\n"); + } + } catch (error) { + console.error(error); + } +}); +document.querySelector("#complex")?.addEventListener("click", async () => { + try { + const authorized = await Notifications.Service.CheckNotificationAuthorization(); + if (authorized) { + const CategoryID = "frontend-notification-id"; + + await Notifications.Service.RegisterNotificationCategory({ + id: CategoryID, + actions: [ + { id: "VIEW", title: "View" }, + { id: "MARK_READ", title: "Mark as read" }, + { id: "DELETE", title: "Delete", destructive: true }, + ], + hasReplyField: true, + replyPlaceholder: "Message...", + replyButtonTitle: "Reply", + }); + + await Notifications.Service.SendNotificationWithActions({ + id: crypto.randomUUID(), + title: "Notification Title", + subtitle: "Subtitle on macOS and Linux", + body: "Body text of notification.", + categoryId: CategoryID, + data: { + "user-id": "user-123", + "message-id": "msg-123", + "timestamp": Date.now(), + }, + }); + } else { + console.warn("Notifications are not authorized.\n You can attempt to request again or let the user know in the UI.\n"); + } + } catch (error) { + console.error(error); + } +}); + +const unlisten = Events.On("notification:action", (response) => { + console.info(`Recieved a ${response.name} event`); + const { userInfo, ...base } = response.data[0]; + console.info("Notification Response:"); + console.table(base); + console.info("Notification Response Metadata:"); + console.table(userInfo); + const table = ` +
Notification Response
+ + + ${Object.keys(base).map(key => ``).join("")} + + + ${Object.values(base).map(value => ``).join("")} + +
${key}
${value}
+
Notification Metadata
+ + + ${Object.keys(userInfo).map(key => ``).join("")} + + + ${Object.values(userInfo).map(value => ``).join("")} + +
${key}
${value}
+ `; + const footer = document.querySelector("#response"); + if (footer) footer.innerHTML = table; +}); + +window.onbeforeunload = () => unlisten(); \ No newline at end of file diff --git a/v3/examples/notifications/frontend/src/vite-env.d.ts b/v3/examples/notifications/frontend/src/vite-env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/v3/examples/notifications/frontend/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/v3/examples/notifications/frontend/tsconfig.json b/v3/examples/notifications/frontend/tsconfig.json new file mode 100644 index 000000000..c267ecf24 --- /dev/null +++ b/v3/examples/notifications/frontend/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ESNext", "DOM"], + "moduleResolution": "Node", + "strict": true, + "resolveJsonModule": true, + "isolatedModules": true, + "esModuleInterop": true, + "noEmit": true, + "noUnusedLocals": true, + "noUnusedParameters": false, + "noImplicitAny": false, + "noImplicitReturns": true, + "skipLibCheck": true + }, + "include": ["src"] +} diff --git a/v3/examples/notifications/go.mod b/v3/examples/notifications/go.mod new file mode 100644 index 000000000..39537e938 --- /dev/null +++ b/v3/examples/notifications/go.mod @@ -0,0 +1,53 @@ +module notifications + +go 1.24.0 + +toolchain go1.24.1 + +require github.com/wailsapp/wails/v3 v3.0.0-dev + +require ( + dario.cat/mergo v1.0.1 // indirect + git.sr.ht/~jackmordaunt/go-toast/v2 v2.0.3 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/ProtonMail/go-crypto v1.1.6 // indirect + github.com/adrg/xdg v0.5.3 // indirect + github.com/bep/debounce v1.2.1 // indirect + github.com/cloudflare/circl v1.6.0 // indirect + github.com/cyphar/filepath-securejoin v0.4.1 // indirect + github.com/ebitengine/purego v0.8.2 // indirect + github.com/emirpasic/gods v1.18.1 // indirect + github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect + github.com/go-git/go-billy/v5 v5.6.2 // indirect + github.com/go-git/go-git/v5 v5.13.2 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect + github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect + github.com/kevinburke/ssh_config v1.2.0 // indirect + github.com/leaanthony/go-ansi-parser v1.6.1 // indirect + github.com/leaanthony/u v1.1.1 // indirect + github.com/lmittmann/tint v1.0.7 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/pjbgf/sha1cd v0.3.2 // indirect + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + github.com/samber/lo v1.49.1 // indirect + github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect + github.com/skeema/knownhosts v1.3.1 // indirect + github.com/wailsapp/go-webview2 v1.0.21 // indirect + github.com/wailsapp/mimetype v1.4.1 // indirect + github.com/xanzy/ssh-agent v0.3.3 // indirect + golang.org/x/crypto v0.36.0 // indirect + golang.org/x/net v0.37.0 // indirect + golang.org/x/sys v0.31.0 // indirect + golang.org/x/text v0.23.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/warnings.v0 v0.1.2 // indirect +) + +replace github.com/wailsapp/wails/v3 => ../wails/v3 diff --git a/v3/examples/notifications/main.go b/v3/examples/notifications/main.go index c2a2502a3..aae1bf2f0 100644 --- a/v3/examples/notifications/main.go +++ b/v3/examples/notifications/main.go @@ -3,7 +3,6 @@ package main import ( "embed" _ "embed" - "encoding/json" "fmt" "log" "time" @@ -12,17 +11,31 @@ import ( "github.com/wailsapp/wails/v3/pkg/services/notifications" ) +// Wails uses Go's `embed` package to embed the frontend files into the binary. +// Any files in the frontend/dist folder will be embedded into the binary and +// made available to the frontend. +// See https://pkg.go.dev/embed for more information. + //go:embed all:frontend/dist var assets embed.FS +// main function serves as the application's entry point. It initializes the application, creates a window, +// and starts a goroutine that emits a time-based event every second. It subsequently runs the application and +// logs any error that might occur. func main() { - notificationService := notifications.New() + // Create a new Notification Service + ns := notifications.New() + // Create a new Wails application by providing the necessary options. + // Variables 'Name' and 'Description' are for application metadata. + // 'Assets' configures the asset server with the 'FS' variable pointing to the frontend files. + // 'Bind' is a list of Go struct instances. The frontend has access to the methods of these instances. + // 'Mac' options tailor the application when running an macOS. app := application.New(application.Options{ - Name: "Notifications", - Description: "A demo of using raw HTML & CSS", + Name: "Notifications Demo", + Description: "A demo of using desktop notifications with Wails", Services: []application.Service{ - application.NewService(notificationService), + application.NewService(ns), }, Assets: application.AssetOptions{ Handler: application.AssetFileServerFS(assets), @@ -30,13 +43,15 @@ func main() { Mac: application.MacOptions{ ApplicationShouldTerminateAfterLastWindowClosed: true, }, - Windows: application.WindowsOptions{ - WndClass: "Notifications", - }, }) + // Create a new window with the necessary options. + // 'Title' is the title of the window. + // 'Mac' options tailor the window when running on macOS. + // 'BackgroundColour' is the background colour of the window. + // 'URL' is the URL that will be loaded into the webview. app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ - Title: "Notifications", + Title: "Window 1", Mac: application.MacWindow{ InvisibleTitleBarHeight: 50, Backdrop: application.MacBackdropTranslucent, @@ -46,67 +61,90 @@ func main() { URL: "/", }) + // Create a goroutine that spawns desktop notifications from Go go func() { - granted, err := notificationService.RequestNotificationAuthorization() + var authorized bool + var err error + authorized, err = ns.CheckNotificationAuthorization() if err != nil { - log.Default().Printf("WARNING: %s\n", err) - return + println(fmt.Errorf("checking app notification authorization failed: %s", err)) } - if granted { - notificationService.OnNotificationResponse(func(result notifications.NotificationResult) { - if result.Error != nil { - fmt.Printf("notification response error: %s", result.Error) - return - } - data, _ := json.Marshal(result.Response) - fmt.Printf("%s\n", string(data)) - app.EmitEvent("notification:response", result.Response) - }) - time.Sleep(time.Second * 2) + if !authorized { + authorized, err = ns.RequestNotificationAuthorization() + if err != nil { + println(fmt.Errorf("requesting app notification authorization failed: %s", err)) + } + } - notificationService.SendNotification(notifications.NotificationOptions{ - ID: "uuid1", - Title: "Title!", - Body: "Body!", + if authorized { + ns.OnNotificationResponse(func(result notifications.NotificationResult) { + if result.Error != nil { + println(fmt.Errorf("parsing notification result failed: %s", result.Error)) + } else { + fmt.Printf("Response: %+v\n", result.Response) + println("Sending response to frontend...") + app.EmitEvent("notification:action", result.Response) + } + }) + + err = ns.SendNotification(notifications.NotificationOptions{ + ID: "uuid-basic-1", + Title: "Notification Title", + Subtitle: "Subtitle on macOS and Linux", + Body: "Body text of notification.", Data: map[string]interface{}{ - "messageId": "msg-123", - "senderId": "user-123", - "timestamp": time.Now().Unix(), + "user-id": "user-123", + "message-id": "msg-123", + "timestamp": time.Now().Unix(), }, }) + if err != nil { + println(fmt.Errorf("sending basic notification failed: %s", err)) + } + // Delay before sending next notification time.Sleep(time.Second * 2) - notificationService.RegisterNotificationCategory(notifications.NotificationCategory{ - ID: "BACKEND_NOTIF", + const CategoryID = "backend-notification-id" + + err = ns.RegisterNotificationCategory(notifications.NotificationCategory{ + ID: CategoryID, Actions: []notifications.NotificationAction{ - {ID: "VIEW_ACTION", Title: "View"}, - {ID: "MARK_READ_ACTION", Title: "Mark as Read"}, - {ID: "DELETE_ACTION", Title: "Delete", Destructive: true}, + {ID: "VIEW", Title: "View"}, + {ID: "MARK_READ", Title: "Mark as read"}, + {ID: "DELETE", Title: "Delete", Destructive: true}, }, HasReplyField: true, + ReplyPlaceholder: "Message...", ReplyButtonTitle: "Reply", - ReplyPlaceholder: "Reply to backend...", }) + if err != nil { + println(fmt.Errorf("creating notification category failed: %s", err)) + } - notificationService.SendNotificationWithActions(notifications.NotificationOptions{ - ID: "uuid2", - Title: "Complex Backend Notification", - Subtitle: "From: Jane Doe", - Body: "Is it raining today where you are?", - CategoryID: "BACKEND_NOTIF", + err = ns.SendNotificationWithActions(notifications.NotificationOptions{ + ID: "uuid-with-actions-1", + Title: "Actions Notification Title", + Subtitle: "Subtitle on macOS and Linux", + Body: "Body text of notification with actions.", + CategoryID: CategoryID, Data: map[string]interface{}{ - "messageId": "msg-456", - "senderId": "user-456", - "timestamp": time.Now().Unix(), + "user-id": "user-123", + "message-id": "msg-123", + "timestamp": time.Now().Unix(), }, }) + if err != nil { + println(fmt.Errorf("sending notification with actions failed: %s", err)) + } } }() + // Run the application. This blocks until the application has been exited. err := app.Run() + // If an error occurred while running the application, log it and exit. if err != nil { log.Fatal(err) }