feat: Add Android support for Wails v3
This commit adds comprehensive Android support for Wails v3, enabling Go applications to run as native Android apps with WebView-based UI. Key features: - Android-specific application implementation with JNI bridge - WebView integration via WebViewAssetLoader for serving assets - JavaScript runtime injection and execution via JNI callbacks - Binding call support with async result callbacks - Event system support for Android platform - Full example Android app with Gradle build system Technical details: - Uses CGO with Android NDK for cross-compilation - Implements JNI callbacks for Go <-> Java communication - Supports both ARM64 and x86_64 architectures - WebView debugging support via Chrome DevTools Protocol - Handles empty response body case in binding calls to prevent panic Files added: - v3/pkg/application/*_android.go - Android platform implementations - v3/pkg/events/events_android.go - Android event definitions - v3/internal/*/\*_android.go - Android-specific internal packages - v3/examples/android/ - Complete example Android application - v3/ANDROID_ARCHITECTURE.md - Architecture documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1025
v3/ANDROID_ARCHITECTURE.md
Normal file
24
v3/examples/android/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# Build outputs
|
||||
bin/
|
||||
*.apk
|
||||
*.aab
|
||||
|
||||
# Android build artifacts
|
||||
build/android/.gradle/
|
||||
build/android/app/build/
|
||||
build/android/local.properties
|
||||
|
||||
# JNI libraries (generated during build)
|
||||
build/android/app/src/main/jniLibs/*/libwails.so
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
*.iml
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Frontend build
|
||||
frontend/dist/
|
||||
frontend/node_modules/
|
||||
|
|
@ -0,0 +1 @@
|
|||
a40fe27d90a25e84deeed985e4075cfa
|
||||
|
|
@ -0,0 +1 @@
|
|||
82dedd4f821c351be61d8e1dbb6eefa
|
||||
|
|
@ -0,0 +1 @@
|
|||
7bfce68482b8f82eb3495774fb52ddca
|
||||
|
|
@ -0,0 +1 @@
|
|||
6e6cec395abdf7aed5c77ae6ab3ed264
|
||||
|
|
@ -0,0 +1 @@
|
|||
3eaf69fc9c4a0eeef54a9ebcc9b25cf7
|
||||
34
v3/examples/android/Taskfile.yml
Normal file
|
|
@ -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
|
||||
android: ./build/android/Taskfile.yml
|
||||
|
||||
vars:
|
||||
APP_NAME: "android"
|
||||
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}}
|
||||
174
v3/examples/android/build/Taskfile.yml
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
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}}'
|
||||
|
||||
|
||||
frontend:vendor:puppertino:
|
||||
summary: Fetches Puppertino CSS into frontend/public for consistent mobile styling
|
||||
sources:
|
||||
- frontend/public/puppertino/puppertino.css
|
||||
generates:
|
||||
- frontend/public/puppertino/puppertino.css
|
||||
cmds:
|
||||
- |
|
||||
set -euo pipefail
|
||||
mkdir -p frontend/public/puppertino
|
||||
# Fetch Puppertino full.css and LICENSE from GitHub main branch
|
||||
curl -fsSL https://raw.githubusercontent.com/codedgar/Puppertino/main/dist/css/full.css -o frontend/public/puppertino/puppertino.css
|
||||
curl -fsSL https://raw.githubusercontent.com/codedgar/Puppertino/main/LICENSE -o frontend/public/puppertino/LICENSE
|
||||
echo "Puppertino CSS updated at frontend/public/puppertino/puppertino.css"
|
||||
# Ensure index.html includes Puppertino CSS and button classes
|
||||
INDEX_HTML=frontend/index.html
|
||||
if [ -f "$INDEX_HTML" ]; then
|
||||
if ! grep -q 'href="/puppertino/puppertino.css"' "$INDEX_HTML"; then
|
||||
# Insert Puppertino link tag after style.css link
|
||||
awk '
|
||||
/href="\/style.css"\/?/ && !x { print; print " <link rel=\"stylesheet\" href=\"/puppertino/puppertino.css\"/>"; x=1; next }1
|
||||
' "$INDEX_HTML" > "$INDEX_HTML.tmp" && mv "$INDEX_HTML.tmp" "$INDEX_HTML"
|
||||
fi
|
||||
# Replace default .btn with Puppertino primary button classes if present
|
||||
sed -E -i'' 's/class=\"btn\"/class=\"p-btn p-prim-col\"/g' "$INDEX_HTML" || true
|
||||
fi
|
||||
|
||||
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
|
||||
|
||||
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 .
|
||||
|
||||
|
||||
ios:device:list:
|
||||
summary: Lists connected iOS devices (UDIDs)
|
||||
cmds:
|
||||
- xcrun xcdevice list
|
||||
|
||||
ios:run:device:
|
||||
summary: Build, install, and launch on a physical iPhone using Apple tools (xcodebuild/devicectl)
|
||||
vars:
|
||||
PROJECT: '{{.PROJECT}}' # e.g., build/ios/xcode/<YourProject>.xcodeproj
|
||||
SCHEME: '{{.SCHEME}}' # e.g., ios.dev
|
||||
CONFIG: '{{.CONFIG | default "Debug"}}'
|
||||
DERIVED: '{{.DERIVED | default "build/ios/DerivedData"}}'
|
||||
UDID: '{{.UDID}}' # from `task ios:device:list`
|
||||
BUNDLE_ID: '{{.BUNDLE_ID}}' # e.g., com.yourco.wails.ios.dev
|
||||
TEAM_ID: '{{.TEAM_ID}}' # optional, if your project is not already set up for signing
|
||||
preconditions:
|
||||
- sh: xcrun -f xcodebuild
|
||||
msg: "xcodebuild not found. Please install Xcode."
|
||||
- sh: xcrun -f devicectl
|
||||
msg: "devicectl not found. Please update to Xcode 15+ (which includes devicectl)."
|
||||
- sh: test -n "{{.PROJECT}}"
|
||||
msg: "Set PROJECT to your .xcodeproj path (e.g., PROJECT=build/ios/xcode/App.xcodeproj)."
|
||||
- sh: test -n "{{.SCHEME}}"
|
||||
msg: "Set SCHEME to your app scheme (e.g., SCHEME=ios.dev)."
|
||||
- sh: test -n "{{.UDID}}"
|
||||
msg: "Set UDID to your device UDID (see: task ios:device:list)."
|
||||
- sh: test -n "{{.BUNDLE_ID}}"
|
||||
msg: "Set BUNDLE_ID to your app's bundle identifier (e.g., com.yourco.wails.ios.dev)."
|
||||
cmds:
|
||||
- |
|
||||
set -euo pipefail
|
||||
echo "Building for device: UDID={{.UDID}} SCHEME={{.SCHEME}} PROJECT={{.PROJECT}}"
|
||||
XCB_ARGS=(
|
||||
-project "{{.PROJECT}}"
|
||||
-scheme "{{.SCHEME}}"
|
||||
-configuration "{{.CONFIG}}"
|
||||
-destination "id={{.UDID}}"
|
||||
-derivedDataPath "{{.DERIVED}}"
|
||||
-allowProvisioningUpdates
|
||||
-allowProvisioningDeviceRegistration
|
||||
)
|
||||
# Optionally inject signing identifiers if provided
|
||||
if [ -n "{{.TEAM_ID}}" ]; then XCB_ARGS+=(DEVELOPMENT_TEAM={{.TEAM_ID}}); fi
|
||||
if [ -n "{{.BUNDLE_ID}}" ]; then XCB_ARGS+=(PRODUCT_BUNDLE_IDENTIFIER={{.BUNDLE_ID}}); fi
|
||||
xcodebuild "${XCB_ARGS[@]}" build | xcpretty || true
|
||||
# If xcpretty isn't installed, run without it
|
||||
if [ "${PIPESTATUS[0]}" -ne 0 ]; then
|
||||
xcodebuild "${XCB_ARGS[@]}" build
|
||||
fi
|
||||
# Find built .app
|
||||
APP_PATH=$(find "{{.DERIVED}}/Build/Products" -type d -name "*.app" -maxdepth 3 | head -n 1)
|
||||
if [ -z "$APP_PATH" ]; then
|
||||
echo "Could not locate built .app under {{.DERIVED}}/Build/Products" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "Installing: $APP_PATH"
|
||||
xcrun devicectl device install app --device "{{.UDID}}" "$APP_PATH"
|
||||
echo "Launching: {{.BUNDLE_ID}}"
|
||||
xcrun devicectl device process launch --device "{{.UDID}}" --stderr console --stdout console "{{.BUNDLE_ID}}"
|
||||
237
v3/examples/android/build/android/Taskfile.yml
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
version: '3'
|
||||
|
||||
includes:
|
||||
common: ../Taskfile.yml
|
||||
|
||||
vars:
|
||||
APP_ID: '{{.APP_ID | default "com.wails.app"}}'
|
||||
MIN_SDK: '21'
|
||||
TARGET_SDK: '34'
|
||||
NDK_VERSION: 'r26d'
|
||||
|
||||
tasks:
|
||||
install:deps:
|
||||
summary: Check and install Android development dependencies
|
||||
cmds:
|
||||
- go run build/android/scripts/deps/install_deps.go
|
||||
env:
|
||||
TASK_FORCE_YES: '{{if .YES}}true{{else}}false{{end}}'
|
||||
prompt: This will check and install Android development dependencies. Continue?
|
||||
|
||||
build:
|
||||
summary: Creates a build of the application for Android
|
||||
deps:
|
||||
- task: common:go:mod:tidy
|
||||
- task: generate:android:bindings
|
||||
vars:
|
||||
BUILD_FLAGS:
|
||||
ref: .BUILD_FLAGS
|
||||
- task: common:build:frontend
|
||||
vars:
|
||||
BUILD_FLAGS:
|
||||
ref: .BUILD_FLAGS
|
||||
PRODUCTION:
|
||||
ref: .PRODUCTION
|
||||
- task: common:generate:icons
|
||||
cmds:
|
||||
- echo "Building Android app {{.APP_NAME}}..."
|
||||
- task: compile:go:shared
|
||||
vars:
|
||||
ARCH: '{{.ARCH | default "arm64"}}'
|
||||
vars:
|
||||
BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production,android -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-tags android,debug -buildvcs=false -gcflags=all="-l"{{end}}'
|
||||
env:
|
||||
PRODUCTION: '{{.PRODUCTION | default "false"}}'
|
||||
|
||||
compile:go:shared:
|
||||
summary: Compile Go code to shared library (.so)
|
||||
cmds:
|
||||
- |
|
||||
NDK_ROOT="${ANDROID_NDK_HOME:-$ANDROID_HOME/ndk/{{.NDK_VERSION}}}"
|
||||
if [ ! -d "$NDK_ROOT" ]; then
|
||||
echo "Error: Android NDK not found at $NDK_ROOT"
|
||||
echo "Please set ANDROID_NDK_HOME or install NDK {{.NDK_VERSION}} via Android Studio"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Determine toolchain based on host OS
|
||||
case "$(uname -s)" in
|
||||
Darwin) HOST_TAG="darwin-x86_64" ;;
|
||||
Linux) HOST_TAG="linux-x86_64" ;;
|
||||
*) echo "Unsupported host OS"; exit 1 ;;
|
||||
esac
|
||||
|
||||
TOOLCHAIN="$NDK_ROOT/toolchains/llvm/prebuilt/$HOST_TAG"
|
||||
|
||||
# Set compiler based on architecture
|
||||
case "{{.ARCH}}" in
|
||||
arm64)
|
||||
export CC="$TOOLCHAIN/bin/aarch64-linux-android{{.MIN_SDK}}-clang"
|
||||
export CXX="$TOOLCHAIN/bin/aarch64-linux-android{{.MIN_SDK}}-clang++"
|
||||
export GOARCH=arm64
|
||||
JNI_DIR="arm64-v8a"
|
||||
;;
|
||||
amd64|x86_64)
|
||||
export CC="$TOOLCHAIN/bin/x86_64-linux-android{{.MIN_SDK}}-clang"
|
||||
export CXX="$TOOLCHAIN/bin/x86_64-linux-android{{.MIN_SDK}}-clang++"
|
||||
export GOARCH=amd64
|
||||
JNI_DIR="x86_64"
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported architecture: {{.ARCH}}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
export CGO_ENABLED=1
|
||||
export GOOS=android
|
||||
|
||||
mkdir -p {{.BIN_DIR}}
|
||||
mkdir -p build/android/app/src/main/jniLibs/$JNI_DIR
|
||||
|
||||
go build -buildmode=c-shared {{.BUILD_FLAGS}} \
|
||||
-o build/android/app/src/main/jniLibs/$JNI_DIR/libwails.so
|
||||
vars:
|
||||
BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production,android -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-tags android,debug -buildvcs=false -gcflags=all="-l"{{end}}'
|
||||
|
||||
compile:go:all-archs:
|
||||
summary: Compile Go code for all Android architectures (fat APK)
|
||||
cmds:
|
||||
- task: compile:go:shared
|
||||
vars:
|
||||
ARCH: arm64
|
||||
- task: compile:go:shared
|
||||
vars:
|
||||
ARCH: amd64
|
||||
|
||||
package:
|
||||
summary: Packages a production build of the application into an APK
|
||||
deps:
|
||||
- task: build
|
||||
vars:
|
||||
PRODUCTION: "true"
|
||||
cmds:
|
||||
- task: assemble:apk
|
||||
|
||||
package:fat:
|
||||
summary: Packages a production build for all architectures (fat APK)
|
||||
cmds:
|
||||
- task: compile:go:all-archs
|
||||
- task: assemble:apk
|
||||
|
||||
assemble:apk:
|
||||
summary: Assembles the APK using Gradle
|
||||
cmds:
|
||||
- |
|
||||
cd build/android
|
||||
./gradlew assembleDebug
|
||||
cp app/build/outputs/apk/debug/app-debug.apk ../../{{.BIN_DIR}}/{{.APP_NAME}}.apk
|
||||
echo "APK created: {{.BIN_DIR}}/{{.APP_NAME}}.apk"
|
||||
|
||||
assemble:apk:release:
|
||||
summary: Assembles a release APK using Gradle
|
||||
cmds:
|
||||
- |
|
||||
cd build/android
|
||||
./gradlew assembleRelease
|
||||
cp app/build/outputs/apk/release/app-release-unsigned.apk ../../{{.BIN_DIR}}/{{.APP_NAME}}-release.apk
|
||||
echo "Release APK created: {{.BIN_DIR}}/{{.APP_NAME}}-release.apk"
|
||||
|
||||
generate:android:bindings:
|
||||
internal: true
|
||||
summary: Generates bindings for Android
|
||||
sources:
|
||||
- "**/*.go"
|
||||
- go.mod
|
||||
- go.sum
|
||||
generates:
|
||||
- frontend/bindings/**/*
|
||||
cmds:
|
||||
- wails3 generate bindings -f '{{.BUILD_FLAGS}}' -clean=true
|
||||
env:
|
||||
GOOS: android
|
||||
CGO_ENABLED: 1
|
||||
GOARCH: '{{.ARCH | default "arm64"}}'
|
||||
|
||||
ensure-emulator:
|
||||
internal: true
|
||||
summary: Ensure Android Emulator is running
|
||||
silent: true
|
||||
cmds:
|
||||
- |
|
||||
# Check if an emulator is already running
|
||||
if adb devices | grep -q "emulator"; then
|
||||
echo "Emulator already running"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Get first available AVD
|
||||
AVD_NAME=$(emulator -list-avds | head -1)
|
||||
if [ -z "$AVD_NAME" ]; then
|
||||
echo "No Android Virtual Devices found."
|
||||
echo "Create one using: Android Studio > Tools > Device Manager"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Starting emulator: $AVD_NAME"
|
||||
emulator -avd "$AVD_NAME" -no-snapshot-load &
|
||||
|
||||
# Wait for emulator to boot (max 60 seconds)
|
||||
echo "Waiting for emulator to boot..."
|
||||
adb wait-for-device
|
||||
|
||||
for i in {1..60}; do
|
||||
BOOT_COMPLETED=$(adb shell getprop sys.boot_completed 2>/dev/null | tr -d '\r')
|
||||
if [ "$BOOT_COMPLETED" = "1" ]; then
|
||||
echo "Emulator booted successfully"
|
||||
exit 0
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo "Emulator boot timeout"
|
||||
exit 1
|
||||
preconditions:
|
||||
- sh: command -v adb
|
||||
msg: "adb not found. Please install Android SDK and add platform-tools to PATH"
|
||||
- sh: command -v emulator
|
||||
msg: "emulator not found. Please install Android SDK and add emulator to PATH"
|
||||
|
||||
deploy-emulator:
|
||||
summary: Deploy to Android Emulator
|
||||
deps: [package]
|
||||
cmds:
|
||||
- adb uninstall {{.APP_ID}} 2>/dev/null || true
|
||||
- adb install {{.BIN_DIR}}/{{.APP_NAME}}.apk
|
||||
- adb shell am start -n {{.APP_ID}}/.MainActivity
|
||||
|
||||
run:
|
||||
summary: Run the application in Android Emulator
|
||||
deps:
|
||||
- task: ensure-emulator
|
||||
- task: build
|
||||
vars:
|
||||
ARCH: x86_64
|
||||
cmds:
|
||||
- task: assemble:apk
|
||||
- adb uninstall {{.APP_ID}} 2>/dev/null || true
|
||||
- adb install {{.BIN_DIR}}/{{.APP_NAME}}.apk
|
||||
- adb shell am start -n {{.APP_ID}}/.MainActivity
|
||||
|
||||
logs:
|
||||
summary: Stream Android logcat filtered to this app
|
||||
cmds:
|
||||
- adb logcat -v time | grep -E "(Wails|{{.APP_NAME}})"
|
||||
|
||||
logs:all:
|
||||
summary: Stream all Android logcat (verbose)
|
||||
cmds:
|
||||
- adb logcat -v time
|
||||
|
||||
clean:
|
||||
summary: Clean build artifacts
|
||||
cmds:
|
||||
- rm -rf {{.BIN_DIR}}
|
||||
- rm -rf build/android/app/build
|
||||
- rm -rf build/android/app/src/main/jniLibs/*/libwails.so
|
||||
- rm -rf build/android/.gradle
|
||||
63
v3/examples/android/build/android/app/build.gradle
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
plugins {
|
||||
id 'com.android.application'
|
||||
}
|
||||
|
||||
android {
|
||||
namespace 'com.wails.app'
|
||||
compileSdk 34
|
||||
|
||||
buildFeatures {
|
||||
buildConfig = true
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.wails.app"
|
||||
minSdk 21
|
||||
targetSdk 34
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
// Configure supported ABIs
|
||||
ndk {
|
||||
abiFilters 'arm64-v8a', 'x86_64'
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
debug {
|
||||
debuggable true
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
// Source sets configuration
|
||||
sourceSets {
|
||||
main {
|
||||
// JNI libraries are in jniLibs folder
|
||||
jniLibs.srcDirs = ['src/main/jniLibs']
|
||||
// Assets for the WebView
|
||||
assets.srcDirs = ['src/main/assets']
|
||||
}
|
||||
}
|
||||
|
||||
// Packaging options
|
||||
packagingOptions {
|
||||
// Don't strip Go symbols in debug builds
|
||||
doNotStrip '*/arm64-v8a/libwails.so'
|
||||
doNotStrip '*/x86_64/libwails.so'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||
implementation 'androidx.webkit:webkit:1.9.0'
|
||||
implementation 'com.google.android.material:material:1.11.0'
|
||||
}
|
||||
12
v3/examples/android/build/android/app/proguard-rules.pro
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
|
||||
# Keep native methods
|
||||
-keepclasseswithmembernames class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
# Keep Wails bridge classes
|
||||
-keep class com.wails.app.WailsBridge { *; }
|
||||
-keep class com.wails.app.WailsJSBridge { *; }
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<!-- Internet permission for WebView -->
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.WailsApp"
|
||||
android:usesCleartextTraffic="true"
|
||||
tools:targetApi="31">
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
package com.wails.app;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.webkit.WebResourceRequest;
|
||||
import android.webkit.WebResourceResponse;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.webkit.WebViewAssetLoader;
|
||||
import com.wails.app.BuildConfig;
|
||||
|
||||
/**
|
||||
* MainActivity hosts the WebView and manages the Wails application lifecycle.
|
||||
* It uses WebViewAssetLoader to serve assets from the Go library without
|
||||
* requiring a network server.
|
||||
*/
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
private static final String TAG = "WailsActivity";
|
||||
private static final String WAILS_SCHEME = "https";
|
||||
private static final String WAILS_HOST = "wails.localhost";
|
||||
|
||||
private WebView webView;
|
||||
private WailsBridge bridge;
|
||||
private WebViewAssetLoader assetLoader;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
// Initialize the native Go library
|
||||
bridge = new WailsBridge(this);
|
||||
bridge.initialize();
|
||||
|
||||
// Set up WebView
|
||||
setupWebView();
|
||||
|
||||
// Load the application
|
||||
loadApplication();
|
||||
}
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
private void setupWebView() {
|
||||
webView = findViewById(R.id.webview);
|
||||
|
||||
// Configure WebView settings
|
||||
WebSettings settings = webView.getSettings();
|
||||
settings.setJavaScriptEnabled(true);
|
||||
settings.setDomStorageEnabled(true);
|
||||
settings.setDatabaseEnabled(true);
|
||||
settings.setAllowFileAccess(false);
|
||||
settings.setAllowContentAccess(false);
|
||||
settings.setMediaPlaybackRequiresUserGesture(false);
|
||||
settings.setMixedContentMode(WebSettings.MIXED_CONTENT_NEVER_ALLOW);
|
||||
|
||||
// Enable debugging in debug builds
|
||||
if (BuildConfig.DEBUG) {
|
||||
WebView.setWebContentsDebuggingEnabled(true);
|
||||
}
|
||||
|
||||
// Set up asset loader for serving local assets
|
||||
assetLoader = new WebViewAssetLoader.Builder()
|
||||
.setDomain(WAILS_HOST)
|
||||
.addPathHandler("/", new WailsPathHandler(bridge))
|
||||
.build();
|
||||
|
||||
// Set up WebView client to intercept requests
|
||||
webView.setWebViewClient(new WebViewClient() {
|
||||
@Nullable
|
||||
@Override
|
||||
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
|
||||
String url = request.getUrl().toString();
|
||||
Log.d(TAG, "Intercepting request: " + url);
|
||||
|
||||
// Handle wails.localhost requests
|
||||
if (request.getUrl().getHost() != null &&
|
||||
request.getUrl().getHost().equals(WAILS_HOST)) {
|
||||
|
||||
// For wails API calls (runtime, capabilities, etc.), we need to pass the full URL
|
||||
// including query string because WebViewAssetLoader.PathHandler strips query params
|
||||
String path = request.getUrl().getPath();
|
||||
if (path != null && path.startsWith("/wails/")) {
|
||||
// Get full path with query string for runtime calls
|
||||
String fullPath = path;
|
||||
String query = request.getUrl().getQuery();
|
||||
if (query != null && !query.isEmpty()) {
|
||||
fullPath = path + "?" + query;
|
||||
}
|
||||
Log.d(TAG, "Wails API call detected, full path: " + fullPath);
|
||||
|
||||
// Call bridge directly with full path
|
||||
byte[] data = bridge.serveAsset(fullPath, request.getMethod(), "{}");
|
||||
if (data != null && data.length > 0) {
|
||||
java.io.InputStream inputStream = new java.io.ByteArrayInputStream(data);
|
||||
java.util.Map<String, String> headers = new java.util.HashMap<>();
|
||||
headers.put("Access-Control-Allow-Origin", "*");
|
||||
headers.put("Cache-Control", "no-cache");
|
||||
headers.put("Content-Type", "application/json");
|
||||
|
||||
return new WebResourceResponse(
|
||||
"application/json",
|
||||
"UTF-8",
|
||||
200,
|
||||
"OK",
|
||||
headers,
|
||||
inputStream
|
||||
);
|
||||
}
|
||||
// Return error response if data is null
|
||||
return new WebResourceResponse(
|
||||
"application/json",
|
||||
"UTF-8",
|
||||
500,
|
||||
"Internal Error",
|
||||
new java.util.HashMap<>(),
|
||||
new java.io.ByteArrayInputStream("{}".getBytes())
|
||||
);
|
||||
}
|
||||
|
||||
// For regular assets, use the asset loader
|
||||
return assetLoader.shouldInterceptRequest(request.getUrl());
|
||||
}
|
||||
|
||||
return super.shouldInterceptRequest(view, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
super.onPageFinished(view, url);
|
||||
Log.d(TAG, "Page loaded: " + url);
|
||||
// Inject Wails runtime
|
||||
bridge.injectRuntime(webView, url);
|
||||
}
|
||||
});
|
||||
|
||||
// Add JavaScript interface for Go communication
|
||||
webView.addJavascriptInterface(new WailsJSBridge(bridge, webView), "wails");
|
||||
}
|
||||
|
||||
private void loadApplication() {
|
||||
// Load the main page from the asset server
|
||||
String url = WAILS_SCHEME + "://" + WAILS_HOST + "/";
|
||||
Log.d(TAG, "Loading URL: " + url);
|
||||
webView.loadUrl(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute JavaScript in the WebView from the Go side
|
||||
*/
|
||||
public void executeJavaScript(final String js) {
|
||||
runOnUiThread(() -> {
|
||||
if (webView != null) {
|
||||
webView.evaluateJavascript(js, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
if (bridge != null) {
|
||||
bridge.onResume();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
if (bridge != null) {
|
||||
bridge.onPause();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (bridge != null) {
|
||||
bridge.shutdown();
|
||||
}
|
||||
if (webView != null) {
|
||||
webView.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (webView != null && webView.canGoBack()) {
|
||||
webView.goBack();
|
||||
} else {
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,214 @@
|
|||
package com.wails.app;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* WailsBridge manages the connection between the Java/Android side and the Go native library.
|
||||
* It handles:
|
||||
* - Loading and initializing the native Go library
|
||||
* - Serving asset requests from Go
|
||||
* - Passing messages between JavaScript and Go
|
||||
* - Managing callbacks for async operations
|
||||
*/
|
||||
public class WailsBridge {
|
||||
private static final String TAG = "WailsBridge";
|
||||
|
||||
static {
|
||||
// Load the native Go library
|
||||
System.loadLibrary("wails");
|
||||
}
|
||||
|
||||
private final Context context;
|
||||
private final AtomicInteger callbackIdGenerator = new AtomicInteger(0);
|
||||
private final ConcurrentHashMap<Integer, AssetCallback> pendingAssetCallbacks = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<Integer, MessageCallback> pendingMessageCallbacks = new ConcurrentHashMap<>();
|
||||
private WebView webView;
|
||||
private volatile boolean initialized = false;
|
||||
|
||||
// Native methods - implemented in Go
|
||||
private static native void nativeInit(WailsBridge bridge);
|
||||
private static native void nativeShutdown();
|
||||
private static native void nativeOnResume();
|
||||
private static native void nativeOnPause();
|
||||
private static native void nativeOnPageFinished(String url);
|
||||
private static native byte[] nativeServeAsset(String path, String method, String headers);
|
||||
private static native String nativeHandleMessage(String message);
|
||||
private static native String nativeGetAssetMimeType(String path);
|
||||
|
||||
public WailsBridge(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the native Go library
|
||||
*/
|
||||
public void initialize() {
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
Log.i(TAG, "Initializing Wails bridge...");
|
||||
try {
|
||||
nativeInit(this);
|
||||
initialized = true;
|
||||
Log.i(TAG, "Wails bridge initialized successfully");
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failed to initialize Wails bridge", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown the native Go library
|
||||
*/
|
||||
public void shutdown() {
|
||||
if (!initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
Log.i(TAG, "Shutting down Wails bridge...");
|
||||
try {
|
||||
nativeShutdown();
|
||||
initialized = false;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error during shutdown", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the activity resumes
|
||||
*/
|
||||
public void onResume() {
|
||||
if (initialized) {
|
||||
nativeOnResume();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the activity pauses
|
||||
*/
|
||||
public void onPause() {
|
||||
if (initialized) {
|
||||
nativeOnPause();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serve an asset from the Go asset server
|
||||
* @param path The URL path requested
|
||||
* @param method The HTTP method
|
||||
* @param headers The request headers as JSON
|
||||
* @return The asset data, or null if not found
|
||||
*/
|
||||
public byte[] serveAsset(String path, String method, String headers) {
|
||||
if (!initialized) {
|
||||
Log.w(TAG, "Bridge not initialized, cannot serve asset: " + path);
|
||||
return null;
|
||||
}
|
||||
|
||||
Log.d(TAG, "Serving asset: " + path);
|
||||
try {
|
||||
return nativeServeAsset(path, method, headers);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error serving asset: " + path, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MIME type for an asset
|
||||
* @param path The asset path
|
||||
* @return The MIME type string
|
||||
*/
|
||||
public String getAssetMimeType(String path) {
|
||||
if (!initialized) {
|
||||
return "application/octet-stream";
|
||||
}
|
||||
|
||||
try {
|
||||
String mimeType = nativeGetAssetMimeType(path);
|
||||
return mimeType != null ? mimeType : "application/octet-stream";
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error getting MIME type for: " + path, e);
|
||||
return "application/octet-stream";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a message from JavaScript
|
||||
* @param message The message from JavaScript (JSON)
|
||||
* @return The response to send back to JavaScript (JSON)
|
||||
*/
|
||||
public String handleMessage(String message) {
|
||||
if (!initialized) {
|
||||
Log.w(TAG, "Bridge not initialized, cannot handle message");
|
||||
return "{\"error\":\"Bridge not initialized\"}";
|
||||
}
|
||||
|
||||
Log.d(TAG, "Handling message from JS: " + message);
|
||||
try {
|
||||
return nativeHandleMessage(message);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error handling message", e);
|
||||
return "{\"error\":\"" + e.getMessage() + "\"}";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject the Wails runtime JavaScript into the WebView.
|
||||
* Called when the page finishes loading.
|
||||
* @param webView The WebView to inject into
|
||||
* @param url The URL that finished loading
|
||||
*/
|
||||
public void injectRuntime(WebView webView, String url) {
|
||||
this.webView = webView;
|
||||
// Notify Go side that page has finished loading so it can inject the runtime
|
||||
Log.d(TAG, "Page finished loading: " + url + ", notifying Go side");
|
||||
if (initialized) {
|
||||
nativeOnPageFinished(url);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute JavaScript in the WebView (called from Go side)
|
||||
* @param js The JavaScript code to execute
|
||||
*/
|
||||
public void executeJavaScript(String js) {
|
||||
if (webView != null) {
|
||||
webView.post(() -> webView.evaluateJavascript(js, null));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from Go when an event needs to be emitted to JavaScript
|
||||
* @param eventName The event name
|
||||
* @param eventData The event data (JSON)
|
||||
*/
|
||||
public void emitEvent(String eventName, String eventData) {
|
||||
String js = String.format("window.wails && window.wails._emit('%s', %s);",
|
||||
escapeJsString(eventName), eventData);
|
||||
executeJavaScript(js);
|
||||
}
|
||||
|
||||
private String escapeJsString(String str) {
|
||||
return str.replace("\\", "\\\\")
|
||||
.replace("'", "\\'")
|
||||
.replace("\n", "\\n")
|
||||
.replace("\r", "\\r");
|
||||
}
|
||||
|
||||
// Callback interfaces
|
||||
public interface AssetCallback {
|
||||
void onAssetReady(byte[] data, String mimeType);
|
||||
void onAssetError(String error);
|
||||
}
|
||||
|
||||
public interface MessageCallback {
|
||||
void onResponse(String response);
|
||||
void onError(String error);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
package com.wails.app;
|
||||
|
||||
import android.util.Log;
|
||||
import android.webkit.JavascriptInterface;
|
||||
import android.webkit.WebView;
|
||||
import com.wails.app.BuildConfig;
|
||||
|
||||
/**
|
||||
* WailsJSBridge provides the JavaScript interface that allows the web frontend
|
||||
* to communicate with the Go backend. This is exposed to JavaScript as the
|
||||
* `window.wails` object.
|
||||
*
|
||||
* Similar to iOS's WKScriptMessageHandler but using Android's addJavascriptInterface.
|
||||
*/
|
||||
public class WailsJSBridge {
|
||||
private static final String TAG = "WailsJSBridge";
|
||||
|
||||
private final WailsBridge bridge;
|
||||
private final WebView webView;
|
||||
|
||||
public WailsJSBridge(WailsBridge bridge, WebView webView) {
|
||||
this.bridge = bridge;
|
||||
this.webView = webView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to Go and return the response synchronously.
|
||||
* Called from JavaScript: wails.invoke(message)
|
||||
*
|
||||
* @param message The message to send (JSON string)
|
||||
* @return The response from Go (JSON string)
|
||||
*/
|
||||
@JavascriptInterface
|
||||
public String invoke(String message) {
|
||||
Log.d(TAG, "Invoke called: " + message);
|
||||
return bridge.handleMessage(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to Go asynchronously.
|
||||
* The response will be sent back via a callback.
|
||||
* Called from JavaScript: wails.invokeAsync(callbackId, message)
|
||||
*
|
||||
* @param callbackId The callback ID to use for the response
|
||||
* @param message The message to send (JSON string)
|
||||
*/
|
||||
@JavascriptInterface
|
||||
public void invokeAsync(final String callbackId, final String message) {
|
||||
Log.d(TAG, "InvokeAsync called: " + message);
|
||||
|
||||
// Handle in background thread to not block JavaScript
|
||||
new Thread(() -> {
|
||||
try {
|
||||
String response = bridge.handleMessage(message);
|
||||
sendCallback(callbackId, response, null);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error in async invoke", e);
|
||||
sendCallback(callbackId, null, e.getMessage());
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a message from JavaScript to Android's logcat
|
||||
* Called from JavaScript: wails.log(level, message)
|
||||
*
|
||||
* @param level The log level (debug, info, warn, error)
|
||||
* @param message The message to log
|
||||
*/
|
||||
@JavascriptInterface
|
||||
public void log(String level, String message) {
|
||||
switch (level.toLowerCase()) {
|
||||
case "debug":
|
||||
Log.d(TAG + "/JS", message);
|
||||
break;
|
||||
case "info":
|
||||
Log.i(TAG + "/JS", message);
|
||||
break;
|
||||
case "warn":
|
||||
Log.w(TAG + "/JS", message);
|
||||
break;
|
||||
case "error":
|
||||
Log.e(TAG + "/JS", message);
|
||||
break;
|
||||
default:
|
||||
Log.v(TAG + "/JS", message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the platform name
|
||||
* Called from JavaScript: wails.platform()
|
||||
*
|
||||
* @return "android"
|
||||
*/
|
||||
@JavascriptInterface
|
||||
public String platform() {
|
||||
return "android";
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we're running in debug mode
|
||||
* Called from JavaScript: wails.isDebug()
|
||||
*
|
||||
* @return true if debug build, false otherwise
|
||||
*/
|
||||
@JavascriptInterface
|
||||
public boolean isDebug() {
|
||||
return BuildConfig.DEBUG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a callback response to JavaScript
|
||||
*/
|
||||
private void sendCallback(String callbackId, String result, String error) {
|
||||
final String js;
|
||||
if (error != null) {
|
||||
js = String.format(
|
||||
"window.wails && window.wails._callback('%s', null, '%s');",
|
||||
escapeJsString(callbackId),
|
||||
escapeJsString(error)
|
||||
);
|
||||
} else {
|
||||
js = String.format(
|
||||
"window.wails && window.wails._callback('%s', %s, null);",
|
||||
escapeJsString(callbackId),
|
||||
result != null ? result : "null"
|
||||
);
|
||||
}
|
||||
|
||||
webView.post(() -> webView.evaluateJavascript(js, null));
|
||||
}
|
||||
|
||||
private String escapeJsString(String str) {
|
||||
if (str == null) return "";
|
||||
return str.replace("\\", "\\\\")
|
||||
.replace("'", "\\'")
|
||||
.replace("\n", "\\n")
|
||||
.replace("\r", "\\r");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
package com.wails.app;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
import android.webkit.WebResourceResponse;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.webkit.WebViewAssetLoader;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* WailsPathHandler implements WebViewAssetLoader.PathHandler to serve assets
|
||||
* from the Go asset server. This allows the WebView to load assets without
|
||||
* using a network server, similar to iOS's WKURLSchemeHandler.
|
||||
*/
|
||||
public class WailsPathHandler implements WebViewAssetLoader.PathHandler {
|
||||
private static final String TAG = "WailsPathHandler";
|
||||
|
||||
private final WailsBridge bridge;
|
||||
|
||||
public WailsPathHandler(WailsBridge bridge) {
|
||||
this.bridge = bridge;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public WebResourceResponse handle(@NonNull String path) {
|
||||
Log.d(TAG, "Handling path: " + path);
|
||||
|
||||
// Normalize path
|
||||
if (path.isEmpty() || path.equals("/")) {
|
||||
path = "/index.html";
|
||||
}
|
||||
|
||||
// Get asset from Go
|
||||
byte[] data = bridge.serveAsset(path, "GET", "{}");
|
||||
|
||||
if (data == null || data.length == 0) {
|
||||
Log.w(TAG, "Asset not found: " + path);
|
||||
return null; // Return null to let WebView handle 404
|
||||
}
|
||||
|
||||
// Determine MIME type
|
||||
String mimeType = bridge.getAssetMimeType(path);
|
||||
Log.d(TAG, "Serving " + path + " with type " + mimeType + " (" + data.length + " bytes)");
|
||||
|
||||
// Create response
|
||||
InputStream inputStream = new ByteArrayInputStream(data);
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("Access-Control-Allow-Origin", "*");
|
||||
headers.put("Cache-Control", "no-cache");
|
||||
|
||||
return new WebResourceResponse(
|
||||
mimeType,
|
||||
"UTF-8",
|
||||
200,
|
||||
"OK",
|
||||
headers,
|
||||
inputStream
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine MIME type from file extension
|
||||
*/
|
||||
private String getMimeType(String path) {
|
||||
String lowerPath = path.toLowerCase();
|
||||
|
||||
if (lowerPath.endsWith(".html") || lowerPath.endsWith(".htm")) {
|
||||
return "text/html";
|
||||
} else if (lowerPath.endsWith(".js") || lowerPath.endsWith(".mjs")) {
|
||||
return "application/javascript";
|
||||
} else if (lowerPath.endsWith(".css")) {
|
||||
return "text/css";
|
||||
} else if (lowerPath.endsWith(".json")) {
|
||||
return "application/json";
|
||||
} else if (lowerPath.endsWith(".png")) {
|
||||
return "image/png";
|
||||
} else if (lowerPath.endsWith(".jpg") || lowerPath.endsWith(".jpeg")) {
|
||||
return "image/jpeg";
|
||||
} else if (lowerPath.endsWith(".gif")) {
|
||||
return "image/gif";
|
||||
} else if (lowerPath.endsWith(".svg")) {
|
||||
return "image/svg+xml";
|
||||
} else if (lowerPath.endsWith(".ico")) {
|
||||
return "image/x-icon";
|
||||
} else if (lowerPath.endsWith(".woff")) {
|
||||
return "font/woff";
|
||||
} else if (lowerPath.endsWith(".woff2")) {
|
||||
return "font/woff2";
|
||||
} else if (lowerPath.endsWith(".ttf")) {
|
||||
return "font/ttf";
|
||||
} else if (lowerPath.endsWith(".eot")) {
|
||||
return "application/vnd.ms-fontobject";
|
||||
} else if (lowerPath.endsWith(".xml")) {
|
||||
return "application/xml";
|
||||
} else if (lowerPath.endsWith(".txt")) {
|
||||
return "text/plain";
|
||||
} else if (lowerPath.endsWith(".wasm")) {
|
||||
return "application/wasm";
|
||||
} else if (lowerPath.endsWith(".mp3")) {
|
||||
return "audio/mpeg";
|
||||
} else if (lowerPath.endsWith(".mp4")) {
|
||||
return "video/mp4";
|
||||
} else if (lowerPath.endsWith(".webm")) {
|
||||
return "video/webm";
|
||||
} else if (lowerPath.endsWith(".webp")) {
|
||||
return "image/webp";
|
||||
}
|
||||
|
||||
return "application/octet-stream";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/main_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<WebView
|
||||
android:id="@+id/webview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</FrameLayout>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 7 KiB |
|
After Width: | Height: | Size: 7 KiB |
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="wails_blue">#3574D4</color>
|
||||
<color name="wails_blue_dark">#2C5FB8</color>
|
||||
<color name="wails_background">#1B2636</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
<color name="black">#FF000000</color>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Wails App</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="Theme.WailsApp" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
||||
<!-- Primary brand color. -->
|
||||
<item name="colorPrimary">@color/wails_blue</item>
|
||||
<item name="colorPrimaryVariant">@color/wails_blue_dark</item>
|
||||
<item name="colorOnPrimary">@android:color/white</item>
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor">@color/wails_background</item>
|
||||
<item name="android:navigationBarColor">@color/wails_background</item>
|
||||
<!-- Window background -->
|
||||
<item name="android:windowBackground">@color/wails_background</item>
|
||||
</style>
|
||||
</resources>
|
||||
4
v3/examples/android/build/android/build.gradle
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
plugins {
|
||||
id 'com.android.application' version '8.7.3' apply false
|
||||
}
|
||||
26
v3/examples/android/build/android/gradle.properties
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Project-wide Gradle settings.
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. For more details, visit
|
||||
# https://developer.android.com/build/optimize-your-build#parallel
|
||||
# org.gradle.parallel=true
|
||||
|
||||
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||
# Android operating system, and which are packaged with your app's APK
|
||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||
android.useAndroidX=true
|
||||
|
||||
# Enables namespacing of each library's R class so that its R class includes only the
|
||||
# resources declared in the library itself and none from the library's dependencies,
|
||||
# thereby reducing the size of the R class for that library
|
||||
android.nonTransitiveRClass=true
|
||||
BIN
v3/examples/android/build/android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
7
v3/examples/android/build/android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
248
v3/examples/android/build/android/gradlew
vendored
Executable file
|
|
@ -0,0 +1,248 @@
|
|||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
93
v3/examples/android/build/android/gradlew.bat
vendored
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
151
v3/examples/android/build/android/scripts/deps/install_deps.go
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println("Checking Android development dependencies...")
|
||||
fmt.Println()
|
||||
|
||||
errors := []string{}
|
||||
|
||||
// Check Go
|
||||
if !checkCommand("go", "version") {
|
||||
errors = append(errors, "Go is not installed. Install from https://go.dev/dl/")
|
||||
} else {
|
||||
fmt.Println("✓ Go is installed")
|
||||
}
|
||||
|
||||
// Check ANDROID_HOME
|
||||
androidHome := os.Getenv("ANDROID_HOME")
|
||||
if androidHome == "" {
|
||||
androidHome = os.Getenv("ANDROID_SDK_ROOT")
|
||||
}
|
||||
if androidHome == "" {
|
||||
// Try common default locations
|
||||
home, _ := os.UserHomeDir()
|
||||
possiblePaths := []string{
|
||||
filepath.Join(home, "Android", "Sdk"),
|
||||
filepath.Join(home, "Library", "Android", "sdk"),
|
||||
"/usr/local/share/android-sdk",
|
||||
}
|
||||
for _, p := range possiblePaths {
|
||||
if _, err := os.Stat(p); err == nil {
|
||||
androidHome = p
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if androidHome == "" {
|
||||
errors = append(errors, "ANDROID_HOME not set. Install Android Studio and set ANDROID_HOME environment variable")
|
||||
} else {
|
||||
fmt.Printf("✓ ANDROID_HOME: %s\n", androidHome)
|
||||
}
|
||||
|
||||
// Check adb
|
||||
if !checkCommand("adb", "version") {
|
||||
if androidHome != "" {
|
||||
platformTools := filepath.Join(androidHome, "platform-tools")
|
||||
errors = append(errors, fmt.Sprintf("adb not found. Add %s to PATH", platformTools))
|
||||
} else {
|
||||
errors = append(errors, "adb not found. Install Android SDK Platform-Tools")
|
||||
}
|
||||
} else {
|
||||
fmt.Println("✓ adb is installed")
|
||||
}
|
||||
|
||||
// Check emulator
|
||||
if !checkCommand("emulator", "-list-avds") {
|
||||
if androidHome != "" {
|
||||
emulatorPath := filepath.Join(androidHome, "emulator")
|
||||
errors = append(errors, fmt.Sprintf("emulator not found. Add %s to PATH", emulatorPath))
|
||||
} else {
|
||||
errors = append(errors, "emulator not found. Install Android Emulator via SDK Manager")
|
||||
}
|
||||
} else {
|
||||
fmt.Println("✓ Android Emulator is installed")
|
||||
}
|
||||
|
||||
// Check NDK
|
||||
ndkHome := os.Getenv("ANDROID_NDK_HOME")
|
||||
if ndkHome == "" && androidHome != "" {
|
||||
// Look for NDK in default location
|
||||
ndkDir := filepath.Join(androidHome, "ndk")
|
||||
if entries, err := os.ReadDir(ndkDir); err == nil {
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
ndkHome = filepath.Join(ndkDir, entry.Name())
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ndkHome == "" {
|
||||
errors = append(errors, "Android NDK not found. Install NDK via Android Studio > SDK Manager > SDK Tools > NDK (Side by side)")
|
||||
} else {
|
||||
fmt.Printf("✓ Android NDK: %s\n", ndkHome)
|
||||
}
|
||||
|
||||
// Check Java
|
||||
if !checkCommand("java", "-version") {
|
||||
errors = append(errors, "Java not found. Install JDK 11+ (OpenJDK recommended)")
|
||||
} else {
|
||||
fmt.Println("✓ Java is installed")
|
||||
}
|
||||
|
||||
// Check for AVD (Android Virtual Device)
|
||||
if checkCommand("emulator", "-list-avds") {
|
||||
cmd := exec.Command("emulator", "-list-avds")
|
||||
output, err := cmd.Output()
|
||||
if err == nil && len(strings.TrimSpace(string(output))) > 0 {
|
||||
avds := strings.Split(strings.TrimSpace(string(output)), "\n")
|
||||
fmt.Printf("✓ Found %d Android Virtual Device(s)\n", len(avds))
|
||||
} else {
|
||||
fmt.Println("⚠ No Android Virtual Devices found. Create one via Android Studio > Tools > Device Manager")
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
|
||||
if len(errors) > 0 {
|
||||
fmt.Println("❌ Missing dependencies:")
|
||||
for _, err := range errors {
|
||||
fmt.Printf(" - %s\n", err)
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println("Setup instructions:")
|
||||
fmt.Println("1. Install Android Studio: https://developer.android.com/studio")
|
||||
fmt.Println("2. Open SDK Manager and install:")
|
||||
fmt.Println(" - Android SDK Platform (API 34)")
|
||||
fmt.Println(" - Android SDK Build-Tools")
|
||||
fmt.Println(" - Android SDK Platform-Tools")
|
||||
fmt.Println(" - Android Emulator")
|
||||
fmt.Println(" - NDK (Side by side)")
|
||||
fmt.Println("3. Set environment variables:")
|
||||
if runtime.GOOS == "darwin" {
|
||||
fmt.Println(" export ANDROID_HOME=$HOME/Library/Android/sdk")
|
||||
} else {
|
||||
fmt.Println(" export ANDROID_HOME=$HOME/Android/Sdk")
|
||||
}
|
||||
fmt.Println(" export PATH=$PATH:$ANDROID_HOME/platform-tools:$ANDROID_HOME/emulator")
|
||||
fmt.Println("4. Create an AVD via Android Studio > Tools > Device Manager")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Println("✓ All Android development dependencies are installed!")
|
||||
}
|
||||
|
||||
func checkCommand(name string, args ...string) bool {
|
||||
cmd := exec.Command(name, args...)
|
||||
cmd.Stdout = nil
|
||||
cmd.Stderr = nil
|
||||
return cmd.Run() == nil
|
||||
}
|
||||
18
v3/examples/android/build/android/settings.gradle
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
pluginManagement {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = "WailsApp"
|
||||
include ':app'
|
||||
BIN
v3/examples/android/build/appicon.png
Normal file
|
After Width: | Height: | Size: 130 KiB |
75
v3/examples/android/build/config.yml
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
# 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: "0.0.1" # The application version
|
||||
|
||||
# Android build configuration (uncomment to customise Android project generation)
|
||||
# Note: Keys under `android` OVERRIDE values under `info` when set.
|
||||
# android:
|
||||
# # The Android application ID used in the generated project (applicationId)
|
||||
# applicationId: "com.mycompany.myproduct"
|
||||
# # The display name shown under the app icon
|
||||
# displayName: "My Product"
|
||||
# # The app version code (integer, must increment for each release)
|
||||
# versionCode: 1
|
||||
# # The app version name (displayed to users)
|
||||
# versionName: "0.0.1"
|
||||
# # Minimum SDK version (API level)
|
||||
# minSdkVersion: 21
|
||||
# # Target SDK version (API level)
|
||||
# targetSdkVersion: 34
|
||||
# # The company/organisation name for templates and project settings
|
||||
# company: "My Company"
|
||||
|
||||
# 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
|
||||
|
||||
# Other data
|
||||
other:
|
||||
- name: My Other Data
|
||||
32
v3/examples/android/build/darwin/Info.dev.plist
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>My Product</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>ios</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.wails.ios</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.1.0</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>This is a comment</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.1.0</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>icons</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.15.0</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>true</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>© now, My Company</string>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsLocalNetworking</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
27
v3/examples/android/build/darwin/Info.plist
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>My Product</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>ios</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.wails.ios</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.1.0</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>This is a comment</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.1.0</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>icons</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.15.0</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>true</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>© now, My Company</string>
|
||||
</dict>
|
||||
</plist>
|
||||
81
v3/examples/android/build/darwin/Taskfile.yml
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
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
|
||||
- codesign --force --deep --sign - {{.BIN_DIR}}/{{.APP_NAME}}.app
|
||||
|
||||
run:
|
||||
cmds:
|
||||
- mkdir -p {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/{MacOS,Resources}
|
||||
- cp build/darwin/icons.icns {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Resources
|
||||
- cp {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/MacOS
|
||||
- cp build/darwin/Info.dev.plist {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Info.plist
|
||||
- codesign --force --deep --sign - {{.BIN_DIR}}/{{.APP_NAME}}.dev.app
|
||||
- '{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/MacOS/{{.APP_NAME}}'
|
||||
BIN
v3/examples/android/build/darwin/icons.icns
Normal file
119
v3/examples/android/build/linux/Taskfile.yml
Normal file
|
|
@ -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: '{{.APP_NAME}}'
|
||||
CATEGORIES: 'Development;'
|
||||
OUTPUTFILE: '{{.ROOT_DIR}}/build/linux/{{.APP_NAME}}.desktop'
|
||||
|
||||
run:
|
||||
cmds:
|
||||
- '{{.BIN_DIR}}/{{.APP_NAME}}'
|
||||
34
v3/examples/android/build/linux/appimage/build.sh
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#!/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"
|
||||
11
v3/examples/android/build/linux/desktop
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Name=My Product
|
||||
Comment=My Product Description
|
||||
# The Exec line includes %u to pass the URL to the application
|
||||
Exec=/usr/local/bin/ios %u
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Icon=ios
|
||||
Categories=Utility;
|
||||
StartupWMClass=ios
|
||||
67
v3/examples/android/build/linux/nfpm/nfpm.yaml
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
# 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: "ios"
|
||||
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/ios"
|
||||
dst: "/usr/local/bin/ios"
|
||||
- src: "./build/appicon.png"
|
||||
dst: "/usr/share/icons/hicolor/128x128/apps/ios.png"
|
||||
- src: "./build/linux/ios.desktop"
|
||||
dst: "/usr/share/applications/ios.desktop"
|
||||
|
||||
# Default dependencies for Debian 12/Ubuntu 22.04+ with WebKit 4.1
|
||||
depends:
|
||||
- libgtk-3-0
|
||||
- libwebkit2gtk-4.1-0
|
||||
|
||||
# Distribution-specific overrides for different package formats and WebKit versions
|
||||
overrides:
|
||||
# RPM packages for RHEL/CentOS/AlmaLinux/Rocky Linux (WebKit 4.0)
|
||||
rpm:
|
||||
depends:
|
||||
- gtk3
|
||||
- webkit2gtk4.1
|
||||
|
||||
# Arch Linux packages (WebKit 4.1)
|
||||
archlinux:
|
||||
depends:
|
||||
- gtk3
|
||||
- webkit2gtk-4.1
|
||||
|
||||
# scripts section to ensure desktop database is updated after install
|
||||
scripts:
|
||||
postinstall: "./build/linux/nfpm/scripts/postinstall.sh"
|
||||
# You can also add preremove, postremove if needed
|
||||
# preremove: "./build/linux/nfpm/scripts/preremove.sh"
|
||||
# postremove: "./build/linux/nfpm/scripts/postremove.sh"
|
||||
|
||||
# replaces:
|
||||
# - foobar
|
||||
# provides:
|
||||
# - bar
|
||||
# depends:
|
||||
# - gtk3
|
||||
# - libwebkit2gtk
|
||||
# recommends:
|
||||
# - whatever
|
||||
# suggests:
|
||||
# - something-else
|
||||
# conflicts:
|
||||
# - not-foo
|
||||
# - not-bar
|
||||
# changelog: "changelog.yaml"
|
||||
21
v3/examples/android/build/linux/nfpm/scripts/postinstall.sh
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Update desktop database for .desktop file changes
|
||||
# This makes the application appear in application menus and registers its capabilities.
|
||||
if command -v update-desktop-database >/dev/null 2>&1; then
|
||||
echo "Updating desktop database..."
|
||||
update-desktop-database -q /usr/share/applications
|
||||
else
|
||||
echo "Warning: update-desktop-database command not found. Desktop file may not be immediately recognized." >&2
|
||||
fi
|
||||
|
||||
# Update MIME database for custom URL schemes (x-scheme-handler)
|
||||
# This ensures the system knows how to handle your custom protocols.
|
||||
if command -v update-mime-database >/dev/null 2>&1; then
|
||||
echo "Updating MIME database..."
|
||||
update-mime-database -n /usr/share/mime
|
||||
else
|
||||
echo "Warning: update-mime-database command not found. Custom URL schemes may not be immediately recognized." >&2
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
|
@ -0,0 +1 @@
|
|||
#!/bin/bash
|
||||
|
|
@ -0,0 +1 @@
|
|||
#!/bin/bash
|
||||
|
|
@ -0,0 +1 @@
|
|||
#!/bin/bash
|
||||
98
v3/examples/android/build/windows/Taskfile.yml
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
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
|
||||
cmds:
|
||||
- |-
|
||||
if [ "{{.FORMAT | default "nsis"}}" = "msix" ]; then
|
||||
task: create:msix:package
|
||||
else
|
||||
task: create:nsis:installer
|
||||
fi
|
||||
vars:
|
||||
FORMAT: '{{.FORMAT | default "nsis"}}'
|
||||
|
||||
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}}'
|
||||
|
||||
create:msix:package:
|
||||
summary: Creates an MSIX package
|
||||
deps:
|
||||
- task: build
|
||||
vars:
|
||||
PRODUCTION: "true"
|
||||
cmds:
|
||||
- |-
|
||||
wails3 tool msix \
|
||||
--config "{{.ROOT_DIR}}/wails.json" \
|
||||
--name "{{.APP_NAME}}" \
|
||||
--executable "{{.ROOT_DIR}}/{{.BIN_DIR}}/{{.APP_NAME}}.exe" \
|
||||
--arch "{{.ARCH}}" \
|
||||
--out "{{.ROOT_DIR}}/{{.BIN_DIR}}/{{.APP_NAME}}-{{.ARCH}}.msix" \
|
||||
{{if .CERT_PATH}}--cert "{{.CERT_PATH}}"{{end}} \
|
||||
{{if .PUBLISHER}}--publisher "{{.PUBLISHER}}"{{end}} \
|
||||
{{if .USE_MSIX_TOOL}}--use-msix-tool{{else}}--use-makeappx{{end}}
|
||||
vars:
|
||||
ARCH: '{{.ARCH | default ARCH}}'
|
||||
CERT_PATH: '{{.CERT_PATH | default ""}}'
|
||||
PUBLISHER: '{{.PUBLISHER | default ""}}'
|
||||
USE_MSIX_TOOL: '{{.USE_MSIX_TOOL | default "false"}}'
|
||||
|
||||
install:msix:tools:
|
||||
summary: Installs tools required for MSIX packaging
|
||||
cmds:
|
||||
- wails3 tool msix-install-tools
|
||||
|
||||
run:
|
||||
cmds:
|
||||
- '{{.BIN_DIR}}/{{.APP_NAME}}.exe'
|
||||
BIN
v3/examples/android/build/windows/icon.ico
Normal file
|
After Width: | Height: | Size: 21 KiB |
15
v3/examples/android/build/windows/info.json
Normal file
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
52
v3/examples/android/build/windows/msix/app_manifest.xml
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package
|
||||
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
|
||||
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10">
|
||||
|
||||
<Identity
|
||||
Name="com.wails.ios"
|
||||
Publisher="CN=My Company"
|
||||
Version="0.1.0.0"
|
||||
ProcessorArchitecture="x64" />
|
||||
|
||||
<Properties>
|
||||
<DisplayName>My Product</DisplayName>
|
||||
<PublisherDisplayName>My Company</PublisherDisplayName>
|
||||
<Description>My Product Description</Description>
|
||||
<Logo>Assets\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||
</Dependencies>
|
||||
|
||||
<Resources>
|
||||
<Resource Language="en-us" />
|
||||
</Resources>
|
||||
|
||||
<Applications>
|
||||
<Application Id="com.wails.ios" Executable="ios" EntryPoint="Windows.FullTrustApplication">
|
||||
<uap:VisualElements
|
||||
DisplayName="My Product"
|
||||
Description="My Product Description"
|
||||
BackgroundColor="transparent"
|
||||
Square150x150Logo="Assets\Square150x150Logo.png"
|
||||
Square44x44Logo="Assets\Square44x44Logo.png">
|
||||
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" />
|
||||
<uap:SplashScreen Image="Assets\SplashScreen.png" />
|
||||
</uap:VisualElements>
|
||||
|
||||
<Extensions>
|
||||
<desktop:Extension Category="windows.fullTrustProcess" Executable="ios" />
|
||||
|
||||
</Extensions>
|
||||
</Application>
|
||||
</Applications>
|
||||
|
||||
<Capabilities>
|
||||
<rescap:Capability Name="runFullTrust" />
|
||||
|
||||
</Capabilities>
|
||||
</Package>
|
||||
54
v3/examples/android/build/windows/msix/template.xml
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<MsixPackagingToolTemplate
|
||||
xmlns="http://schemas.microsoft.com/msix/packaging/msixpackagingtool/template/2022">
|
||||
<Settings
|
||||
AllowTelemetry="false"
|
||||
ApplyACLsToPackageFiles="true"
|
||||
GenerateCommandLineFile="true"
|
||||
AllowPromptForPassword="false">
|
||||
</Settings>
|
||||
<Installer
|
||||
Path="ios"
|
||||
Arguments=""
|
||||
InstallLocation="C:\Program Files\My Company\My Product">
|
||||
</Installer>
|
||||
<PackageInformation
|
||||
PackageName="My Product"
|
||||
PackageDisplayName="My Product"
|
||||
PublisherName="CN=My Company"
|
||||
PublisherDisplayName="My Company"
|
||||
Version="0.1.0.0"
|
||||
PackageDescription="My Product Description">
|
||||
<Capabilities>
|
||||
<Capability Name="runFullTrust" />
|
||||
|
||||
</Capabilities>
|
||||
<Applications>
|
||||
<Application
|
||||
Id="com.wails.ios"
|
||||
Description="My Product Description"
|
||||
DisplayName="My Product"
|
||||
ExecutableName="ios"
|
||||
EntryPoint="Windows.FullTrustApplication">
|
||||
|
||||
</Application>
|
||||
</Applications>
|
||||
<Resources>
|
||||
<Resource Language="en-us" />
|
||||
</Resources>
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||
</Dependencies>
|
||||
<Properties>
|
||||
<Framework>false</Framework>
|
||||
<DisplayName>My Product</DisplayName>
|
||||
<PublisherDisplayName>My Company</PublisherDisplayName>
|
||||
<Description>My Product Description</Description>
|
||||
<Logo>Assets\AppIcon.png</Logo>
|
||||
</Properties>
|
||||
</PackageInformation>
|
||||
<SaveLocation PackagePath="ios.msix" />
|
||||
<PackageIntegrity>
|
||||
<CertificatePath></CertificatePath>
|
||||
</PackageIntegrity>
|
||||
</MsixPackagingToolTemplate>
|
||||
112
v3/examples/android/build/windows/nsis/project.nsi
Normal file
|
|
@ -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 "ios"
|
||||
## !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
|
||||
212
v3/examples/android/build/windows/nsis/wails_tools.nsh
Normal file
|
|
@ -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 "ios"
|
||||
!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
|
||||
22
v3/examples/android/build/windows/wails.exe.manifest
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<assemblyIdentity type="win32" name="com.wails.ios" version="0.1.0" processorArchitecture="*"/>
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
<asmv3:application>
|
||||
<asmv3:windowsSettings>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware> <!-- fallback for Windows 7 and 8 -->
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">permonitorv2,permonitor</dpiAwareness> <!-- falls back to per-monitor if per-monitor v2 is not supported -->
|
||||
</asmv3:windowsSettings>
|
||||
</asmv3:application>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<security>
|
||||
<requestedPrivileges>
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
</assembly>
|
||||
93
v3/examples/android/frontend/Inter Font License.txt
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
Copyright 2020 The Inter Project Authors (https://github.com/rsms/inter)
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// @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 { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "@wailsio/runtime";
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @returns {$CancellablePromise<string>}
|
||||
*/
|
||||
export function Greet(name) {
|
||||
return $Call.ByID(1411160069, name);
|
||||
}
|
||||
8
v3/examples/android/frontend/bindings/changeme/index.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
// @ts-check
|
||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
|
||||
import * as GreetService from "./greetservice.js";
|
||||
export {
|
||||
GreetService
|
||||
};
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
//@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";
|
||||
|
||||
Object.freeze($Create.Events);
|
||||
2
v3/examples/android/frontend/bindings/github.com/wailsapp/wails/v3/internal/eventdata.d.ts
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
110
v3/examples/android/frontend/index.html
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<link rel="icon" type="image/svg+xml" href="/wails.png"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<link rel="stylesheet" href="/style.css"/>
|
||||
|
||||
<title>Wails App</title>
|
||||
<!-- Android WebView setup - must run before module scripts to enable window._wails.invoke -->
|
||||
<script>
|
||||
// Android WebView exposes window.wails via addJavascriptInterface
|
||||
// We need to set up window._wails.invoke before the module scripts run
|
||||
if (window.wails && window.wails.invoke) {
|
||||
console.log('[Wails Android Bootstrap] window.wails.invoke detected, setting up _wails');
|
||||
window._wails = window._wails || {};
|
||||
window._wails.invoke = function(m) {
|
||||
return window.wails.invoke(typeof m === 'string' ? m : JSON.stringify(m));
|
||||
};
|
||||
} else {
|
||||
console.log('[Wails Android Bootstrap] window.wails not available yet');
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div>
|
||||
<a data-wml-openURL="https://wails.io">
|
||||
<img src="/wails.png" class="logo" alt="Wails logo"/>
|
||||
</a>
|
||||
<a data-wml-openURL="https://developer.mozilla.org/en-US/docs/Web/JavaScript">
|
||||
<img src="/javascript.svg" class="logo vanilla" alt="JavaScript logo"/>
|
||||
</a>
|
||||
</div>
|
||||
<h1>Wails + Javascript</h1>
|
||||
<div class="card mobile-pane">
|
||||
<div class="result">Demo Screens</div>
|
||||
<div class="p-mobile-tabs-content">
|
||||
<!-- Screen 1: Bindings -->
|
||||
<div class="p-mobile-tabs--content active" id="screen-bindings">
|
||||
<div class="result" id="result">Please enter your name below 👇</div>
|
||||
<div class="input-box" id="input">
|
||||
<input class="input" id="name" type="text" autocomplete="off"/>
|
||||
<button class="p-btn p-prim-col" onclick="doGreet()">Greet</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Screen 2: Go Runtime -->
|
||||
<div class="p-mobile-tabs--content" id="screen-go">
|
||||
<div class="input-box">
|
||||
<label><input type="checkbox" id="goScrollEnabled" checked onchange="setGoToggle('ios:setScrollEnabled', this.checked)"> Scroll Enabled (Go)</label>
|
||||
</div>
|
||||
<div class="input-box">
|
||||
<label><input type="checkbox" id="goBounceEnabled" checked onchange="setGoToggle('ios:setBounceEnabled', this.checked)"> Bounce Enabled (Go)</label>
|
||||
</div>
|
||||
<div class="input-box">
|
||||
<label><input type="checkbox" id="goIndicatorsEnabled" checked onchange="setGoToggle('ios:setScrollIndicatorsEnabled', this.checked)"> Scroll Indicators (Go)</label>
|
||||
</div>
|
||||
<div class="input-box">
|
||||
<label><input type="checkbox" id="goNavGesturesEnabled" onchange="setGoToggle('ios:setBackForwardGesturesEnabled', this.checked)"> Back/Forward Gestures (Go)</label>
|
||||
</div>
|
||||
<div class="input-box">
|
||||
<label><input type="checkbox" id="goLinkPreviewEnabled" checked onchange="setGoToggle('ios:setLinkPreviewEnabled', this.checked)"> Link Preview (Go)</label>
|
||||
</div>
|
||||
<div class="input-box">
|
||||
<input class="input" id="uaInputGo" type="text" placeholder="Custom User Agent"/>
|
||||
<button class="p-btn" onclick="emitGo('ios:setCustomUserAgent', {ua: document.getElementById('uaInputGo').value})">Set UA (Go)</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Screen 3: JS Runtime -->
|
||||
<div class="p-mobile-tabs--content" id="screen-js">
|
||||
<div class="input-box">
|
||||
<button class="p-btn" onclick="doHaptic('light')">Haptic: Light</button>
|
||||
<button class="p-btn" onclick="doHaptic('medium')">Haptic: Medium</button>
|
||||
<button class="p-btn" onclick="doHaptic('heavy')">Haptic: Heavy</button>
|
||||
<button class="p-btn p-prim-col" onclick="getDeviceInfo();">Get Device Info</button>
|
||||
</div>
|
||||
<div class="input-box">
|
||||
<label><input type="checkbox" id="jsScrollEnabled" checked onchange="setJsToggle('Scroll.SetEnabled', this.checked)"> Scroll Enabled (JS)</label>
|
||||
</div>
|
||||
<div class="input-box">
|
||||
<label><input type="checkbox" id="jsBounceEnabled" checked onchange="setJsToggle('Scroll.SetBounceEnabled', this.checked)"> Bounce Enabled (JS)</label>
|
||||
</div>
|
||||
<div class="input-box">
|
||||
<label><input type="checkbox" id="jsIndicatorsEnabled" checked onchange="setJsToggle('Scroll.SetIndicatorsEnabled', this.checked)"> Scroll Indicators (JS)</label>
|
||||
</div>
|
||||
<div class="input-box">
|
||||
<label><input type="checkbox" id="jsNavGesturesEnabled" onchange="setJsToggle('Navigation.SetBackForwardGesturesEnabled', this.checked)"> Back/Forward Gestures (JS)</label>
|
||||
</div>
|
||||
<div class="input-box">
|
||||
<label><input type="checkbox" id="jsLinkPreviewEnabled" checked onchange="setJsToggle('Links.SetPreviewEnabled', this.checked)"> Link Preview (JS)</label>
|
||||
</div>
|
||||
<div class="input-box">
|
||||
<input class="input" id="uaInputJs" type="text" placeholder="Custom User Agent"/>
|
||||
<button class="p-btn" onclick="iosJsSet('UserAgent.Set', {ua: document.getElementById('uaInputJs').value})">Set UA</button>
|
||||
</div>
|
||||
<pre id="deviceInfo" style="white-space: pre-wrap; word-break: break-word;"></pre>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div><p>Click on the Wails logo to learn more</p></div>
|
||||
<div><p id="time">Listening for Time event...</p></div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="module" src="/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
113
v3/examples/android/frontend/main.js
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
import {GreetService} from "./bindings/changeme";
|
||||
import * as Runtime from "@wailsio/runtime";
|
||||
|
||||
const resultElement = document.getElementById('result');
|
||||
const timeElement = document.getElementById('time');
|
||||
const deviceInfoElement = document.getElementById('deviceInfo');
|
||||
const Events = Runtime.Events;
|
||||
const IOS = Runtime.IOS; // May be undefined in published package; we guard usages below.
|
||||
|
||||
window.doGreet = () => {
|
||||
let name = document.getElementById('name').value;
|
||||
if (!name) {
|
||||
name = 'anonymous';
|
||||
}
|
||||
GreetService.Greet(name).then((result) => {
|
||||
resultElement.innerText = result;
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
|
||||
window.doHaptic = (style) => {
|
||||
if (!IOS || !IOS.Haptics?.Impact) {
|
||||
console.warn('IOS runtime not available in @wailsio/runtime. Skipping haptic call.');
|
||||
return;
|
||||
}
|
||||
IOS.Haptics.Impact(style).catch((err) => {
|
||||
console.error('Haptics error:', err);
|
||||
});
|
||||
}
|
||||
|
||||
window.getDeviceInfo = async () => {
|
||||
if (!IOS || !IOS.Device?.Info) {
|
||||
deviceInfoElement.innerText = 'iOS runtime not available; cannot fetch device info.';
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const info = await IOS.Device.Info();
|
||||
deviceInfoElement.innerText = JSON.stringify(info, null, 2);
|
||||
} catch (e) {
|
||||
deviceInfoElement.innerText = `Error: ${e?.message || e}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Generic caller for IOS.<Group>.<Method>(args)
|
||||
window.iosJsSet = async (methodPath, args) => {
|
||||
if (!IOS) {
|
||||
console.warn('IOS runtime not available in @wailsio/runtime.');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const [group, method] = methodPath.split('.');
|
||||
const target = IOS?.[group];
|
||||
const fn = target?.[method];
|
||||
if (typeof fn !== 'function') {
|
||||
console.warn('IOS method not found:', methodPath);
|
||||
return;
|
||||
}
|
||||
await fn(args);
|
||||
} catch (e) {
|
||||
console.error('iosJsSet error for', methodPath, e);
|
||||
}
|
||||
}
|
||||
|
||||
// Emit events for Go handlers
|
||||
window.emitGo = (eventName, data) => {
|
||||
try {
|
||||
Events.Emit(eventName, data);
|
||||
} catch (e) {
|
||||
console.error('emitGo error:', e);
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle helpers for UI switches
|
||||
window.setGoToggle = (eventName, enabled) => {
|
||||
emitGo(eventName, { enabled: !!enabled });
|
||||
}
|
||||
|
||||
window.setJsToggle = (methodPath, enabled) => {
|
||||
iosJsSet(methodPath, { enabled: !!enabled });
|
||||
}
|
||||
|
||||
Events.On('time', (payload) => {
|
||||
// payload may be a plain value or an object with a `data` field depending on emitter/runtime
|
||||
const value = (payload && typeof payload === 'object' && 'data' in payload) ? payload.data : payload;
|
||||
console.log('[frontend] time event:', payload, '->', value);
|
||||
timeElement.innerText = value;
|
||||
});
|
||||
|
||||
// Simple pane switcher responding to native UITabBar
|
||||
function showPaneByIndex(index) {
|
||||
const panes = [
|
||||
document.getElementById('screen-bindings'),
|
||||
document.getElementById('screen-go'),
|
||||
document.getElementById('screen-js'),
|
||||
];
|
||||
panes.forEach((el, i) => {
|
||||
if (!el) return;
|
||||
if (i === index) el.classList.add('active');
|
||||
else el.classList.remove('active');
|
||||
});
|
||||
}
|
||||
|
||||
// Listen for native tab selection events posted by the iOS layer
|
||||
window.addEventListener('nativeTabSelected', (e) => {
|
||||
const idx = (e && e.detail && typeof e.detail.index === 'number') ? e.detail.index : 0;
|
||||
showPaneByIndex(idx);
|
||||
});
|
||||
|
||||
// Ensure default pane is visible on load (index 0)
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
showPaneByIndex(0);
|
||||
});
|
||||
936
v3/examples/android/frontend/package-lock.json
generated
Normal file
|
|
@ -0,0 +1,936 @@
|
|||
{
|
||||
"name": "frontend",
|
||||
"version": "0.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "frontend",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@wailsio/runtime": "latest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"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.50.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.0.tgz",
|
||||
"integrity": "sha512-lVgpeQyy4fWN5QYebtW4buT/4kn4p4IJ+kDNB4uYNT5b8c8DLJDg6titg20NIg7E8RWwdWZORW6vUFfrLyG3KQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.50.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.0.tgz",
|
||||
"integrity": "sha512-2O73dR4Dc9bp+wSYhviP6sDziurB5/HCym7xILKifWdE9UsOe2FtNcM+I4xZjKrfLJnq5UR8k9riB87gauiQtw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.50.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.0.tgz",
|
||||
"integrity": "sha512-vwSXQN8T4sKf1RHr1F0s98Pf8UPz7pS6P3LG9NSmuw0TVh7EmaE+5Ny7hJOZ0M2yuTctEsHHRTMi2wuHkdS6Hg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.50.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.0.tgz",
|
||||
"integrity": "sha512-cQp/WG8HE7BCGyFVuzUg0FNmupxC+EPZEwWu2FCGGw5WDT1o2/YlENbm5e9SMvfDFR6FRhVCBePLqj0o8MN7Vw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||
"version": "4.50.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.0.tgz",
|
||||
"integrity": "sha512-UR1uTJFU/p801DvvBbtDD7z9mQL8J80xB0bR7DqW7UGQHRm/OaKzp4is7sQSdbt2pjjSS72eAtRh43hNduTnnQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||
"version": "4.50.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.0.tgz",
|
||||
"integrity": "sha512-G/DKyS6PK0dD0+VEzH/6n/hWDNPDZSMBmqsElWnCRGrYOb2jC0VSupp7UAHHQ4+QILwkxSMaYIbQ72dktp8pKA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.50.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.0.tgz",
|
||||
"integrity": "sha512-u72Mzc6jyJwKjJbZZcIYmd9bumJu7KNmHYdue43vT1rXPm2rITwmPWF0mmPzLm9/vJWxIRbao/jrQmxTO0Sm9w==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||
"version": "4.50.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.0.tgz",
|
||||
"integrity": "sha512-S4UefYdV0tnynDJV1mdkNawp0E5Qm2MtSs330IyHgaccOFrwqsvgigUD29uT+B/70PDY1eQ3t40+xf6wIvXJyg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.50.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.0.tgz",
|
||||
"integrity": "sha512-1EhkSvUQXJsIhk4msxP5nNAUWoB4MFDHhtc4gAYvnqoHlaL9V3F37pNHabndawsfy/Tp7BPiy/aSa6XBYbaD1g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.50.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.0.tgz",
|
||||
"integrity": "sha512-EtBDIZuDtVg75xIPIK1l5vCXNNCIRM0OBPUG+tbApDuJAy9mKago6QxX+tfMzbCI6tXEhMuZuN1+CU8iDW+0UQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
|
||||
"version": "4.50.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.50.0.tgz",
|
||||
"integrity": "sha512-BGYSwJdMP0hT5CCmljuSNx7+k+0upweM2M4YGfFBjnFSZMHOLYR0gEEj/dxyYJ6Zc6AiSeaBY8dWOa11GF/ppQ==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
|
||||
"version": "4.50.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.0.tgz",
|
||||
"integrity": "sha512-I1gSMzkVe1KzAxKAroCJL30hA4DqSi+wGc5gviD0y3IL/VkvcnAqwBf4RHXHyvH66YVHxpKO8ojrgc4SrWAnLg==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.50.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.0.tgz",
|
||||
"integrity": "sha512-bSbWlY3jZo7molh4tc5dKfeSxkqnf48UsLqYbUhnkdnfgZjgufLS/NTA8PcP/dnvct5CCdNkABJ56CbclMRYCA==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-musl": {
|
||||
"version": "4.50.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.0.tgz",
|
||||
"integrity": "sha512-LSXSGumSURzEQLT2e4sFqFOv3LWZsEF8FK7AAv9zHZNDdMnUPYH3t8ZlaeYYZyTXnsob3htwTKeWtBIkPV27iQ==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||
"version": "4.50.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.0.tgz",
|
||||
"integrity": "sha512-CxRKyakfDrsLXiCyucVfVWVoaPA4oFSpPpDwlMcDFQvrv3XY6KEzMtMZrA+e/goC8xxp2WSOxHQubP8fPmmjOQ==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.50.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.0.tgz",
|
||||
"integrity": "sha512-8PrJJA7/VU8ToHVEPu14FzuSAqVKyo5gg/J8xUerMbyNkWkO9j2ExBho/68RnJsMGNJq4zH114iAttgm7BZVkA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.50.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.0.tgz",
|
||||
"integrity": "sha512-SkE6YQp+CzpyOrbw7Oc4MgXFvTw2UIBElvAvLCo230pyxOLmYwRPwZ/L5lBe/VW/qT1ZgND9wJfOsdy0XptRvw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-openharmony-arm64": {
|
||||
"version": "4.50.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.0.tgz",
|
||||
"integrity": "sha512-PZkNLPfvXeIOgJWA804zjSFH7fARBBCpCXxgkGDRjjAhRLOR8o0IGS01ykh5GYfod4c2yiiREuDM8iZ+pVsT+Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openharmony"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.50.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.0.tgz",
|
||||
"integrity": "sha512-q7cIIdFvWQoaCbLDUyUc8YfR3Jh2xx3unO8Dn6/TTogKjfwrax9SyfmGGK6cQhKtjePI7jRfd7iRYcxYs93esg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.50.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.0.tgz",
|
||||
"integrity": "sha512-XzNOVg/YnDOmFdDKcxxK410PrcbcqZkBmz+0FicpW5jtjKQxcW1BZJEQOF0NJa6JO7CZhett8GEtRN/wYLYJuw==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.50.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.0.tgz",
|
||||
"integrity": "sha512-xMmiWRR8sp72Zqwjgtf3QbZfF1wdh8X2ABu3EaozvZcyHJeU0r+XAnXdKgs4cCAp6ORoYoCygipYP1mjmbjrsg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
||||
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
|
||||
"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==",
|
||||
"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.6",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
|
||||
"integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
|
||||
"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.11",
|
||||
"picocolors": "^1.1.1",
|
||||
"source-map-js": "^1.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.50.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.50.0.tgz",
|
||||
"integrity": "sha512-/Zl4D8zPifNmyGzJS+3kVoyXeDeT/GrsJM94sACNg9RtUE0hrHa1bNPtRSrfHTMH5HjRzce6K7rlTh3Khiw+pw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "1.0.8"
|
||||
},
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0",
|
||||
"npm": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-android-arm-eabi": "4.50.0",
|
||||
"@rollup/rollup-android-arm64": "4.50.0",
|
||||
"@rollup/rollup-darwin-arm64": "4.50.0",
|
||||
"@rollup/rollup-darwin-x64": "4.50.0",
|
||||
"@rollup/rollup-freebsd-arm64": "4.50.0",
|
||||
"@rollup/rollup-freebsd-x64": "4.50.0",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.50.0",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.50.0",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.50.0",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.50.0",
|
||||
"@rollup/rollup-linux-loongarch64-gnu": "4.50.0",
|
||||
"@rollup/rollup-linux-ppc64-gnu": "4.50.0",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.50.0",
|
||||
"@rollup/rollup-linux-riscv64-musl": "4.50.0",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.50.0",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.50.0",
|
||||
"@rollup/rollup-linux-x64-musl": "4.50.0",
|
||||
"@rollup/rollup-openharmony-arm64": "4.50.0",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.50.0",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.50.0",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.50.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/vite": {
|
||||
"version": "5.4.19",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz",
|
||||
"integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==",
|
||||
"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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
18
v3/examples/android/frontend/package.json
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "frontend",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build:dev": "vite build --minify false --mode development",
|
||||
"build": "vite build --mode production",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@wailsio/runtime": "latest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^5.0.0"
|
||||
}
|
||||
}
|
||||
BIN
v3/examples/android/frontend/public/Inter-Medium.ttf
Normal file
1
v3/examples/android/frontend/public/javascript.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="32" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path fill="#F7DF1E" d="M0 0h256v256H0V0Z"></path><path d="m67.312 213.932l19.59-11.856c3.78 6.701 7.218 12.371 15.465 12.371c7.905 0 12.89-3.092 12.89-15.12v-81.798h24.057v82.138c0 24.917-14.606 36.259-35.916 36.259c-19.245 0-30.416-9.967-36.087-21.996m85.07-2.576l19.588-11.341c5.157 8.421 11.859 14.607 23.715 14.607c9.969 0 16.325-4.984 16.325-11.858c0-8.248-6.53-11.17-17.528-15.98l-6.013-2.58c-17.357-7.387-28.87-16.667-28.87-36.257c0-18.044 13.747-31.792 35.228-31.792c15.294 0 26.292 5.328 34.196 19.247l-18.732 12.03c-4.125-7.389-8.591-10.31-15.465-10.31c-7.046 0-11.514 4.468-11.514 10.31c0 7.217 4.468 10.14 14.778 14.608l6.014 2.577c20.45 8.765 31.963 17.7 31.963 37.804c0 21.654-17.012 33.51-39.867 33.51c-22.339 0-36.774-10.654-43.819-24.574"></path></svg>
|
||||
|
After Width: | Height: | Size: 995 B |
21
v3/examples/android/frontend/public/puppertino/LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2019 Edgar Pérez
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
149
v3/examples/android/frontend/public/puppertino/css/actions.css
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
:root {
|
||||
--font: -apple-system, "Inter", sans-serif;
|
||||
--primary-col-ac: #0f75f5;
|
||||
--p-modal-bg: rgba(255, 255, 255, 0.8);
|
||||
--p-modal-bd-color: rgba(0,0,0,.1);
|
||||
--p-modal-fallback-color: rgba(255,255,255,.95);
|
||||
--p-actions-static-color: #555761;
|
||||
}
|
||||
|
||||
.p-modal-opened {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.p-action-background{
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
height: 100vh;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
transition: 0.3s;
|
||||
width: 100vw;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.p-action-background.nowactive {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
|
||||
.p-action-big-container{
|
||||
position:fixed;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 1rem 5vw;
|
||||
bottom:0;
|
||||
}
|
||||
|
||||
.p-action-container{
|
||||
background: var(--p-modal-bg);
|
||||
display:block;
|
||||
margin:auto;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 10px;
|
||||
max-width: 700px;
|
||||
}
|
||||
|
||||
.p-action-big-container .p-action-container:first-child{
|
||||
margin-bottom:10px;
|
||||
}
|
||||
|
||||
.p-action--intern{
|
||||
width: 100%;
|
||||
display:block;
|
||||
margin:auto;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
text-align:center;
|
||||
padding: 15px 0;
|
||||
border: 0;
|
||||
border-bottom: 1px solid #bfbfbf;
|
||||
color: #0f75f5;
|
||||
text-decoration:none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.p-action-destructive{
|
||||
color: #c6262e;
|
||||
}
|
||||
|
||||
.p-action-neutral{
|
||||
color: var(--p-actions-static-color);
|
||||
}
|
||||
|
||||
.p-action-cancel, .p-action-container a:last-child{
|
||||
border-bottom:none;
|
||||
}
|
||||
|
||||
.p-action-cancel{
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
.p-action-icon{
|
||||
position:relative;
|
||||
}
|
||||
.p-action-icon svg, .p-action-icon img{
|
||||
position:absolute;
|
||||
left:5%;
|
||||
top:50%;
|
||||
transform:translateY(-50%);
|
||||
}
|
||||
|
||||
.p-action-icon-inline{
|
||||
text-align: left;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.p-action-icon-inline svg, .p-action-icon-inline img{
|
||||
margin-left: 5%;
|
||||
margin-right: 3%;
|
||||
}
|
||||
|
||||
.p-action-title{
|
||||
padding: 30px 15px;
|
||||
border-bottom: 1px solid #bfbfbf;
|
||||
}
|
||||
|
||||
.p-action-title--intern,.p-action-text{
|
||||
margin:0;
|
||||
color:var(--p-actions-static-color);
|
||||
}
|
||||
|
||||
.p-action-title--intern{
|
||||
margin-bottom: .3rem;
|
||||
}
|
||||
|
||||
@supports not (backdrop-filter: blur(10px)) {
|
||||
.p-action-container {
|
||||
background: var(--p-modal-fallback-color);
|
||||
}
|
||||
}
|
||||
|
||||
.p-action-big-container{
|
||||
-webkit-transform: translateY(30%);
|
||||
transform: translateY(30%);
|
||||
opacity: 0;
|
||||
transition: opacity 0.4s, transform 0.4s;
|
||||
transition-timing-function: ease;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.p-action-big-container.active {
|
||||
-webkit-transform: translateY(0);
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
|
||||
.p-action-big-container.active .p-action-container {
|
||||
backdrop-filter: saturate(180%) blur(10px);
|
||||
}
|
||||
|
||||
.p-action-big-container[aria-hidden="true"] .p-action--intern {
|
||||
display: none;
|
||||
}
|
||||
158
v3/examples/android/frontend/public/puppertino/css/buttons.css
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
@charset "UTF-8";
|
||||
:root{
|
||||
--p-btn-border: #cacaca;
|
||||
--p-btn-def-bg: #FFFFFF;
|
||||
--p-btn-def-col: #000000;
|
||||
--p-btn-dir-col: #242424;
|
||||
--p-prim-text-col: #f5f5f5;
|
||||
--p-btn-scope-unactive: #212136;
|
||||
--p-btn-scope-action: #212136;
|
||||
}
|
||||
|
||||
.p-btn {
|
||||
background: var(--p-btn-def-bg);
|
||||
border: 1px solid var(--p-btn-border);
|
||||
border-radius: 10px;
|
||||
color: var(--p-btn-def-col);
|
||||
display: inline-block;
|
||||
font-family: -apple-system, "Inter", sans-serif;
|
||||
font-size: 1.1rem;
|
||||
margin: .7rem;
|
||||
padding: .4rem 1.2rem;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
box-shadow: 0 1px 0.375px rgba(0, 0, 0, 0.05), 0 0.25px 0.375px rgba(0, 0, 0, 0.15);
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.p-btn:focus{
|
||||
outline: 2px solid #64baff;
|
||||
}
|
||||
.p-btn.p-btn-block{
|
||||
display: block;
|
||||
}
|
||||
.p-btn.p-btn-sm {
|
||||
padding: .3rem 1.1rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
.p-btn.p-btn-md {
|
||||
padding: .8rem 2.4rem;
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
.p-btn.p-btn-lg {
|
||||
padding: 1.2rem 2.8rem;
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
.p-btn-destructive{
|
||||
color: #FF3B30;
|
||||
}
|
||||
.p-btn-mob{
|
||||
padding: 10px 40px;
|
||||
background: #227bec;
|
||||
color: #fff;
|
||||
border: 0;
|
||||
box-shadow: inset 0 1px 1px rgb(255 255 255 / 41%), 0px 2px 3px -2px rgba(0,0,0,.3);
|
||||
}
|
||||
.p-btn[disabled],
|
||||
.p-btn:disabled,
|
||||
.p-btn-disabled{
|
||||
filter:contrast(0.5) grayscale(.5) opacity(.8);
|
||||
cursor: not-allowed;
|
||||
box-shadow: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.p-prim-col {
|
||||
position: relative;
|
||||
background: #007AFF;
|
||||
border: none;
|
||||
box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.41), 0px 2px 3px -2px rgba(0, 0, 0, 0.3);
|
||||
color: var(--p-prim-text-col);
|
||||
overflow: hidden; /* Ensure the ::before element doesn't overflow */
|
||||
}
|
||||
|
||||
.p-prim-col:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(180deg, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
|
||||
opacity: 0.17;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.p-btn.p-prim-col:active {
|
||||
background: #0f75f5;
|
||||
}
|
||||
|
||||
.p-btn-more::after {
|
||||
content: "...";
|
||||
}
|
||||
|
||||
.p-btn-round {
|
||||
border: 0;
|
||||
border-radius: 50px;
|
||||
box-shadow: inset 0 1px 1px rgb(255 255 255 / 41%);
|
||||
padding: 10px 30px;
|
||||
}
|
||||
|
||||
.p-btn-icon {
|
||||
align-items: center;
|
||||
background: var(--p-btn-def-bg);
|
||||
border: 2px solid currentColor;
|
||||
border-radius: 50%;
|
||||
color: #0f75f5;
|
||||
display: inline-flex;
|
||||
font-weight: 900;
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
justify-content: center;
|
||||
margin: 5px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
box-sizing: border-box;
|
||||
user-select: none;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.p-btn-icon.p-btn-icon-no-border{
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
.p-btn-scope {
|
||||
background: #8e8e8e;
|
||||
color: #fff;
|
||||
margin: 5px;
|
||||
padding: 2px 20px;
|
||||
box-shadow: none;
|
||||
}
|
||||
.p-btn-scope-unactive {
|
||||
background: transparent;
|
||||
border-color: transparent;
|
||||
color: var(--p-btn-scope-unactive);
|
||||
transition: border-color 0.2s;
|
||||
}
|
||||
.p-btn-scope-unactive:hover {
|
||||
border-color: var(--p-btn-border);
|
||||
}
|
||||
|
||||
.p-btn-scope-outline {
|
||||
background: transparent;
|
||||
color: var(--p-btn-scope-action);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.p-btn-outline {
|
||||
background: none;
|
||||
border-color: currentColor;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.p-btn-outline-dash {
|
||||
background: none;
|
||||
border-color: currentColor;
|
||||
border-style: dashed;
|
||||
box-shadow: none;
|
||||
}
|
||||
55
v3/examples/android/frontend/public/puppertino/css/cards.css
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
:root{
|
||||
--p-color-card: #1a1a1a;
|
||||
--p-bg-card: #fff;
|
||||
--p-bd-card: #c5c5c55e;
|
||||
}
|
||||
.p-card {
|
||||
background: var(--p-bg-card);
|
||||
border: 1px solid var(--p-bd-card);
|
||||
color: var(--p-color-card);
|
||||
display: block;
|
||||
margin: 15px;
|
||||
margin-left:7.5px;
|
||||
margin-right:7.5px;
|
||||
text-decoration: none;
|
||||
border-radius: 25px;
|
||||
padding: 20px 0px;
|
||||
transition: .3s ease;
|
||||
box-shadow: 0 0.5px 1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.p-card-image > img {
|
||||
border-bottom: 3px solid var(--accent-article);
|
||||
display: block;
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
}
|
||||
.p-card-tags {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
.p-card-tags::before {
|
||||
background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 75%, white 100%);
|
||||
content: "";
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 30%;
|
||||
}
|
||||
.p-card-title {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 15px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
.p-card-content {
|
||||
padding: 15px;
|
||||
padding-top: 15px;
|
||||
}
|
||||
.p-card-text {
|
||||
font-size: 17px;
|
||||
margin-bottom: 10px;
|
||||
margin-left: 10px;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,917 @@
|
|||
:root{
|
||||
--p-strawberry: #c6262e;
|
||||
--p-strawberry-100: #ff8c82;
|
||||
--p-strawberry-300: #ed5353;
|
||||
--p-strawberry-500: #c6262e;
|
||||
--p-strawberry-700: #a10705;
|
||||
--p-strawberry-900: #7a0000;
|
||||
|
||||
--p-orange: #f37329;
|
||||
--p-orange-100: #ffc27d;
|
||||
--p-orange-300: #ffa154;
|
||||
--p-orange-500: #f37329;
|
||||
--p-orange-700: #cc3b02;
|
||||
--p-orange-900: #a62100;
|
||||
|
||||
|
||||
--p-banana: #f9c440;
|
||||
--p-banana-100: #fff394;
|
||||
--p-banana-300: #ffe16b;
|
||||
--p-banana-500: #f9c440;
|
||||
--p-banana-700: #d48e15;
|
||||
--p-banana-900: #ad5f00;
|
||||
|
||||
--p-lime: #68b723;
|
||||
--p-lime-100: #d1ff82;
|
||||
--p-lime-300: #9bdb4d;
|
||||
--p-lime-500: #68b723;
|
||||
--p-lime-700: #3a9104;
|
||||
--p-lime-900: #206b00;
|
||||
|
||||
--p-mint: #28bca3;
|
||||
--p-mint-100: #89ffdd;
|
||||
--p-mint-300: #43d6b5;
|
||||
--p-mint-500: #28bca3;
|
||||
--p-mint-700: #0e9a83;
|
||||
--p-mint-900: #007367;
|
||||
|
||||
|
||||
--p-blueberry: #3689e6;
|
||||
--p-blueberry-100: #8cd5ff;
|
||||
--p-blueberry-300: #64baff;
|
||||
--p-blueberry-500: #3689e6;
|
||||
--p-blueberry-700: #0d52bf;
|
||||
--p-blueberry-900: #002e99;
|
||||
|
||||
--p-grape: #a56de2;
|
||||
--p-grape-100: #e4c6fa;
|
||||
--p-grape-300: #cd9ef7;
|
||||
--p-grape-500: #a56de2;
|
||||
--p-grape-700: #7239b3;
|
||||
--p-grape-900: #452981;
|
||||
|
||||
--p-bubblegum: #de3e80;
|
||||
--p-bubblegum-100: #fe9ab8;
|
||||
--p-bubblegum-300: #f4679d;
|
||||
--p-bubblegum-500: #de3e80;
|
||||
--p-bubblegum-700: #bc245d;
|
||||
--p-bubblegum-900: #910e38;
|
||||
|
||||
|
||||
--p-cocoa: #715344;
|
||||
--p-cocoa-100: #a3907c;
|
||||
--p-cocoa-300: #8a715e;
|
||||
--p-cocoa-500: #715344;
|
||||
--p-cocoa-700: #57392d;
|
||||
--p-cocoa-900: #3d211b;
|
||||
|
||||
--p-silver: #abacae;
|
||||
--p-silver-100: #fafafa;
|
||||
--p-silver-300: #d4d4d4;
|
||||
--p-silver-500: #abacae;
|
||||
--p-silver-700: #7e8087;
|
||||
--p-silver-900: #555761;
|
||||
|
||||
--p-slate: #485a6c;
|
||||
--p-slate-100: #95a3ab;
|
||||
--p-slate-300: #667885;
|
||||
--p-slate-500: #485a6c;
|
||||
--p-slate-700: #273445;
|
||||
--p-slate-900: #0e141f;
|
||||
|
||||
|
||||
--p-dark: #333;
|
||||
--p-dark-100: #666;
|
||||
--p-dark-300: #4d4d4d;
|
||||
--p-dark-500: #333;
|
||||
--p-dark-700: #1a1a1a;
|
||||
--p-dark-900: #000;
|
||||
|
||||
|
||||
--p-apple-red: rgb(255, 59 , 48);
|
||||
--p-apple-red-dark: rgb(255, 69 , 58);
|
||||
--p-apple-orange: rgb(255,149,0);
|
||||
--p-apple-orange-dark: rgb(255,159,10);
|
||||
--p-apple-yellow: rgb(255,204,0);
|
||||
--p-apple-yellow-dark: rgb(255,214,10);
|
||||
--p-apple-green: rgb(40,205,65);
|
||||
--p-apple-green-dark: rgb(40,215,75);
|
||||
--p-apple-mint: rgb(0,199,190);
|
||||
--p-apple-mint-dark: rgb(102,212,207);
|
||||
--p-apple-teal: rgb(89, 173, 196);
|
||||
--p-apple-teal-dark: rgb(106, 196, 220);
|
||||
--p-apple-cyan: rgb(85,190,240);
|
||||
--p-apple-cyan-dark: rgb(90,200,245);
|
||||
--p-apple-blue: rgb(0, 122, 255);
|
||||
--p-apple-blue-dark: rgb(10, 132, 255);
|
||||
--p-apple-indigo: rgb(88, 86, 214);
|
||||
--p-apple-indigo-dark: rgb(94, 92, 230);
|
||||
--p-apple-purple: rgb(175, 82, 222);
|
||||
--p-apple-purple-dark: rgb(191, 90, 242);
|
||||
--p-apple-pink: rgb(255, 45, 85);
|
||||
--p-apple-pink-dark: rgb(255, 55, 95);
|
||||
--p-apple-brown: rgb(162, 132, 94);
|
||||
--p-apple-brown-dark: rgb(172, 142, 104);
|
||||
--p-apple-gray: rgb(142, 142, 147);
|
||||
--p-apple-gray-dark: rgb(152, 152, 157);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
APPLE OFFICIAL COLORS
|
||||
*/
|
||||
|
||||
.p-apple-red{
|
||||
background: rgb(255, 59 , 48);
|
||||
}
|
||||
|
||||
.p-apple-red-dark{
|
||||
background: rgb(255, 69 , 58);
|
||||
}
|
||||
|
||||
.p-apple-orange{
|
||||
background: rgb(255,149,0);
|
||||
}
|
||||
|
||||
.p-apple-orange-dark{
|
||||
background: rgb(255,159,10);
|
||||
}
|
||||
|
||||
.p-apple-yellow{
|
||||
background: rgb(255,204,0);
|
||||
}
|
||||
|
||||
.p-apple-yellow-dark{
|
||||
background: rgb(255,214,10);
|
||||
}
|
||||
|
||||
.p-apple-green{
|
||||
background: rgb(40,205,65);
|
||||
}
|
||||
|
||||
.p-apple-green-dark{
|
||||
background: rgb(40,215,75);
|
||||
}
|
||||
|
||||
.p-apple-mint{
|
||||
background: rgb(0,199,190);
|
||||
}
|
||||
|
||||
.p-apple-mint-dark{
|
||||
background: rgb(102,212,207);
|
||||
}
|
||||
|
||||
.p-apple-teal{
|
||||
background: rgb(89, 173, 196);
|
||||
}
|
||||
|
||||
.p-apple-teal-dark{
|
||||
background: rgb(106, 196, 220);
|
||||
}
|
||||
|
||||
.p-apple-cyan{
|
||||
background: rgb(85,190,240);
|
||||
}
|
||||
|
||||
.p-apple-cyan-dark{
|
||||
background: rgb(90,200,245);
|
||||
}
|
||||
|
||||
.p-apple-blue{
|
||||
background: rgb(0, 122, 255);
|
||||
}
|
||||
|
||||
.p-apple-blue-dark{
|
||||
background: rgb(10, 132, 255);
|
||||
}
|
||||
|
||||
.p-apple-indigo{
|
||||
background: rgb(88, 86, 214);
|
||||
}
|
||||
|
||||
.p-apple-indigo-dark{
|
||||
background: rgb(94, 92, 230);
|
||||
}
|
||||
|
||||
.p-apple-purple{
|
||||
background: rgb(175, 82, 222);
|
||||
}
|
||||
|
||||
.p-apple-purple-dark{
|
||||
background: rgb(191, 90, 242);
|
||||
}
|
||||
|
||||
.p-apple-pink{
|
||||
background: rgb(255, 45, 85);
|
||||
}
|
||||
|
||||
.p-apple-pink-dark{
|
||||
background: rgb(255, 55, 95);
|
||||
}
|
||||
|
||||
.p-apple-brown{
|
||||
background: rgb(162, 132, 94);
|
||||
}
|
||||
|
||||
.p-apple-brown-dark{
|
||||
background: rgb(172, 142, 104);
|
||||
}
|
||||
|
||||
.p-apple-gray{
|
||||
background: rgb(142, 142, 147);
|
||||
}
|
||||
|
||||
.p-apple-gray-dark{
|
||||
background: rgb(152, 152, 157);
|
||||
}
|
||||
|
||||
.p-apple-red-color{
|
||||
color: rgb(255, 59 , 48);
|
||||
}
|
||||
|
||||
.p-apple-red-dark-color{
|
||||
color: rgb(255, 69 , 58);
|
||||
}
|
||||
|
||||
.p-apple-orange-color{
|
||||
color: rgb(255,149,0);
|
||||
}
|
||||
|
||||
.p-apple-orange-dark-color{
|
||||
color: rgb(255,159,10);
|
||||
}
|
||||
|
||||
.p-apple-yellow-color{
|
||||
color: rgb(255,204,0);
|
||||
}
|
||||
|
||||
.p-apple-yellow-dark-color{
|
||||
color: rgb(255,214,10);
|
||||
}
|
||||
|
||||
.p-apple-green-color{
|
||||
color: rgb(40,205,65);
|
||||
}
|
||||
|
||||
.p-apple-green-dark-color{
|
||||
color: rgb(40,215,75);
|
||||
}
|
||||
|
||||
.p-apple-mint-color{
|
||||
color: rgb(0,199,190);
|
||||
}
|
||||
|
||||
.p-apple-mint-dark-color{
|
||||
color: rgb(102,212,207);
|
||||
}
|
||||
|
||||
.p-apple-teal-color{
|
||||
color: rgb(89, 173, 196);
|
||||
}
|
||||
|
||||
.p-apple-teal-dark-color{
|
||||
color: rgb(106, 196, 220);
|
||||
}
|
||||
|
||||
.p-apple-cyan-color{
|
||||
color: rgb(85,190,240);
|
||||
}
|
||||
|
||||
.p-apple-cyan-dark-color{
|
||||
color: rgb(90,200,245);
|
||||
}
|
||||
|
||||
.p-apple-blue-color{
|
||||
color: rgb(0, 122, 255);
|
||||
}
|
||||
|
||||
.p-apple-blue-dark-color{
|
||||
color: rgb(10, 132, 255);
|
||||
}
|
||||
|
||||
.p-apple-indigo-color{
|
||||
color: rgb(88, 86, 214);
|
||||
}
|
||||
|
||||
.p-apple-indigo-dark-color{
|
||||
color: rgb(94, 92, 230);
|
||||
}
|
||||
|
||||
.p-apple-purple-color{
|
||||
color: rgb(175, 82, 222);
|
||||
}
|
||||
|
||||
.p-apple-purple-dark-color{
|
||||
color: rgb(191, 90, 242);
|
||||
}
|
||||
|
||||
.p-apple-pink-color{
|
||||
color: rgb(255, 45, 85);
|
||||
}
|
||||
|
||||
.p-apple-pink-dark-color{
|
||||
color: rgb(255, 55, 95);
|
||||
}
|
||||
|
||||
.p-apple-brown-color{
|
||||
color: rgb(162, 132, 94);
|
||||
}
|
||||
|
||||
.p-apple-brown-dark-color{
|
||||
color: rgb(172, 142, 104);
|
||||
}
|
||||
|
||||
.p-apple-gray-color{
|
||||
color: rgb(142, 142, 147);
|
||||
}
|
||||
|
||||
.p-apple-gray-dark-color{
|
||||
color: rgb(152, 152, 157);
|
||||
}
|
||||
|
||||
.p-strawberry {
|
||||
background: #c6262e;
|
||||
}
|
||||
|
||||
.p-strawberry-100 {
|
||||
background: #ff8c82;
|
||||
}
|
||||
|
||||
.p-strawberry-300 {
|
||||
background: #ed5353;
|
||||
}
|
||||
|
||||
.p-strawberry-500 {
|
||||
background: #c6262e;
|
||||
}
|
||||
|
||||
.p-strawberry-700 {
|
||||
background: #a10705;
|
||||
}
|
||||
|
||||
.p-strawberry-900 {
|
||||
background: #7a0000;
|
||||
}
|
||||
|
||||
.p-orange {
|
||||
background: #f37329;
|
||||
}
|
||||
|
||||
.p-orange-100 {
|
||||
background: #ffc27d;
|
||||
}
|
||||
|
||||
.p-orange-300 {
|
||||
background: #ffa154;
|
||||
}
|
||||
|
||||
.p-orange-500 {
|
||||
background: #f37329;
|
||||
}
|
||||
|
||||
.p-orange-700 {
|
||||
background: #cc3b02;
|
||||
}
|
||||
|
||||
.p-orange-900 {
|
||||
background: #a62100;
|
||||
}
|
||||
|
||||
.p-banana {
|
||||
background: #f9c440;
|
||||
}
|
||||
|
||||
.p-banana-100 {
|
||||
background: #fff394;
|
||||
}
|
||||
|
||||
.p-banana-300 {
|
||||
background: #ffe16b;
|
||||
}
|
||||
|
||||
.p-banana-500 {
|
||||
background: #f9c440;
|
||||
}
|
||||
|
||||
.p-banana-700 {
|
||||
background: #d48e15;
|
||||
}
|
||||
|
||||
.p-banana-900 {
|
||||
background: #ad5f00;
|
||||
}
|
||||
|
||||
.p-lime {
|
||||
background: #68b723;
|
||||
}
|
||||
|
||||
.p-lime-100 {
|
||||
background: #d1ff82;
|
||||
}
|
||||
|
||||
.p-lime-300 {
|
||||
background: #9bdb4d;
|
||||
}
|
||||
|
||||
.p-lime-500 {
|
||||
background: #68b723;
|
||||
}
|
||||
|
||||
.p-lime-700 {
|
||||
background: #3a9104;
|
||||
}
|
||||
|
||||
.p-lime-900 {
|
||||
background: #206b00;
|
||||
}
|
||||
|
||||
.p-mint {
|
||||
background: #28bca3;
|
||||
}
|
||||
|
||||
.p-mint-100 {
|
||||
background: #89ffdd;
|
||||
}
|
||||
|
||||
.p-mint-300 {
|
||||
background: #43d6b5;
|
||||
}
|
||||
|
||||
.p-mint-500 {
|
||||
background: #28bca3;
|
||||
}
|
||||
|
||||
.p-mint-700 {
|
||||
background: #0e9a83;
|
||||
}
|
||||
|
||||
.p-mint-900 {
|
||||
background: #007367;
|
||||
}
|
||||
|
||||
.p-blueberry {
|
||||
background: #3689e6;
|
||||
}
|
||||
|
||||
.p-blueberry-100 {
|
||||
background: #8cd5ff;
|
||||
}
|
||||
|
||||
.p-blueberry-300 {
|
||||
background: #64baff;
|
||||
}
|
||||
|
||||
.p-blueberry-500 {
|
||||
background: #3689e6;
|
||||
}
|
||||
|
||||
.p-blueberry-700 {
|
||||
background: #0d52bf;
|
||||
}
|
||||
|
||||
.p-blueberry-900 {
|
||||
background: #002e99;
|
||||
}
|
||||
|
||||
.p-grape {
|
||||
background: #a56de2;
|
||||
}
|
||||
|
||||
.p-grape-100 {
|
||||
background: #e4c6fa;
|
||||
}
|
||||
|
||||
.p-grape-300 {
|
||||
background: #cd9ef7;
|
||||
}
|
||||
|
||||
.p-grape-500 {
|
||||
background: #a56de2;
|
||||
}
|
||||
|
||||
.p-grape-700 {
|
||||
background: #7239b3;
|
||||
}
|
||||
|
||||
.p-grape-900 {
|
||||
background: #452981;
|
||||
}
|
||||
|
||||
.p-bubblegum {
|
||||
background: #de3e80;
|
||||
}
|
||||
|
||||
.p-bubblegum-100 {
|
||||
background: #fe9ab8;
|
||||
}
|
||||
|
||||
.p-bubblegum-300 {
|
||||
background: #f4679d;
|
||||
}
|
||||
|
||||
.p-bubblegum-500 {
|
||||
background: #de3e80;
|
||||
}
|
||||
|
||||
.p-bubblegum-700 {
|
||||
background: #bc245d;
|
||||
}
|
||||
|
||||
.p-bubblegum-900 {
|
||||
background: #910e38;
|
||||
}
|
||||
|
||||
.p-cocoa {
|
||||
background: #715344;
|
||||
}
|
||||
|
||||
.p-cocoa-100 {
|
||||
background: #a3907c;
|
||||
}
|
||||
|
||||
.p-cocoa-300 {
|
||||
background: #8a715e;
|
||||
}
|
||||
|
||||
.p-cocoa-500 {
|
||||
background: #715344;
|
||||
}
|
||||
|
||||
.p-cocoa-700 {
|
||||
background: #57392d;
|
||||
}
|
||||
|
||||
.p-cocoa-900 {
|
||||
background: #3d211b;
|
||||
}
|
||||
|
||||
.p-silver {
|
||||
background: #abacae;
|
||||
}
|
||||
|
||||
.p-silver-100 {
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.p-silver-300 {
|
||||
background: #d4d4d4;
|
||||
}
|
||||
|
||||
.p-silver-500 {
|
||||
background: #abacae;
|
||||
}
|
||||
|
||||
.p-silver-700 {
|
||||
background: #7e8087;
|
||||
}
|
||||
|
||||
.p-silver-900 {
|
||||
background: #555761;
|
||||
}
|
||||
|
||||
.p-slate {
|
||||
background: #485a6c;
|
||||
}
|
||||
|
||||
.p-slate-100 {
|
||||
background: #95a3ab;
|
||||
}
|
||||
|
||||
.p-slate-300 {
|
||||
background: #667885;
|
||||
}
|
||||
|
||||
.p-slate-500 {
|
||||
background: #485a6c;
|
||||
}
|
||||
|
||||
.p-slate-700 {
|
||||
background: #273445;
|
||||
}
|
||||
|
||||
.p-slate-900 {
|
||||
background: #0e141f;
|
||||
}
|
||||
|
||||
.p-dark {
|
||||
background: #333;
|
||||
}
|
||||
|
||||
.p-dark-100 {
|
||||
background: #666;
|
||||
/* hehe */
|
||||
}
|
||||
|
||||
.p-dark-300 {
|
||||
background: #4d4d4d;
|
||||
}
|
||||
|
||||
.p-dark-500 {
|
||||
background: #333;
|
||||
}
|
||||
|
||||
.p-dark-700 {
|
||||
background: #1a1a1a;
|
||||
}
|
||||
|
||||
.p-dark-900 {
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.p-white{
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.p-strawberry-color {
|
||||
color: #c6262e;
|
||||
}
|
||||
|
||||
.p-strawberry-100-color {
|
||||
color: #ff8c82;
|
||||
}
|
||||
|
||||
.p-strawberry-300-color {
|
||||
color: #ed5353;
|
||||
}
|
||||
|
||||
.p-strawberry-500-color {
|
||||
color: #c6262e;
|
||||
}
|
||||
|
||||
.p-strawberry-700-color {
|
||||
color: #a10705;
|
||||
}
|
||||
|
||||
.p-strawberry-900-color {
|
||||
color: #7a0000;
|
||||
}
|
||||
|
||||
.p-orange-color {
|
||||
color: #f37329;
|
||||
}
|
||||
|
||||
.p-orange-100-color {
|
||||
color: #ffc27d;
|
||||
}
|
||||
|
||||
.p-orange-300-color {
|
||||
color: #ffa154;
|
||||
}
|
||||
|
||||
.p-orange-500-color {
|
||||
color: #f37329;
|
||||
}
|
||||
|
||||
.p-orange-700-color {
|
||||
color: #cc3b02;
|
||||
}
|
||||
|
||||
.p-orange-900-color {
|
||||
color: #a62100;
|
||||
}
|
||||
|
||||
.p-banana-color {
|
||||
color: #f9c440;
|
||||
}
|
||||
|
||||
.p-banana-100-color {
|
||||
color: #fff394;
|
||||
}
|
||||
|
||||
.p-banana-300-color {
|
||||
color: #ffe16b;
|
||||
}
|
||||
|
||||
.p-banana-500-color {
|
||||
color: #f9c440;
|
||||
}
|
||||
|
||||
.p-banana-700-color {
|
||||
color: #d48e15;
|
||||
}
|
||||
|
||||
.p-banana-900-color {
|
||||
color: #ad5f00;
|
||||
}
|
||||
|
||||
.p-lime-color {
|
||||
color: #68b723;
|
||||
}
|
||||
|
||||
.p-lime-100-color {
|
||||
color: #d1ff82;
|
||||
}
|
||||
|
||||
.p-lime-300-color {
|
||||
color: #9bdb4d;
|
||||
}
|
||||
|
||||
.p-lime-500-color {
|
||||
color: #68b723;
|
||||
}
|
||||
|
||||
.p-lime-700-color {
|
||||
color: #3a9104;
|
||||
}
|
||||
|
||||
.p-lime-900-color {
|
||||
color: #206b00;
|
||||
}
|
||||
|
||||
.p-mint-color {
|
||||
color: #28bca3;
|
||||
}
|
||||
|
||||
.p-mint-100-color {
|
||||
color: #89ffdd;
|
||||
}
|
||||
|
||||
.p-mint-300-color {
|
||||
color: #43d6b5;
|
||||
}
|
||||
|
||||
.p-mint-500-color {
|
||||
color: #28bca3;
|
||||
}
|
||||
|
||||
.p-mint-700-color {
|
||||
color: #0e9a83;
|
||||
}
|
||||
|
||||
.p-mint-900-color {
|
||||
color: #007367;
|
||||
}
|
||||
|
||||
.p-blueberry-color {
|
||||
color: #3689e6;
|
||||
}
|
||||
|
||||
.p-blueberry-100-color {
|
||||
color: #8cd5ff;
|
||||
}
|
||||
|
||||
.p-blueberry-300-color {
|
||||
color: #64baff;
|
||||
}
|
||||
|
||||
.p-blueberry-500-color {
|
||||
color: #3689e6;
|
||||
}
|
||||
|
||||
.p-blueberry-700-color {
|
||||
color: #0d52bf;
|
||||
}
|
||||
|
||||
.p-blueberry-900-color {
|
||||
color: #002e99;
|
||||
}
|
||||
|
||||
.p-grape-color {
|
||||
color: #a56de2;
|
||||
}
|
||||
|
||||
.p-grape-100-color {
|
||||
color: #e4c6fa;
|
||||
}
|
||||
|
||||
.p-grape-300-color {
|
||||
color: #cd9ef7;
|
||||
}
|
||||
|
||||
.p-grape-500-color {
|
||||
color: #a56de2;
|
||||
}
|
||||
|
||||
.p-grape-700-color {
|
||||
color: #7239b3;
|
||||
}
|
||||
|
||||
.p-grape-900-color {
|
||||
color: #452981;
|
||||
}
|
||||
|
||||
.p-bubblegum-color {
|
||||
color: #de3e80;
|
||||
}
|
||||
|
||||
.p-bubblegum-100-color {
|
||||
color: #fe9ab8;
|
||||
}
|
||||
|
||||
.p-bubblegum-300-color {
|
||||
color: #f4679d;
|
||||
}
|
||||
|
||||
.p-bubblegum-500-color {
|
||||
color: #de3e80;
|
||||
}
|
||||
|
||||
.p-bubblegum-700-color {
|
||||
color: #bc245d;
|
||||
}
|
||||
|
||||
.p-bubblegum-900-color {
|
||||
color: #910e38;
|
||||
}
|
||||
|
||||
.p-cocoa-color {
|
||||
color: #715344;
|
||||
}
|
||||
|
||||
.p-cocoa-100-color {
|
||||
color: #a3907c;
|
||||
}
|
||||
|
||||
.p-cocoa-300-color {
|
||||
color: #8a715e;
|
||||
}
|
||||
|
||||
.p-cocoa-500-color {
|
||||
color: #715344;
|
||||
}
|
||||
|
||||
.p-cocoa-700-color {
|
||||
color: #57392d;
|
||||
}
|
||||
|
||||
.p-cocoa-900-color {
|
||||
color: #3d211b;
|
||||
}
|
||||
|
||||
.p-silver-color {
|
||||
color: #abacae;
|
||||
}
|
||||
|
||||
.p-silver-100-color {
|
||||
color: #fafafa;
|
||||
}
|
||||
|
||||
.p-silver-300-color {
|
||||
color: #d4d4d4;
|
||||
}
|
||||
|
||||
.p-silver-500-color {
|
||||
color: #abacae;
|
||||
}
|
||||
|
||||
.p-silver-700-color {
|
||||
color: #7e8087;
|
||||
}
|
||||
|
||||
.p-silver-900-color {
|
||||
color: #555761;
|
||||
}
|
||||
|
||||
.p-slate-color {
|
||||
color: #485a6c;
|
||||
}
|
||||
|
||||
.p-slate-100-color {
|
||||
color: #95a3ab;
|
||||
}
|
||||
|
||||
.p-slate-300-color {
|
||||
color: #667885;
|
||||
}
|
||||
|
||||
.p-slate-500-color {
|
||||
color: #485a6c;
|
||||
}
|
||||
|
||||
.p-slate-700-color {
|
||||
color: #273445;
|
||||
}
|
||||
|
||||
.p-slate-900-color {
|
||||
color: #0e141f;
|
||||
}
|
||||
|
||||
.p-dark-color {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.p-dark-100-color {
|
||||
color: #666;
|
||||
/* hehe */
|
||||
}
|
||||
|
||||
.p-dark-300-color {
|
||||
color: #4d4d4d;
|
||||
}
|
||||
|
||||
.p-dark-500-color {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.p-dark-700-color {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
|
||||
.p-dark-900-color {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.p-white-color{
|
||||
color: #fff;
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
/* Puppertino dark_mode placeholder - local vendored */
|
||||
509
v3/examples/android/frontend/public/puppertino/css/forms.css
Normal file
|
|
@ -0,0 +1,509 @@
|
|||
:root {
|
||||
--primary-col:linear-gradient(to bottom, #4fc5fa 0%,#0f75f5 100%);
|
||||
--primary-col-ac:#0f75f5;
|
||||
--bg-color-input:#fff;
|
||||
|
||||
--p-checkbox-gradient: linear-gradient(180deg, #4B91F7 0%, #367AF6 100%);
|
||||
--p-checkbox-border: rgba(0, 0, 0, 0.2);
|
||||
--p-checkbox-border-active: rgba(0, 0, 0, 0.12);
|
||||
--p-checkbox-bg: transparent;
|
||||
--p-checkbox-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.15), inset 0px 0px 2px rgba(0, 0, 0, 0.10);
|
||||
|
||||
--p-input-bg:#fff;
|
||||
--p-input-color: rgba(0,0,0,.85);
|
||||
--p-input-color-plac:rgba(0,0,0,0.25);
|
||||
|
||||
--p-input-color:#808080;
|
||||
--p-input-bd:rgba(0,0,0,0.15);
|
||||
--bg-hover-color:#f9f9f9;
|
||||
--bg-front-col:#000;
|
||||
--invalid-color:#d6513c;
|
||||
--valid-color:#94d63c;
|
||||
}
|
||||
|
||||
.p-dark-mode{
|
||||
--p-checkbox-bg: linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.13) 100%);
|
||||
--p-checkbox-shadow: 0px 0px 1px rgba(0, 0, 0, 0.25), inset 0px 0.5px 0px rgba(255, 255, 255, 0.15);
|
||||
--p-checkbox-border: rgba(0, 0, 0, 0);
|
||||
|
||||
--p-checkbox-gradient: linear-gradient(180deg, #3168DD 0%, #2C5FC8 100%);
|
||||
--p-checkbox-border-active: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.p-form-select {
|
||||
border-radius: 5px;
|
||||
display: inline-block;
|
||||
font-family: -apple-system, "Inter", sans-serif;
|
||||
margin: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.p-form-select > select:focus{
|
||||
outline: 2px solid #64baff;
|
||||
}
|
||||
|
||||
.p-form-select::after {
|
||||
background: url("data:image/svg+xml,%3Csvg fill='none' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 12'%3E%3Cpath d='M.288 4.117 3.16 1.18c.168-.168.336-.246.54-.246a.731.731 0 0 1 .538.246L7.108 4.12c.125.121.184.27.184.45 0 .359-.293.656-.648.656a.655.655 0 0 1-.48-.211L3.701 2.465l-2.469 2.55a.664.664 0 0 1-.48.212.656.656 0 0 1-.465-1.11Zm3.41 7.324a.73.73 0 0 0 .54-.246l2.87-2.941a.601.601 0 0 0 .184-.45.656.656 0 0 0-.648-.656.677.677 0 0 0-.48.211L3.701 9.91 1.233 7.36a.68.68 0 0 0-.48-.212.656.656 0 0 0-.465 1.11l2.871 2.937c.172.168.336.246.54.246Z' fill='white' style='mix-blend-mode:luminosity'/%3E%3C/svg%3E"), #017AFF;
|
||||
background-size: 100% 75%;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
border-radius: 5px;
|
||||
bottom: 0;
|
||||
content: "";
|
||||
display: block;
|
||||
height: 80%;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
right: 3%;
|
||||
top: 10%;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.p-form-select > select {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
background: var(--p-input-bg);
|
||||
border: 1px solid var(--p-input-bd);
|
||||
border-radius: 5px;
|
||||
font-size: 14px;
|
||||
margin: 0;
|
||||
outline: none;
|
||||
padding: 5px 35px 5px 10px;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
color: var(--p-input-color);
|
||||
}
|
||||
|
||||
.p-form-text:invalid,
|
||||
.p-form-text-alt:invalid{
|
||||
border-color: var(--invalid-color);
|
||||
}
|
||||
|
||||
.p-form-text:valid,
|
||||
.p-form-text-alt:valid{
|
||||
border-color: var(--valid-color);
|
||||
}
|
||||
|
||||
.p-form-text:placeholder-shown,
|
||||
.p-form-text-alt:placeholder-shown{
|
||||
border-color: var(--p-input-bd);
|
||||
}
|
||||
|
||||
.p-form-text {
|
||||
color: var(--p-input-color);
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
background: var(--p-input-bg);
|
||||
border: 1px solid var(--p-input-bd);
|
||||
border-radius: 5px;
|
||||
font-family: -apple-system, "Inter", sans-serif;
|
||||
font-size: 13px;
|
||||
margin: 10px;
|
||||
outline: 0;
|
||||
padding: 3px 7px;
|
||||
resize: none;
|
||||
transition: border-color 200ms;
|
||||
box-shadow: 0px 0.5px 2.5px rgba(0,0,0,.3), 0px 0px 0px rgba(0,0,0,.1);
|
||||
}
|
||||
|
||||
.p-form-text-alt {
|
||||
color: var(--p-input-color);
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
box-shadow: none;
|
||||
background: var(--p-input-bg);
|
||||
border: 0px;
|
||||
border-bottom: 2px solid var(--p-input-bd);
|
||||
padding: 10px;
|
||||
border-top-left-radius: 3px;
|
||||
border-top-right-radius: 3px;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.p-form-text-alt::placeholder,
|
||||
.p-form-text::placeholder
|
||||
{
|
||||
color: var(--p-input-color-plac);
|
||||
}
|
||||
|
||||
.p-form-text:active,
|
||||
.p-form-text:focus
|
||||
{
|
||||
outline: 3px solid rgb(0 122 255 / 50%);
|
||||
}
|
||||
|
||||
.p-form-text-alt:focus {
|
||||
outline: 0;
|
||||
outline: 3px solid rgb(0 122 255 / 50%);
|
||||
border-color: #3689e6;
|
||||
}
|
||||
|
||||
.p-form-no-validate:valid,
|
||||
.p-form-no-validate:invalid{
|
||||
border-color: var(--p-input-bd);
|
||||
color: var(--p-input-color)!important;
|
||||
}
|
||||
|
||||
.p-form-text:focus {
|
||||
border-color: rgb(0 122 255);
|
||||
}
|
||||
|
||||
textarea.p-form-text {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.p-form-truncated {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.p-form-text[type=password] {
|
||||
font-family: caption;
|
||||
}
|
||||
|
||||
.p-form-label,
|
||||
.p-form-radio-cont,
|
||||
.p-form-checkbox-cont,
|
||||
.p-form-label-inline {
|
||||
font-family: -apple-system, "Inter", sans-serif;
|
||||
}
|
||||
|
||||
.p-form-label, .p-form-label-inline {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.p-form-label{
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.p-form-label-inline {
|
||||
background: var(--p-input-bg);
|
||||
padding: 5px;
|
||||
border-bottom: 2px solid var(--p-input-bd);
|
||||
color: #656565;
|
||||
font-weight: 500;
|
||||
transition: .3s;
|
||||
}
|
||||
|
||||
.p-form-label-inline:focus-within {
|
||||
color: #3689e6;
|
||||
border-color: #3689e6;
|
||||
}
|
||||
|
||||
.p-form-label-inline > .p-form-text-alt {
|
||||
border-bottom: 0px;
|
||||
padding: 0;
|
||||
outline: 0;
|
||||
background: var(--p-input-bg);
|
||||
|
||||
}
|
||||
|
||||
.p-form-label-inline > .p-form-text-alt:-webkit-autofill{
|
||||
background: var(--p-input-bg);
|
||||
-webkit-box-shadow: 0 0 0 30px rgba(0,0,0,0) inset !important;
|
||||
}
|
||||
|
||||
.p-form-label-inline > .p-form-text-alt:invalid {
|
||||
color: var(--invalid-color);
|
||||
}
|
||||
|
||||
.p-form-label-inline > .p-form-text-alt:valid {
|
||||
color: #3689e6;
|
||||
}
|
||||
|
||||
.p-form-label-inline > .p-form-text-alt:focus{
|
||||
color: var(--p-input-color);
|
||||
}
|
||||
|
||||
.p-form-radio-cont,
|
||||
.p-form-checkbox-cont {
|
||||
align-items: center;
|
||||
display: inline-flex;
|
||||
cursor: pointer;
|
||||
margin: 0 10px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.p-form-radio-cont > input + span,
|
||||
.p-form-checkbox-cont > input + span {
|
||||
background: var(--p-input-bg);
|
||||
border: 1px solid var(--p-input-bd);
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
height: 20px;
|
||||
margin-right: 5px;
|
||||
position: relative;
|
||||
transition: 0.2s;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.p-form-radio-cont > input + span{
|
||||
box-shadow: inset 0px 1px 2px rgba(0,0,0,0.10), inset 0px 0px 2px rgba(0,0,0,0.10);
|
||||
}
|
||||
|
||||
.p-form-radio-cont > input:focus + span,
|
||||
.p-form-checkbox-cont > input:focus + span{
|
||||
outline: 3px solid rgb(0 122 255 / 50%);
|
||||
}
|
||||
|
||||
.p-form-radio-cont:hover > input + span{
|
||||
background: #f9f9f9;
|
||||
}
|
||||
|
||||
.p-form-radio-cont > input,
|
||||
.p-form-checkbox-cont > input {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.p-form-radio-cont > input + span::after {
|
||||
background: #fff;
|
||||
border-radius: 50%;
|
||||
content: "";
|
||||
display: block;
|
||||
height: 30%;
|
||||
left: calc(50% - 15%);
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: calc(50% - 15%);
|
||||
transform: scale(2);
|
||||
transition: opacity 0.2s, transform 0.3s;
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
.p-form-radio-cont > input:checked + span {
|
||||
background: #0f75f5;
|
||||
box-shadow: 0px 1px 2.5px 1px rgba(0, 122, 255, 0.24), inset 0px 0px 0px 0.5px rgba(0, 122, 255, 0.12);
|
||||
}
|
||||
|
||||
.p-form-radio-cont > input:checked + span::after {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.p-form-checkbox-cont > input + span {
|
||||
border-radius: 5px;
|
||||
box-shadow: var(--p-checkbox-shadow);
|
||||
border: 0.5px solid var(--p-checkbox-border);
|
||||
background: var(--p-checkbox-bg)
|
||||
}
|
||||
|
||||
.p-form-checkbox-cont > input:checked + span {
|
||||
background: var(--p-checkbox-gradient);
|
||||
border: 0.5px solid var(--p-checkbox-border-active);
|
||||
box-shadow: 0px 1px 2.5px rgba(0, 122, 255, 0.24), 0px 0px 0px 0.5px rgba(0, 122, 255, 0.12);
|
||||
}
|
||||
|
||||
.p-form-checkbox-cont > input + span::before{
|
||||
content: "";
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
left: 0%;
|
||||
top: 0%;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s;
|
||||
background-image: url("data:image/svg+xml,%3Csvg width='10' height='8' viewBox='0 0 10 8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.10791 7.81299C3.83545 7.81299 3.6084 7.70459 3.42676 7.48779L1.15918 4.74121C1.08008 4.65039 1.02441 4.5625 0.992188 4.47754C0.959961 4.39258 0.943848 4.30469 0.943848 4.21387C0.943848 4.00586 1.0127 3.83447 1.15039 3.69971C1.29102 3.56201 1.4668 3.49316 1.67773 3.49316C1.91211 3.49316 2.10693 3.58838 2.26221 3.77881L4.10791 6.04297L7.68066 0.368652C7.77148 0.230957 7.86523 0.134277 7.96191 0.0786133C8.06152 0.0200195 8.18311 -0.00927734 8.32666 -0.00927734C8.5376 -0.00927734 8.71191 0.0581055 8.84961 0.192871C8.9873 0.327637 9.05615 0.497559 9.05615 0.702637C9.05615 0.778809 9.04297 0.85791 9.0166 0.939941C8.99023 1.02197 8.94922 1.10693 8.89355 1.19482L4.80225 7.45703C4.64111 7.69434 4.40967 7.81299 4.10791 7.81299Z' fill='white'/%3E%3C/svg%3E%0A");
|
||||
background-size: 70%;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.p-form-checkbox-cont > input + span::after{
|
||||
content: '';
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
.p-form-checkbox-cont > input + span:active::after{
|
||||
border-radius: 5px;
|
||||
backdrop-filter: brightness(1.2);
|
||||
}
|
||||
|
||||
.p-form-checkbox-cont > input:checked + span::before{
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
||||
.p-form-checkbox-cont > input[disabled] + span,
|
||||
.p-form-radio-cont > input[disabled] ~ span
|
||||
{
|
||||
opacity: .7;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.p-form-button {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
background: #fff;
|
||||
border: 1px solid var(--p-input-bd);
|
||||
border-radius: 5px;
|
||||
color: #333230;
|
||||
display: inline-block;
|
||||
font-size: 17px;
|
||||
margin: 10px;
|
||||
padding: 5px 20px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.p-form-send {
|
||||
background: linear-gradient(to bottom, #4fc5fa 0%, #0f75f5 100%);
|
||||
border: 0;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.p-form-send:active {
|
||||
background: #0f75f5;
|
||||
}
|
||||
|
||||
.p-form-invalid,
|
||||
.p-form-invalid:placeholder-shown,
|
||||
.p-form-invalid:valid,
|
||||
.p-form-invalid:invalid {
|
||||
border-color: var(--invalid-color);
|
||||
}
|
||||
|
||||
.p-form-valid,
|
||||
.p-form-valid:placeholder-shown,
|
||||
.p-form-valid:valid,
|
||||
.p-form-valid:invalid {
|
||||
border-color: var(--valid-color);
|
||||
}
|
||||
|
||||
.p-form-switch {
|
||||
--width: 80px;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.p-form-switch > input:checked + span::after {
|
||||
left: calc(100% - calc(var(--width) / 1.8));
|
||||
}
|
||||
|
||||
.p-form-switch > input:checked + span {
|
||||
background: #60c35b;
|
||||
}
|
||||
|
||||
.p-form-switch > span {
|
||||
background: #e0e0e0;
|
||||
border: 1px solid #d3d3d3;
|
||||
border-radius: 500px;
|
||||
display: block;
|
||||
height: calc(var(--width) / 1.6);
|
||||
position: relative;
|
||||
transition: all 0.2s;
|
||||
width: var(--width);
|
||||
}
|
||||
|
||||
.p-form-switch > span::after {
|
||||
background: #f9f9f9;
|
||||
border-radius: 50%;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.101987);
|
||||
box-shadow: 0px 3px 1px rgba(0, 0, 0, 0.1), 0px 1px 1px rgba(0, 0, 0, 0.16), 0px 3px 8px rgba(0, 0, 0, 0.15);
|
||||
box-sizing: border-box;
|
||||
content: "";
|
||||
height: 84%;
|
||||
left: 3%;
|
||||
position: absolute;
|
||||
top: 6.5%;
|
||||
transition: all 0.2s;
|
||||
width: 52.5%;
|
||||
}
|
||||
|
||||
.p-form-switch > input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.p-chip input{
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.p-chip span{
|
||||
padding: .8rem 1rem;
|
||||
border-radius: 1.6rem;
|
||||
display:inline-block;
|
||||
margin:10px;
|
||||
background: #e4e4e4ca;
|
||||
color: #3689e6;
|
||||
transition: .3s;
|
||||
user-select: none;
|
||||
cursor:pointer;
|
||||
font-family: -apple-system, "Inter", sans-serif;
|
||||
font-size: 1rem;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
-moz-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.p-chip:focus-within span{
|
||||
outline: 2px solid #64baff;
|
||||
}
|
||||
|
||||
.p-chip svg{
|
||||
display:block;
|
||||
margin:auto;
|
||||
}
|
||||
|
||||
|
||||
.p-chip input:checked + span{
|
||||
background: #3689e6;
|
||||
color:#fff;
|
||||
}
|
||||
|
||||
.p-chip-outline span, .p-chip-outline-to-bg span{
|
||||
background: transparent;
|
||||
color: #3e3e3e;
|
||||
border: 1px solid currentColor;
|
||||
}
|
||||
|
||||
.p-chip-outline input:checked + span{
|
||||
background: transparent;
|
||||
color: #3689e6;
|
||||
}
|
||||
|
||||
.p-chip-radius-b span{
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.p-chip-dark span{
|
||||
color: #3e3e3e;
|
||||
}
|
||||
|
||||
.p-chip-dark input:checked + span{
|
||||
background: #3e3e3e;
|
||||
}
|
||||
|
||||
.p-chip input:disabled + span,
|
||||
.p-chip input[disabled] + span{
|
||||
opacity: .5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.p-chip-big span{
|
||||
font-size: 1.3rem;
|
||||
padding: 1.5rem;
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
.p-form-checkbox-cont[disabled],
|
||||
.p-form-label[disabled],
|
||||
.p-form-text[disabled],
|
||||
.p-form-text-alt[disabled],
|
||||
.p-form-select[disabled],
|
||||
.p-form-radio-cont[disabled]{
|
||||
filter: grayscale(1) opacity(.3);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
.p-large-title{
|
||||
font-size: 2.75rem;
|
||||
}
|
||||
|
||||
.p-layout h1 {
|
||||
font-size: 2.25rem;
|
||||
}
|
||||
|
||||
.p-layout h2 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
|
||||
.p-layout h3 {
|
||||
font-size: 1.58rem;
|
||||
}
|
||||
|
||||
.p-headline {
|
||||
font-size: 1.34rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.p-layout p {
|
||||
font-size: 1.15rem;
|
||||
}
|
||||
|
||||
.p-layout .link,
|
||||
.p-layout input {
|
||||
font-size: 0.813rem;
|
||||
}
|
||||
|
||||
.p-callout {
|
||||
font-size: 1.14rem;
|
||||
}
|
||||
|
||||
.p-subhead {
|
||||
font-size: 1.167rem;
|
||||
}
|
||||
|
||||
.p-footnote {
|
||||
font-size: 1.07rem;
|
||||
}
|
||||
|
||||
.p-caption {
|
||||
font-size: 0.91rem;
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
/* Puppertino modals placeholder - local vendored */
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
@import url('actions.css');
|
||||
@import url('buttons.css');
|
||||
@import url('layout.css');
|
||||
@import url('cards.css');
|
||||
@import url('color_palette.css');
|
||||
@import url('forms.css');
|
||||
@import url('modals.css');
|
||||
@import url('segmented-controls.css');
|
||||
@import url('shadows.css');
|
||||
@import url('tabs.css');
|
||||
@import url('dark_mode.css');
|
||||
|
|
@ -0,0 +1 @@
|
|||
/* Puppertino segmented-controls placeholder - local vendored */
|
||||
|
|
@ -0,0 +1 @@
|
|||
/* Puppertino shadows placeholder - local vendored */
|
||||
|
|
@ -0,0 +1 @@
|
|||
/* Puppertino tabs placeholder - local vendored */
|
||||
1774
v3/examples/android/frontend/public/puppertino/puppertino.css
Normal file
327
v3/examples/android/frontend/public/style.css
Normal file
|
|
@ -0,0 +1,327 @@
|
|||
:root {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial,
|
||||
sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
font-weight: 400;
|
||||
color-scheme: light dark;
|
||||
/* Desktop defaults (mobile overrides below) */
|
||||
--bg: #ffffff;
|
||||
--fg: #213547;
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
|
||||
/* Mobile bottom tabs layout (works on all themes) */
|
||||
.mobile-pane {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
max-width: 520px;
|
||||
height: 70vh; /* fixed-height main screen */
|
||||
border-radius: 12px;
|
||||
}
|
||||
.mobile-pane .p-mobile-tabs-content {
|
||||
position: relative;
|
||||
flex: 1 1 auto;
|
||||
overflow: hidden; /* contain panels */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.p-mobile-tabs-content .p-mobile-tabs--content {
|
||||
display: none;
|
||||
overflow: auto; /* scroll inside content area */
|
||||
-webkit-overflow-scrolling: touch;
|
||||
padding: 8px 8px 16px;
|
||||
}
|
||||
.p-mobile-tabs-content .p-mobile-tabs--content.active { display: block; }
|
||||
|
||||
*, *::before, *::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Prefer system fonts on mobile; remove custom font to reduce bundle size */
|
||||
|
||||
h3 {
|
||||
font-size: 3em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
/* Remove generic button styling to allow Puppertino .btn to control buttons */
|
||||
|
||||
.result {
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow-x: hidden; /* prevent horizontal overflow */
|
||||
overflow-y: auto; /* allow vertical scroll if needed */
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 320px;
|
||||
/* Use small viewport units to avoid iOS Safari URL bar issues */
|
||||
min-height: 100svh;
|
||||
height: auto; /* avoid forcing overflow */
|
||||
/* Equal responsive spacing top & bottom */
|
||||
padding-block: clamp(8px, 4vh, 48px);
|
||||
color: var(--fg);
|
||||
background-color: var(--bg);
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
/* Responsive spacing between elements */
|
||||
gap: clamp(8px, 2vh, 24px);
|
||||
width: 100%;
|
||||
max-width: 480px;
|
||||
padding-inline: 16px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
/* Responsive heading size */
|
||||
font-size: clamp(1.6rem, 6vw, 3.2rem);
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
#app {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
/* Responsive inner padding: horizontal only, no extra top/bottom */
|
||||
padding: 0 clamp(12px, 4vw, 32px);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
/* Consistent visual size across images: fix height, auto width */
|
||||
height: clamp(80px, 18vh, 140px);
|
||||
width: auto;
|
||||
max-width: 80vw;
|
||||
padding: 0.5em;
|
||||
will-change: filter;
|
||||
}
|
||||
|
||||
.logo:hover {
|
||||
filter: drop-shadow(0 0 2em #e80000aa);
|
||||
}
|
||||
|
||||
.logo.vanilla:hover {
|
||||
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;
|
||||
}
|
||||
|
||||
/* Tabs: default hide panels, show one matching the checked radio */
|
||||
.tabs .tabs-content .tab-panel { display: none; }
|
||||
.tabs input#tab-js:checked ~ .tabs-content [data-tab="tab-js"] { display: block; }
|
||||
.tabs input#tab-go:checked ~ .tabs-content [data-tab="tab-go"] { display: block; }
|
||||
|
||||
/* Sticky tabs header */
|
||||
.tabs .tabs-header {
|
||||
position: sticky;
|
||||
top: env(safe-area-inset-top);
|
||||
z-index: 5;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 8px;
|
||||
padding: 8px 0;
|
||||
background: var(--bg);
|
||||
backdrop-filter: saturate(1.2) blur(4px);
|
||||
}
|
||||
|
||||
/* Subtle divider under sticky header */
|
||||
.tabs .tabs-header::after {
|
||||
content: "";
|
||||
grid-column: 1 / -1;
|
||||
height: 1px;
|
||||
background: rgba(0,0,0,0.08);
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
/* Mobile-specific light mode */
|
||||
@media (max-width: 768px) and (prefers-color-scheme: light) {
|
||||
:root {
|
||||
--fg: #213547;
|
||||
--bg: #ffffff;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #747bff;
|
||||
}
|
||||
|
||||
/* allow Puppertino to style .btn */
|
||||
|
||||
.input-box .input {
|
||||
color: #111827;
|
||||
background-color: #f3f4f6;
|
||||
border: 1px solid #e5e7eb; /* show border in light mode */
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
border-color: #d1d5db; /* slate-300 */
|
||||
}
|
||||
|
||||
.input-box .input:focus {
|
||||
border-color: #9ca3af; /* gray-400 */
|
||||
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15); /* subtle focus ring */
|
||||
}
|
||||
}
|
||||
|
||||
/* let Puppertino handle .btn hover */
|
||||
|
||||
.input-box .input {
|
||||
border: 1px solid transparent; /* default; themed in media queries */
|
||||
border-radius: 8px;
|
||||
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 {
|
||||
background-color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
.input-box .input:focus {
|
||||
background-color: rgba(255, 255, 255, 1);
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
/* Mobile-specific dark mode */
|
||||
@media (max-width: 768px) and (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
color: rgba(255, 255, 255, 0.88);
|
||||
--fg: rgba(255, 255, 255, 0.88);
|
||||
--bg: #0f1115; /* deep dark background */
|
||||
}
|
||||
|
||||
a {
|
||||
color: #8ea2ff;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #aab6ff;
|
||||
}
|
||||
|
||||
/* allow Puppertino to style .btn in dark mode */
|
||||
|
||||
.input-box .input {
|
||||
background-color: #111827; /* gray-900 */
|
||||
color: #e5e7eb;
|
||||
caret-color: #ffffff;
|
||||
border: 1px solid #374151; /* slate-700 */
|
||||
}
|
||||
|
||||
.input-box .input:hover,
|
||||
.input-box .input:focus {
|
||||
background-color: #0b1220;
|
||||
border-color: #4b5563; /* slate-600 */
|
||||
}
|
||||
|
||||
/* allow Puppertino to handle active state */
|
||||
}
|
||||
|
||||
/* Mobile baseline overrides (apply to both light and dark) */
|
||||
@media (max-width: 768px) {
|
||||
/* Prevent iOS zoom on focus */
|
||||
input, textarea, select, button { font-size: 16px; }
|
||||
|
||||
/* Make layout vertical and scrollable */
|
||||
html, body {
|
||||
height: auto;
|
||||
min-height: 100svh;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
body {
|
||||
padding-top: env(safe-area-inset-top);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
position: static;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 520px; /* allow a bit wider on phones */
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
/* Stack controls vertically with full-width tap targets */
|
||||
.input-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.input-box .input,
|
||||
.input,
|
||||
button,
|
||||
.p-btn {
|
||||
width: 100%;
|
||||
min-height: 44px; /* comfortable touch target */
|
||||
}
|
||||
|
||||
/* Tabs vertical and full-width */
|
||||
.tabs {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 8px;
|
||||
}
|
||||
.tabs .p-btn { width: 100%; }
|
||||
|
||||
/* Cap device info height for readability */
|
||||
#deviceInfo {
|
||||
max-height: 30vh;
|
||||
overflow: auto;
|
||||
padding: 8px;
|
||||
border-radius: 8px;
|
||||
background: rgba(0,0,0,0.04);
|
||||
}
|
||||
}
|
||||
BIN
v3/examples/android/frontend/public/wails.png
Normal file
|
After Width: | Height: | Size: 8.8 KiB |
11
v3/examples/android/frontend/vite.config.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { defineConfig } from 'vite';
|
||||
import path from 'path';
|
||||
|
||||
export default defineConfig({
|
||||
resolve: {
|
||||
alias: {
|
||||
// Use the local repo runtime sources instead of the published package
|
||||
'@wailsio/runtime': path.resolve(__dirname, '../../../internal/runtime/desktop/@wailsio/runtime/src/index.ts'),
|
||||
},
|
||||
},
|
||||
});
|
||||
52
v3/examples/android/go.mod
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
module changeme
|
||||
|
||||
go 1.24.0
|
||||
|
||||
toolchain go1.24.6
|
||||
|
||||
require github.com/wailsapp/wails/v3 v3.0.0-dev
|
||||
|
||||
require (
|
||||
dario.cat/mergo v1.0.1 // 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 => ../../
|
||||
146
v3/examples/android/go.sum
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
||||
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw=
|
||||
github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
|
||||
github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78=
|
||||
github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY=
|
||||
github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0=
|
||||
github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk=
|
||||
github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
|
||||
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I=
|
||||
github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||
github.com/elazarl/goproxy v1.4.0 h1:4GyuSbFa+s26+3rmYNSuUVsx+HgPrV1bk1jXI0l9wjM=
|
||||
github.com/elazarl/goproxy v1.4.0/go.mod h1:X/5W/t+gzDyLfHW4DrMdpjqYjpXsURlBt9lpBDxZZZQ=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
||||
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
||||
github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
|
||||
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||
github.com/go-git/go-git/v5 v5.13.2 h1:7O7xvsK7K+rZPKW6AQR1YyNhfywkv7B8/FsP3ki6Zv0=
|
||||
github.com/go-git/go-git/v5 v5.13.2/go.mod h1:hWdW5P4YZRjmpGHwRH2v3zkWcNl6HeXaXQEMGb3NJ9A=
|
||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
|
||||
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
|
||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A=
|
||||
github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU=
|
||||
github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M=
|
||||
github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI=
|
||||
github.com/lmittmann/tint v1.0.7 h1:D/0OqWZ0YOGZ6AyC+5Y2kD8PBEzBk6rFHVSfOqCkF9Y=
|
||||
github.com/lmittmann/tint v1.0.7/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
|
||||
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
|
||||
github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ=
|
||||
github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
|
||||
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
|
||||
github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4=
|
||||
github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew=
|
||||
github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8=
|
||||
github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/wailsapp/go-webview2 v1.0.21 h1:k3dtoZU4KCoN/AEIbWiPln3P2661GtA2oEgA2Pb+maA=
|
||||
github.com/wailsapp/go-webview2 v1.0.21/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc=
|
||||
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
|
||||
github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac h1:l5+whBCLH3iH2ZNHYLbAe58bo7yrN4mVcnkHDYz5vvs=
|
||||
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac/go.mod h1:hH+7mtFmImwwcMvScyxUhjuVHR3HGaDPMn9rMSUUbxo=
|
||||
golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
||||
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
|
||||
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
7
v3/examples/android/greetservice.go
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
package main
|
||||
|
||||
type GreetService struct{}
|
||||
|
||||
func (g *GreetService) Greet(name string) string {
|
||||
return "Hello " + name + "!"
|
||||
}
|
||||
73
v3/examples/android/main.go
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"embed"
|
||||
_ "embed"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
)
|
||||
|
||||
// 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() {
|
||||
|
||||
// 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.
|
||||
app := application.New(application.Options{
|
||||
Name: "android",
|
||||
Description: "A demo of using raw HTML & CSS",
|
||||
Services: []application.Service{
|
||||
application.NewService(&GreetService{}),
|
||||
},
|
||||
Assets: application.AssetOptions{
|
||||
Handler: application.AssetFileServerFS(assets),
|
||||
},
|
||||
Mac: application.MacOptions{
|
||||
ApplicationShouldTerminateAfterLastWindowClosed: true,
|
||||
},
|
||||
Android: application.AndroidOptions{
|
||||
// Android-specific options will go here
|
||||
},
|
||||
})
|
||||
|
||||
// Create a new window with the necessary options.
|
||||
// 'Title' is the title of the window.
|
||||
// 'BackgroundColour' is the background colour of the window.
|
||||
// 'URL' is the URL that will be loaded into the webview.
|
||||
app.Window.NewWithOptions(application.WebviewWindowOptions{
|
||||
Title: "Window 1",
|
||||
BackgroundColour: application.NewRGB(27, 38, 54),
|
||||
URL: "/",
|
||||
})
|
||||
|
||||
// Create a goroutine that emits an event containing the current time every second.
|
||||
// The frontend can listen to this event and update the UI accordingly.
|
||||
go func() {
|
||||
for {
|
||||
now := time.Now().Format(time.RFC1123)
|
||||
app.Event.Emit("time", now)
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}()
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
11
v3/examples/android/main_android.go
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
//go:build android
|
||||
|
||||
package main
|
||||
|
||||
import "github.com/wailsapp/wails/v3/pkg/application"
|
||||
|
||||
func init() {
|
||||
// Register main function to be called when the Android app initializes
|
||||
// This is necessary because in c-shared build mode, main() is not automatically called
|
||||
application.RegisterAndroidMain(main)
|
||||
}
|
||||
12
v3/internal/assetserver/assetserver_android.go
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
//go:build android
|
||||
|
||||
package assetserver
|
||||
|
||||
import "net/url"
|
||||
|
||||
// Android uses https://wails.localhost as the base URL
|
||||
// This matches the WebViewAssetLoader domain configuration
|
||||
var baseURL = url.URL{
|
||||
Scheme: "https",
|
||||
Host: "wails.localhost",
|
||||
}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
//go:build linux && !android
|
||||
|
||||
package assetserver
|
||||
|
||||
import "net/url"
|
||||
|
|
|
|||
102
v3/internal/assetserver/webview/request_android.go
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
//go:build android
|
||||
|
||||
package webview
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Request interface for Android asset requests
|
||||
// On Android, requests are handled via JNI from Java's WebViewAssetLoader
|
||||
|
||||
// androidRequest implements the Request interface for Android
|
||||
type androidRequest struct {
|
||||
url string
|
||||
method string
|
||||
headers http.Header
|
||||
body io.ReadCloser
|
||||
rw *androidResponseWriter
|
||||
}
|
||||
|
||||
// NewRequestFromJNI creates a new request from JNI parameters
|
||||
func NewRequestFromJNI(url string, method string, headersJSON string) Request {
|
||||
return &androidRequest{
|
||||
url: url,
|
||||
method: method,
|
||||
headers: http.Header{},
|
||||
body: http.NoBody,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *androidRequest) URL() (string, error) {
|
||||
return r.url, nil
|
||||
}
|
||||
|
||||
func (r *androidRequest) Method() (string, error) {
|
||||
return r.method, nil
|
||||
}
|
||||
|
||||
func (r *androidRequest) Header() (http.Header, error) {
|
||||
return r.headers, nil
|
||||
}
|
||||
|
||||
func (r *androidRequest) Body() (io.ReadCloser, error) {
|
||||
return r.body, nil
|
||||
}
|
||||
|
||||
func (r *androidRequest) Response() ResponseWriter {
|
||||
if r.rw == nil {
|
||||
r.rw = &androidResponseWriter{}
|
||||
}
|
||||
return r.rw
|
||||
}
|
||||
|
||||
func (r *androidRequest) Close() error {
|
||||
if r.body != nil {
|
||||
return r.body.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// androidResponseWriter implements ResponseWriter for Android
|
||||
type androidResponseWriter struct {
|
||||
statusCode int
|
||||
headers http.Header
|
||||
body bytes.Buffer
|
||||
finished bool
|
||||
}
|
||||
|
||||
func (w *androidResponseWriter) Header() http.Header {
|
||||
if w.headers == nil {
|
||||
w.headers = http.Header{}
|
||||
}
|
||||
return w.headers
|
||||
}
|
||||
|
||||
func (w *androidResponseWriter) Write(data []byte) (int, error) {
|
||||
return w.body.Write(data)
|
||||
}
|
||||
|
||||
func (w *androidResponseWriter) WriteHeader(statusCode int) {
|
||||
w.statusCode = statusCode
|
||||
}
|
||||
|
||||
func (w *androidResponseWriter) Finish() error {
|
||||
w.finished = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// Code returns the HTTP status code of the response
|
||||
func (w *androidResponseWriter) Code() int {
|
||||
if w.statusCode == 0 {
|
||||
return 200
|
||||
}
|
||||
return w.statusCode
|
||||
}
|
||||
|
||||
// GetResponseData returns the response data for JNI
|
||||
func (w *androidResponseWriter) GetResponseData() []byte {
|
||||
return w.body.Bytes()
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
//go:build linux
|
||||
// +build linux
|
||||
//go:build linux && !android
|
||||
|
||||
package webview
|
||||
|
||||
|
|
|
|||